Merge branch 'master' into translate-c-userland

This commit is contained in:
hryx 2019-06-23 12:31:22 -07:00
commit c423697c78
No known key found for this signature in database
GPG Key ID: 6A2784E15D7D95D6
145 changed files with 88406 additions and 87564 deletions

View File

@ -6,7 +6,7 @@ if(NOT CMAKE_BUILD_TYPE)
endif()
if(NOT CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}" CACHE STRING
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}" CACHE STRING
"Directory to install zig to" FORCE)
endif()
@ -479,6 +479,7 @@ set(ZIG_STD_FILES
"crypto.zig"
"crypto/blake2.zig"
"crypto/chacha20.zig"
"crypto/gimli.zig"
"crypto/hmac.zig"
"crypto/md5.zig"
"crypto/poly1305.zig"
@ -6594,7 +6595,7 @@ set(ZIG_LIBCXX_FILES
if(MSVC)
set(MSVC_DIA_SDK_DIR "$ENV{VSINSTALLDIR}DIA SDK")
if (IS_DIRECTORY ${MSVC_DIA_SDK_DIR})
if(IS_DIRECTORY ${MSVC_DIA_SDK_DIR})
set(ZIG_DIA_GUIDS_LIB "${MSVC_DIA_SDK_DIR}/lib/amd64/diaguids.lib")
string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_DIA_GUIDS_LIB_ESCAPED "${ZIG_DIA_GUIDS_LIB}")
endif()
@ -6633,20 +6634,18 @@ set(EXE_CFLAGS "-std=c++11")
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
if(MSVC)
set(EXE_CFLAGS "${EXE_CFLAGS} /w")
elseif(MINGW)
set(EXE_CFLAGS "${EXE_CFLAGS} -Wall -Werror -Wno-error=format= -Wno-error=format -Wno-error=format-extra-args")
else()
set(EXE_CFLAGS "${EXE_CFLAGS} -Werror -Wall")
endif()
endif()
if(MSVC)
set(EXE_CFLAGS "${EXE_CFLAGS}")
set(EXE_CFLAGS "${EXE_CFLAGS}")
else()
set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
if(MINGW)
set(EXE_CFLAGS "${EXE_CFLAGS} -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")
endif()
set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
if(MINGW)
set(EXE_CFLAGS "${EXE_CFLAGS} -Wno-format")
endif()
endif()
set(OPTIMIZED_C_FLAGS "-std=c99 -O3")

View File

@ -53,7 +53,7 @@ brew install cmake llvm@8
brew outdated llvm@8 || brew upgrade llvm@8
mkdir build
cd build
cmake .. -DCMAKE_PREFIX_PATH=/usr/local/Cellar/llvm/8.0.0
cmake .. -DCMAKE_PREFIX_PATH=/usr/local/Cellar/llvm/8.0.0_1
make install
```

View File

@ -18,10 +18,10 @@ pub fn build(b: *Builder) !void {
const rel_zig_exe = try fs.path.relative(b.allocator, b.build_root, b.zig_exe);
const langref_out_path = fs.path.join(
b.allocator,
[][]const u8{ b.cache_root, "langref.html" },
[_][]const u8{ b.cache_root, "langref.html" },
) catch unreachable;
var docgen_cmd = docgen_exe.run();
docgen_cmd.addArgs([][]const u8{
docgen_cmd.addArgs([_][]const u8{
rel_zig_exe,
"doc" ++ fs.path.sep_str ++ "langref.html.in",
langref_out_path,
@ -34,7 +34,7 @@ pub fn build(b: *Builder) !void {
const test_step = b.step("test", "Run all the tests");
// find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library
const build_info = try b.exec([][]const u8{
const build_info = try b.exec([_][]const u8{
b.zig_exe,
"BUILD_INFO",
});
@ -55,7 +55,7 @@ pub fn build(b: *Builder) !void {
var test_stage2 = b.addTest("src-self-hosted/test.zig");
test_stage2.setBuildMode(builtin.Mode.Debug);
const fmt_build_zig = b.addFmt([][]const u8{"build.zig"});
const fmt_build_zig = b.addFmt([_][]const u8{"build.zig"});
var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
exe.setBuildMode(mode);
@ -139,7 +139,7 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {
}
const lib_dir = fs.path.join(
b.allocator,
[][]const u8{ dep.prefix, "lib" },
[_][]const u8{ dep.prefix, "lib" },
) catch unreachable;
for (dep.system_libs.toSliceConst()) |lib| {
const static_bare_name = if (mem.eql(u8, lib, "curses"))
@ -148,7 +148,7 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {
b.fmt("lib{}.a", lib);
const static_lib_name = fs.path.join(
b.allocator,
[][]const u8{ lib_dir, static_bare_name },
[_][]const u8{ lib_dir, static_bare_name },
) catch unreachable;
const have_static = fileExists(static_lib_name) catch unreachable;
if (have_static) {
@ -175,7 +175,7 @@ fn fileExists(filename: []const u8) !bool {
fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void {
const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
lib_exe_obj.addObjectFile(fs.path.join(b.allocator, [][]const u8{
lib_exe_obj.addObjectFile(fs.path.join(b.allocator, [_][]const u8{
cmake_binary_dir,
"zig_cpp",
b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt()),
@ -191,22 +191,22 @@ const LibraryDep = struct {
};
fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
const shared_mode = try b.exec([][]const u8{ llvm_config_exe, "--shared-mode" });
const shared_mode = try b.exec([_][]const u8{ llvm_config_exe, "--shared-mode" });
const is_static = mem.startsWith(u8, shared_mode, "static");
const libs_output = if (is_static)
try b.exec([][]const u8{
try b.exec([_][]const u8{
llvm_config_exe,
"--libfiles",
"--system-libs",
})
else
try b.exec([][]const u8{
try b.exec([_][]const u8{
llvm_config_exe,
"--libs",
});
const includes_output = try b.exec([][]const u8{ llvm_config_exe, "--includedir" });
const libdir_output = try b.exec([][]const u8{ llvm_config_exe, "--libdir" });
const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" });
const includes_output = try b.exec([_][]const u8{ llvm_config_exe, "--includedir" });
const libdir_output = try b.exec([_][]const u8{ llvm_config_exe, "--libdir" });
const prefix_output = try b.exec([_][]const u8{ llvm_config_exe, "--prefix" });
var result = LibraryDep{
.prefix = mem.tokenize(prefix_output, " \r\n").next().?,
@ -255,10 +255,10 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
var it = mem.tokenize(stdlib_files, ";");
while (it.next()) |stdlib_file| {
const src_path = fs.path.join(b.allocator, [][]const u8{ "std", stdlib_file }) catch unreachable;
const src_path = fs.path.join(b.allocator, [_][]const u8{ "std", stdlib_file }) catch unreachable;
const dest_path = fs.path.join(
b.allocator,
[][]const u8{ "lib", "zig", "std", stdlib_file },
[_][]const u8{ "lib", "zig", "std", stdlib_file },
) catch unreachable;
b.installFile(src_path, dest_path);
}
@ -267,10 +267,10 @@ pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void {
var it = mem.tokenize(c_header_files, ";");
while (it.next()) |c_header_file| {
const src_path = fs.path.join(b.allocator, [][]const u8{ "c_headers", c_header_file }) catch unreachable;
const src_path = fs.path.join(b.allocator, [_][]const u8{ "c_headers", c_header_file }) catch unreachable;
const dest_path = fs.path.join(
b.allocator,
[][]const u8{ "lib", "zig", "include", c_header_file },
[_][]const u8{ "lib", "zig", "include", c_header_file },
) catch unreachable;
b.installFile(src_path, dest_path);
}
@ -354,7 +354,7 @@ fn addCxxKnownPath(
objname: []const u8,
errtxt: ?[]const u8,
) !void {
const path_padded = try b.exec([][]const u8{
const path_padded = try b.exec([_][]const u8{
ctx.cxx_compiler,
b.fmt("-print-file-name={}", objname),
});

View File

@ -16,10 +16,7 @@ const tmp_dir_name = "docgen_tmp";
const test_out_path = tmp_dir_name ++ fs.path.sep_str ++ "test" ++ exe_ext;
pub fn main() !void {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
defer arena.deinit();
const allocator = &arena.allocator;
@ -717,7 +714,7 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
return buf.toOwnedSlice();
}
const builtin_types = [][]const u8{
const builtin_types = [_][]const u8{
"f16", "f32", "f64", "f128", "c_longdouble", "c_short",
"c_ushort", "c_int", "c_uint", "c_long", "c_ulong", "c_longlong",
"c_ulonglong", "c_char", "c_void", "void", "bool", "isize",
@ -1016,7 +1013,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
const tmp_source_file_name = try fs.path.join(
allocator,
[][]const u8{ tmp_dir_name, name_plus_ext },
[_][]const u8{ tmp_dir_name, name_plus_ext },
);
try io.writeFile(tmp_source_file_name, trimmed_raw_source);
@ -1025,11 +1022,11 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
const tmp_bin_file_name = try fs.path.join(
allocator,
[][]const u8{ tmp_dir_name, name_plus_bin_ext },
[_][]const u8{ tmp_dir_name, name_plus_bin_ext },
);
var build_args = std.ArrayList([]const u8).init(allocator);
defer build_args.deinit();
try build_args.appendSlice([][]const u8{
try build_args.appendSlice([_][]const u8{
zig_exe,
"build-exe",
tmp_source_file_name,
@ -1060,7 +1057,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext);
const full_path_object = try fs.path.join(
allocator,
[][]const u8{ tmp_dir_name, name_with_ext },
[_][]const u8{ tmp_dir_name, name_with_ext },
);
try build_args.append("--object");
try build_args.append(full_path_object);
@ -1072,7 +1069,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
try out.print(" --library c");
}
if (code.target_str) |triple| {
try build_args.appendSlice([][]const u8{ "-target", triple });
try build_args.appendSlice([_][]const u8{ "-target", triple });
if (!code.is_inline) {
try out.print(" -target {}", triple);
}
@ -1123,7 +1120,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
}
}
const run_args = [][]const u8{tmp_bin_file_name};
const run_args = [_][]const u8{tmp_bin_file_name};
const result = if (expected_outcome == ExpectedOutcome.Fail) blk: {
const result = try ChildProcess.exec(allocator, run_args, null, &env_map, max_doc_file_size);
@ -1157,7 +1154,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([][]const u8{
try test_args.appendSlice([_][]const u8{
zig_exe,
"test",
tmp_source_file_name,
@ -1181,7 +1178,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
},
}
if (code.target_str) |triple| {
try test_args.appendSlice([][]const u8{ "-target", triple });
try test_args.appendSlice([_][]const u8{ "-target", triple });
try out.print(" -target {}", triple);
}
const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
@ -1193,7 +1190,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([][]const u8{
try test_args.appendSlice([_][]const u8{
zig_exe,
"test",
"--color",
@ -1252,7 +1249,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([][]const u8{
try test_args.appendSlice([_][]const u8{
zig_exe,
"test",
tmp_source_file_name,
@ -1314,7 +1311,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext);
const tmp_obj_file_name = try fs.path.join(
allocator,
[][]const u8{ tmp_dir_name, name_plus_obj_ext },
[_][]const u8{ tmp_dir_name, name_plus_obj_ext },
);
var build_args = std.ArrayList([]const u8).init(allocator);
defer build_args.deinit();
@ -1322,10 +1319,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", code.name);
const output_h_file_name = try fs.path.join(
allocator,
[][]const u8{ tmp_dir_name, name_plus_h_ext },
[_][]const u8{ tmp_dir_name, name_plus_h_ext },
);
try build_args.appendSlice([][]const u8{
try build_args.appendSlice([_][]const u8{
zig_exe,
"build-obj",
tmp_source_file_name,
@ -1364,7 +1361,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
}
if (code.target_str) |triple| {
try build_args.appendSlice([][]const u8{ "-target", triple });
try build_args.appendSlice([_][]const u8{ "-target", triple });
try out.print(" -target {}", triple);
}
@ -1411,7 +1408,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([][]const u8{
try test_args.appendSlice([_][]const u8{
zig_exe,
"build-lib",
tmp_source_file_name,
@ -1435,7 +1432,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
},
}
if (code.target_str) |triple| {
try test_args.appendSlice([][]const u8{ "-target", triple });
try test_args.appendSlice([_][]const u8{ "-target", triple });
try out.print(" -target {}", triple);
}
const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
@ -1476,7 +1473,7 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u
}
fn getBuiltinCode(allocator: *mem.Allocator, env_map: *std.BufMap, zig_exe: []const u8) ![]const u8 {
const result = try exec(allocator, env_map, []const []const u8{
const result = try exec(allocator, env_map, [_][]const u8{
zig_exe,
"builtin",
});

View File

@ -266,7 +266,7 @@ const Timestamp = struct {
{#code_end#}
<p>
Doc comments are only allowed in certain places; eventually, it will
become a compile error have a doc comment in an unexpected place, such as
become a compile error to have a doc comment in an unexpected place, such as
in the middle of an expression, or just before a non-doc comment.
</p>
{#header_close#}
@ -1530,10 +1530,10 @@ value == null{#endsyntax#}</pre>
</td>
<td>
<pre>{#syntax#}const mem = @import("std").mem;
const array1 = []u32{1,2};
const array2 = []u32{3,4};
const array1 = [_]u32{1,2};
const array2 = [_]u32{3,4};
const together = array1 ++ array2;
mem.eql(u32, together, []u32{1,2,3,4}){#endsyntax#}</pre>
mem.eql(u32, together, [_]u32{1,2,3,4}){#endsyntax#}</pre>
</td>
</tr>
<tr>
@ -1628,7 +1628,7 @@ const assert = @import("std").debug.assert;
const mem = @import("std").mem;
// array literal
const message = []u8{ 'h', 'e', 'l', 'l', 'o' };
const message = [_]u8{ 'h', 'e', 'l', 'l', 'o' };
// get the size of an array
comptime {
@ -1664,11 +1664,11 @@ test "modify an array" {
// array concatenation works if the values are known
// at compile time
const part_one = []i32{ 1, 2, 3, 4 };
const part_two = []i32{ 5, 6, 7, 8 };
const part_one = [_]i32{ 1, 2, 3, 4 };
const part_two = [_]i32{ 5, 6, 7, 8 };
const all_of_it = part_one ++ part_two;
comptime {
assert(mem.eql(i32, all_of_it, []i32{ 1, 2, 3, 4, 5, 6, 7, 8 }));
assert(mem.eql(i32, all_of_it, [_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }));
}
// remember that string literals are arrays
@ -1686,7 +1686,7 @@ comptime {
}
// initialize an array to zero
const all_zero = []u16{0} ** 10;
const all_zero = [_]u16{0} ** 10;
comptime {
assert(all_zero.len == 10);
@ -1715,7 +1715,7 @@ test "compile-time array initalization" {
}
// call a function to initialize an array
var more_points = []Point{makePoint(3)} ** 10;
var more_points = [_]Point{makePoint(3)} ** 10;
fn makePoint(x: i32) Point {
return Point{
.x = x,
@ -1819,7 +1819,7 @@ test "pointer array access" {
// Taking an address of an individual element gives a
// pointer to a single item. This kind of pointer
// does not support pointer arithmetic.
var array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
const ptr = &array[2];
assert(@typeOf(ptr) == *u8);
@ -1841,7 +1841,7 @@ test "pointer array access" {
const assert = @import("std").debug.assert;
test "pointer slicing" {
var array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
const slice = array[2..4];
assert(slice.len == 2);
@ -1922,7 +1922,7 @@ test "volatile" {
const assert = @import("std").debug.assert;
test "pointer casting" {
const bytes align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12 };
const bytes align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12 };
const u32_ptr = @ptrCast(*const u32, &bytes);
assert(u32_ptr.* == 0x12121212);
@ -2011,7 +2011,7 @@ test "function alignment" {
const assert = @import("std").debug.assert;
test "pointer alignment safety" {
var array align(4) = []u32{ 0x11111111, 0x11111111 };
var array align(4) = [_]u32{ 0x11111111, 0x11111111 };
const bytes = @sliceToBytes(array[0..]);
assert(foo(bytes) == 0x11111111);
}
@ -2048,7 +2048,7 @@ test "allowzero" {
const assert = @import("std").debug.assert;
test "basic slices" {
var array = []i32{ 1, 2, 3, 4 };
var array = [_]i32{ 1, 2, 3, 4 };
// A slice is a pointer and a length. The difference between an array and
// a slice is that the array's length is part of the type and known at
// compile-time, whereas the slice's length is known at runtime.
@ -2116,7 +2116,7 @@ test "slice pointer" {
test "slice widening" {
// Zig supports slice widening and slice narrowing. Cast a slice of u8
// to a slice of anything else, and Zig will perform the length conversion.
const array align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 };
const array align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 };
const slice = @bytesToSlice(u32, array[0..]);
assert(slice.len == 2);
assert(slice[0] == 0x12121212);
@ -3245,7 +3245,7 @@ fn typeNameLength(comptime T: type) usize {
const assert = @import("std").debug.assert;
test "for basics" {
const items = []i32 { 4, 5, 3, 4, 0 };
const items = [_]i32 { 4, 5, 3, 4, 0 };
var sum: i32 = 0;
// For loops iterate over slices and arrays.
@ -3275,7 +3275,7 @@ test "for basics" {
}
test "for reference" {
var items = []i32 { 3, 4, 2 };
var items = [_]i32 { 3, 4, 2 };
// Iterate over the slice by reference by
// specifying that the capture value is a pointer.
@ -3290,21 +3290,20 @@ test "for reference" {
test "for else" {
// For allows an else attached to it, the same as a while loop.
var items = []?i32 { 3, 4, null, 5 };
var items = [_]?i32 { 3, 4, null, 5 };
// For loops can also be used as expressions.
// Similar to while loops, when you break from a for loop, the else branch is not evaluated.
var sum: i32 = 0;
const result = for (items) |value| {
if (value == null) {
break 9;
} else {
if (value != null) {
sum += value.?;
}
} else blk: {
assert(sum == 7);
assert(sum == 12);
break :blk sum;
};
assert(result == 12);
}
{#code_end#}
{#header_open|Labeled for#}
@ -3316,8 +3315,8 @@ const assert = std.debug.assert;
test "nested break" {
var count: usize = 0;
outer: for ([]i32{ 1, 2, 3, 4, 5 }) |_| {
for ([]i32{ 1, 2, 3, 4, 5 }) |_| {
outer: for ([_]i32{ 1, 2, 3, 4, 5 }) |_| {
for ([_]i32{ 1, 2, 3, 4, 5 }) |_| {
count += 1;
break :outer;
}
@ -3327,8 +3326,8 @@ test "nested break" {
test "nested continue" {
var count: usize = 0;
outer: for ([]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }) |_| {
for ([]i32{ 1, 2, 3, 4, 5 }) |_| {
outer: for ([_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }) |_| {
for ([_]i32{ 1, 2, 3, 4, 5 }) |_| {
count += 1;
continue :outer;
}
@ -3350,7 +3349,7 @@ test "nested continue" {
const assert = @import("std").debug.assert;
test "inline for loop" {
const nums = []i32{2, 4, 6};
const nums = [_]i32{2, 4, 6};
var sum: usize = 0;
inline for (nums) |i| {
const T = switch (i) {
@ -3788,7 +3787,7 @@ test "fn reflection" {
However right now it is hard coded to be a {#syntax#}u16{#endsyntax#}. See <a href="https://github.com/ziglang/zig/issues/786">#768</a>.
</p>
<p>
You can {#link|implicitly cast|Implicit Casts#} an error from a subset to its superset:
You can {#link|implicitly cast|Implicit Casts#} an error from a subset to a superset:
</p>
{#code_begin|test#}
const std = @import("std");
@ -4699,7 +4698,7 @@ test "implicit casting to optionals wrapped in error union" {
{#code_end#}
{#header_close#}
{#header_open|Implicit Cast: Error Unions#}
<p>The the payload type of an {#link|Error Union Type#} as well as the {#link|Error Set Type#}
<p>The payload type of an {#link|Error Union Type#} as well as the {#link|Error Set Type#}
implicitly cast to the error union type:
</p>
{#code_begin|test#}
@ -4884,7 +4883,7 @@ test "peer type resolution: [0]u8 and []const u8" {
}
fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
if (a) {
return []const u8{};
return [_]u8{};
}
return slice[0..1];
@ -4905,7 +4904,7 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
}
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
if (a) {
return []u8{};
return [_]u8{};
}
return slice[0..1];
@ -4928,7 +4927,7 @@ test "peer type resolution: *const T and ?*T" {
<li>The {#link|Integers#} {#syntax#}u0{#endsyntax#} and {#syntax#}i0{#endsyntax#}.</li>
<li>{#link|Arrays#} and {#link|Vectors#} with len 0, or with an element type that is a zero bit type.</li>
<li>An {#link|enum#} with only 1 tag.</li>
<li>An {#link|struct#} with all fields being zero bit types.</li>
<li>A {#link|struct#} with all fields being zero bit types.</li>
<li>A {#link|union#} with only 1 field which is a zero bit type.</li>
<li>{#link|Pointers to Zero Bit Types#} are themselves zero bit types.</li>
</ul>
@ -4986,7 +4985,7 @@ fn eql_i32(a: i32, b: i32) bool {
return a == b;
}
{#code_end#}
<p>Note that this is different than using a dummy value for the hash map value.
<p>Note that this is different from using a dummy value for the hash map value.
By using {#syntax#}void{#endsyntax#} as the type of the value, the hash map entry type has no value field, and
thus the hash map takes up less space. Further, all the code that deals with storing and loading the
value is deleted, as seen above.
@ -5193,7 +5192,7 @@ const CmdFn = struct {
func: fn(i32) i32,
};
const cmd_fns = []CmdFn{
const cmd_fns = [_]CmdFn{
CmdFn {.name = "one", .func = one},
CmdFn {.name = "two", .func = two},
CmdFn {.name = "three", .func = three},
@ -5934,7 +5933,7 @@ async fn testAsyncSeq() void {
suspend;
seq('d');
}
var points = []u8{0} ** "abcdefg".len;
var points = [_]u8{0} ** "abcdefg".len;
var index: usize = 0;
fn seq(c: u8) void {
@ -6072,7 +6071,7 @@ async fn another() i32 {
return 1234;
}
var seq_points = []u8{0} ** "abcdefghi".len;
var seq_points = [_]u8{0} ** "abcdefghi".len;
var seq_index: usize = 0;
fn seq(c: u8) void {
@ -6226,7 +6225,7 @@ comptime {
{#header_close#}
{#header_open|@bitOffsetOf#}
<pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
<pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: []const u8) comptime_int{#endsyntax#}</pre>
<p>
Returns the bit offset of a field relative to its containing struct.
</p>
@ -6284,7 +6283,7 @@ comptime {
{#header_close#}
{#header_open|@byteOffsetOf#}
<pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
<pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: []const u8) comptime_int{#endsyntax#}</pre>
<p>
Returns the byte offset of a field relative to its containing struct.
</p>
@ -6649,7 +6648,7 @@ test "main" {
{#header_close#}
{#header_open|@export#}
<pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>
<pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) void{#endsyntax#}</pre>
<p>
Creates a symbol in the output object file.
</p>
@ -7392,7 +7391,7 @@ const std = @import("std");
const assert = std.debug.assert;
test "@This()" {
var items = []i32{ 1, 2, 3, 4 };
var items = [_]i32{ 1, 2, 3, 4 };
const list = List(i32){ .items = items[0..] };
assert(list.length() == 4);
}
@ -8306,7 +8305,7 @@ comptime {
<p>At runtime:</p>
{#code_begin|exe_err#}
pub fn main() !void {
var array align(4) = []u32{ 0x11111111, 0x11111111 };
var array align(4) = [_]u32{ 0x11111111, 0x11111111 };
const bytes = @sliceToBytes(array[0..]);
if (foo(bytes) != 0x11111111) return error.Wrong;
}
@ -8506,10 +8505,7 @@ fn concat(allocator: *Allocator, a: []const u8, b: []const u8) ![]u8 {
const std = @import("std");
pub fn main() !void {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
defer arena.deinit();
const allocator = &arena.allocator;
@ -8938,7 +8934,7 @@ pub fn build(b: *Builder) void {
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
const exe = b.addExecutable("test", null);
exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
exe.addCSourceFile("test.c", [_][]const u8{"-std=c99"});
exe.linkLibrary(lib);
exe.linkSystemLibrary("c");
@ -9003,7 +8999,7 @@ pub fn build(b: *Builder) void {
const obj = b.addObject("base64", "base64.zig");
const exe = b.addCExecutable("test");
exe.addCompileFlags([][]const u8 {
exe.addCompileFlags([_][]const u8 {
"-std=c99",
});
exe.addSourceFile("test.c");

View File

@ -4,7 +4,7 @@ pub fn build(b: *Builder) void {
const obj = b.addObject("base64", "base64.zig");
const exe = b.addExecutable("test", null);
exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
exe.addCSourceFile("test.c", [_][]const u8{"-std=c99"});
exe.addObject(obj);
exe.linkSystemLibrary("c");

View File

@ -4,7 +4,7 @@ pub fn build(b: *Builder) void {
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
const exe = b.addExecutable("test", null);
exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
exe.addCSourceFile("test.c", [_][]const u8{"-std=c99"});
exe.linkLibrary(lib);
exe.linkSystemLibrary("c");

View File

@ -707,8 +707,7 @@ const TargetToHash = std.HashMap(DestTarget, []const u8, DestTarget.hash, DestTa
const PathTable = std.AutoHashMap([]const u8, *TargetToHash);
pub fn main() !void {
var direct_allocator = std.heap.DirectAllocator.init();
var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
const allocator = &arena.allocator;
const args = try std.os.argsAlloc(allocator);
var search_paths = std.ArrayList([]const u8).init(allocator);

View File

@ -178,7 +178,7 @@ pub const Args = struct {
else => @panic("attempted to retrieve flag with wrong type"),
}
} else {
return []const []const u8{};
return [_][]const u8{};
}
}
};
@ -238,11 +238,11 @@ pub const Flag = struct {
};
test "parse arguments" {
const spec1 = comptime []const Flag{
const spec1 = comptime [_]Flag{
Flag.Bool("--help"),
Flag.Bool("--init"),
Flag.Arg1("--build-file"),
Flag.Option("--color", []const []const u8{
Flag.Option("--color", [_][]const u8{
"on",
"off",
"auto",
@ -252,7 +252,7 @@ test "parse arguments" {
Flag.ArgN("--library", 1),
};
const cliargs = []const []const u8{
const cliargs = [_][]const u8{
"build",
"--help",
"pos1",

View File

@ -15,7 +15,7 @@ pub const CInt = struct {
ULongLong,
};
pub const list = []CInt{
pub const list = [_]CInt{
CInt{
.id = Id.Short,
.zig_name = "c_short",

View File

@ -102,8 +102,8 @@ pub const ZigCompiler = struct {
/// Must be called only once, ever. Sets global state.
pub fn setLlvmArgv(allocator: *Allocator, llvm_argv: []const []const u8) !void {
if (llvm_argv.len != 0) {
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(allocator, [][]const []const u8{
[][]const u8{"zig (LLVM option parsing)"},
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(allocator, [_][]const []const u8{
[_][]const u8{"zig (LLVM option parsing)"},
llvm_argv,
});
defer c_compatible_args.deinit();
@ -160,7 +160,7 @@ pub const Compilation = struct {
/// it uses an optional pointer so that tombstone removals are possible
fn_link_set: event.Locked(FnLinkSet),
pub const FnLinkSet = std.LinkedList(?*Value.Fn);
pub const FnLinkSet = std.TailQueue(?*Value.Fn);
windows_subsystem_windows: bool,
windows_subsystem_console: bool,
@ -421,20 +421,20 @@ pub const Compilation = struct {
.strip = false,
.is_static = is_static,
.linker_rdynamic = false,
.clang_argv = [][]const u8{},
.lib_dirs = [][]const u8{},
.rpath_list = [][]const u8{},
.assembly_files = [][]const u8{},
.link_objects = [][]const u8{},
.clang_argv = [_][]const u8{},
.lib_dirs = [_][]const u8{},
.rpath_list = [_][]const u8{},
.assembly_files = [_][]const u8{},
.link_objects = [_][]const u8{},
.fn_link_set = event.Locked(FnLinkSet).init(loop, FnLinkSet.init()),
.windows_subsystem_windows = false,
.windows_subsystem_console = false,
.link_libs_list = undefined,
.libc_link_lib = null,
.err_color = errmsg.Color.Auto,
.darwin_frameworks = [][]const u8{},
.darwin_frameworks = [_][]const u8{},
.darwin_version_min = DarwinVersionMin.None,
.test_filters = [][]const u8{},
.test_filters = [_][]const u8{},
.test_name_prefix = null,
.emit_file_type = Emit.Binary,
.link_out_file = null,
@ -487,7 +487,7 @@ pub const Compilation = struct {
comp.name = try Buffer.init(comp.arena(), name);
comp.llvm_triple = try target.getTriple(comp.arena());
comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple);
comp.zig_std_dir = try std.fs.path.join(comp.arena(), [][]const u8{ zig_lib_dir, "std" });
comp.zig_std_dir = try std.fs.path.join(comp.arena(), [_][]const u8{ zig_lib_dir, "std" });
const opt_level = switch (build_mode) {
builtin.Mode.Debug => llvm.CodeGenLevelNone,
@ -1196,7 +1196,7 @@ pub const Compilation = struct {
const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix);
defer self.gpa().free(file_name);
const full_path = try std.fs.path.join(self.gpa(), [][]const u8{ tmp_dir, file_name[0..] });
const full_path = try std.fs.path.join(self.gpa(), [_][]const u8{ tmp_dir, file_name[0..] });
errdefer self.gpa().free(full_path);
return Buffer.fromOwnedSlice(self.gpa(), full_path);
@ -1217,7 +1217,7 @@ pub const Compilation = struct {
const zig_dir_path = try getZigDir(self.gpa());
defer self.gpa().free(zig_dir_path);
const tmp_dir = try std.fs.path.join(self.arena(), [][]const u8{ zig_dir_path, comp_dir_name[0..] });
const tmp_dir = try std.fs.path.join(self.arena(), [_][]const u8{ zig_dir_path, comp_dir_name[0..] });
try std.fs.makePath(self.gpa(), tmp_dir);
return tmp_dir;
}

View File

@ -837,12 +837,11 @@ test "error prereq - continuation expecting end-of-line" {
// - tokenize input, emit textual representation, and compare to expect
fn depTokenizer(input: []const u8, expect: []const u8) !void {
var direct_allocator = std.heap.DirectAllocator.init();
var arena_allocator = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
var arena_allocator = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
const arena = &arena_allocator.allocator;
defer arena_allocator.deinit();
var it = Tokenizer.init(&direct_allocator.allocator, input);
var it = Tokenizer.init(arena, input);
var buffer = try std.Buffer.initSize(arena, 0);
var i: usize = 0;
while (true) {
@ -900,7 +899,7 @@ fn printLabel(out: var, label: []const u8, bytes: []const u8) !void {
var i: usize = text.len;
const end = 79;
while (i < 79) : (i += 1) {
try out.write([]const u8{label[0]});
try out.write([_]u8{label[0]});
}
try out.write("\n");
}
@ -993,7 +992,7 @@ fn printHexValue(out: var, value: u64, width: u8) !void {
fn printCharValues(out: var, bytes: []const u8) !void {
for (bytes) |b| {
try out.write([]const u8{printable_char_tab[b]});
try out.write([_]u8{printable_char_tab[b]});
}
}
@ -1002,7 +1001,7 @@ fn printUnderstandableChar(out: var, char: u8) !void {
std.fmt.format(out.context, anyerror, out.output, "\\x{X2}", char) catch {};
} else {
try out.write("'");
try out.write([]const u8{printable_char_tab[char]});
try out.write([_]u8{printable_char_tab[char]});
try out.write("'");
}
}

View File

@ -8,10 +8,10 @@ const warn = std.debug.warn;
/// Caller must free result
pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 {
const test_zig_dir = try fs.path.join(allocator, [][]const u8{ test_path, "lib", "zig" });
const test_zig_dir = try fs.path.join(allocator, [_][]const u8{ test_path, "lib", "zig" });
errdefer allocator.free(test_zig_dir);
const test_index_file = try fs.path.join(allocator, [][]const u8{ test_zig_dir, "std", "std.zig" });
const test_index_file = try fs.path.join(allocator, [_][]const u8{ test_zig_dir, "std", "std.zig" });
defer allocator.free(test_index_file);
var file = try fs.File.openRead(test_index_file);

View File

@ -35,7 +35,7 @@ pub const LibCInstallation = struct {
) !void {
self.initEmpty();
const keys = []const []const u8{
const keys = [_][]const u8{
"include_dir",
"lib_dir",
"static_lib_dir",
@ -183,7 +183,7 @@ pub const LibCInstallation = struct {
async fn findNativeIncludeDirLinux(self: *LibCInstallation, loop: *event.Loop) !void {
const cc_exe = std.os.getenv("CC") orelse "cc";
const argv = []const []const u8{
const argv = [_][]const u8{
cc_exe,
"-E",
"-Wp,-v",
@ -231,7 +231,7 @@ pub const LibCInstallation = struct {
while (path_i < search_paths.len) : (path_i += 1) {
const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");
const stdlib_path = try fs.path.join(loop.allocator, [][]const u8{ search_path, "stdlib.h" });
const stdlib_path = try fs.path.join(loop.allocator, [_][]const u8{ search_path, "stdlib.h" });
defer loop.allocator.free(stdlib_path);
if (try fileExists(stdlib_path)) {
@ -257,7 +257,7 @@ pub const LibCInstallation = struct {
const stdlib_path = try fs.path.join(
loop.allocator,
[][]const u8{ result_buf.toSliceConst(), "stdlib.h" },
[_][]const u8{ result_buf.toSliceConst(), "stdlib.h" },
);
defer loop.allocator.free(stdlib_path);
@ -289,7 +289,7 @@ pub const LibCInstallation = struct {
}
const ucrt_lib_path = try fs.path.join(
loop.allocator,
[][]const u8{ result_buf.toSliceConst(), "ucrt.lib" },
[_][]const u8{ result_buf.toSliceConst(), "ucrt.lib" },
);
defer loop.allocator.free(ucrt_lib_path);
if (try fileExists(ucrt_lib_path)) {
@ -309,7 +309,7 @@ pub const LibCInstallation = struct {
}
async fn findNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop) FindError!void {
var dyn_tests = []DynTest{
var dyn_tests = [_]DynTest{
DynTest{
.name = "ld-linux-x86-64.so.2",
.result = null,
@ -367,7 +367,7 @@ pub const LibCInstallation = struct {
}
const kernel32_path = try fs.path.join(
loop.allocator,
[][]const u8{ result_buf.toSliceConst(), "kernel32.lib" },
[_][]const u8{ result_buf.toSliceConst(), "kernel32.lib" },
);
defer loop.allocator.free(kernel32_path);
if (try fileExists(kernel32_path)) {
@ -395,7 +395,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
const cc_exe = std.os.getenv("CC") orelse "cc";
const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file);
defer loop.allocator.free(arg1);
const argv = []const []const u8{ cc_exe, arg1 };
const argv = [_][]const u8{ cc_exe, arg1 };
// TODO This simulates evented I/O for the child process exec
await (async loop.yield() catch unreachable);

View File

@ -311,7 +311,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
}
fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
const full_path = try std.fs.path.join(&ctx.arena.allocator, [][]const u8{ dirname, basename });
const full_path = try std.fs.path.join(&ctx.arena.allocator, [_][]const u8{ dirname, basename });
const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
try ctx.args.append(full_path_with_null.ptr);
}
@ -722,7 +722,7 @@ fn darwinGetReleaseVersion(str: []const u8, major: *u32, minor: *u32, micro: *u3
return error.InvalidDarwinVersionString;
var start_pos: usize = 0;
for ([]*u32{ major, minor, micro }) |v| {
for ([_]*u32{ major, minor, micro }) |v| {
const dot_pos = mem.indexOfScalarPos(u8, str, start_pos, '.');
const end_pos = dot_pos orelse str.len;
v.* = std.fmt.parseUnsigned(u32, str[start_pos..end_pos], 10) catch return error.InvalidDarwinVersionString;

View File

@ -74,7 +74,7 @@ pub fn main() !void {
process.exit(1);
}
const commands = []Command{
const commands = [_]Command{
Command{
.name = "build-exe",
.exec = cmdBuildExe,
@ -190,14 +190,14 @@ const usage_build_generic =
\\
;
const args_build_generic = []Flag{
const args_build_generic = [_]Flag{
Flag.Bool("--help"),
Flag.Option("--color", []const []const u8{
Flag.Option("--color", [_][]const u8{
"auto",
"off",
"on",
}),
Flag.Option("--mode", []const []const u8{
Flag.Option("--mode", [_][]const u8{
"debug",
"release-fast",
"release-safe",
@ -205,7 +205,7 @@ const args_build_generic = []Flag{
}),
Flag.ArgMergeN("--assembly", 1),
Flag.Option("--emit", []const []const u8{
Flag.Option("--emit", [_][]const u8{
"asm",
"bin",
"llvm-ir",
@ -525,10 +525,10 @@ pub const usage_fmt =
\\
;
pub const args_fmt_spec = []Flag{
pub const args_fmt_spec = [_]Flag{
Flag.Bool("--help"),
Flag.Bool("--check"),
Flag.Option("--color", []const []const u8{
Flag.Option("--color", [_][]const u8{
"auto",
"off",
"on",
@ -756,7 +756,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
var group = event.Group(FmtError!void).init(fmt.loop);
while (try dir.next()) |entry| {
if (entry.kind == fs.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
const full_path = try fs.path.join(fmt.loop.allocator, [][]const u8{ file_path, entry.name });
const full_path = try fs.path.join(fmt.loop.allocator, [_][]const u8{ file_path, entry.name });
try group.call(fmtPath, fmt, full_path, check_mode);
}
}
@ -855,7 +855,7 @@ fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
try stdout.print("{}\n", std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING));
}
const args_test_spec = []Flag{Flag.Bool("--help")};
const args_test_spec = [_]Flag{Flag.Bool("--help")};
fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
try stdout.write(usage);
@ -897,7 +897,7 @@ fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
process.exit(1);
}
const sub_commands = []Command{Command{
const sub_commands = [_]Command{Command{
.name = "build-info",
.exec = cmdInternalBuildInfo,
}};

View File

@ -287,7 +287,7 @@ fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void
while (try dir.next()) |entry| {
if (entry.kind == fs.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
const full_path = try fs.path.join(fmt.allocator, [][]const u8{ file_path, entry.name });
const full_path = try fs.path.join(fmt.allocator, [_][]const u8{ file_path, entry.name });
try fmtPath(fmt, full_path, check_mode);
}
}

View File

@ -186,7 +186,7 @@ pub const Value = struct {
/// Path to the object file that contains this function
containing_object: Buffer,
link_set_node: *std.LinkedList(?*Value.Fn).Node,
link_set_node: *std.TailQueue(?*Value.Fn).Node,
/// Creates a Fn value with 1 ref
/// Takes ownership of symbol_name
@ -391,7 +391,7 @@ pub const Value = struct {
const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
const ptr_bit_count = ofile.comp.target_ptr_bits;
const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;
const indices = []*llvm.Value{
const indices = [_]*llvm.Value{
llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
};

View File

@ -460,6 +460,7 @@ enum NodeType {
NodeTypeContainerInitExpr,
NodeTypeStructValueField,
NodeTypeArrayType,
NodeTypeInferredArrayType,
NodeTypeErrorType,
NodeTypeIfErrorExpr,
NodeTypeIfOptional,
@ -685,6 +686,10 @@ struct AstNodePointerType {
bool is_volatile;
};
struct AstNodeInferredArrayType {
AstNode *child_type;
};
struct AstNodeArrayType {
AstNode *size;
AstNode *child_type;
@ -989,6 +994,7 @@ struct AstNode {
AstNodeContinueExpr continue_expr;
AstNodeUnreachableExpr unreachable_expr;
AstNodeArrayType array_type;
AstNodeInferredArrayType inferred_array_type;
AstNodeErrorType error_type;
AstNodeErrorSetDecl err_set_decl;
AstNodeCancelExpr cancel_expr;
@ -1328,7 +1334,7 @@ enum FnInline {
FnInlineNever,
};
struct FnExport {
struct GlobalExport {
Buf name;
GlobalLinkageId linkage;
};
@ -1366,7 +1372,7 @@ struct ZigFn {
AstNode *set_cold_node;
ZigList<FnExport> export_list;
ZigList<GlobalExport> export_list;
LLVMValueRef valgrind_client_request_array;
@ -1890,14 +1896,6 @@ struct CodeGen {
size_t clang_argv_len;
};
enum VarLinkage {
VarLinkageInternal,
VarLinkageExportStrong,
VarLinkageExportWeak,
VarLinkageExportLinkOnce,
VarLinkageExternal,
};
struct ZigVar {
Buf name;
ConstExprValue *const_value;
@ -1920,8 +1918,9 @@ struct ZigVar {
// this pointer to the redefined variable.
ZigVar *next_var;
ZigList<GlobalExport> export_list;
uint32_t align_bytes;
VarLinkage linkage;
bool shadowable;
bool src_is_const;
@ -2590,6 +2589,7 @@ struct IrInstructionContainerInitList {
IrInstruction base;
IrInstruction *container_type;
IrInstruction *elem_type;
size_t item_count;
IrInstruction **items;
LLVMValueRef tmp_ptr;

View File

@ -2712,6 +2712,13 @@ ZigType *get_test_fn_type(CodeGen *g) {
return g->test_fn_type;
}
void add_var_export(CodeGen *g, ZigVar *var, Buf *symbol_name, GlobalLinkageId linkage) {
GlobalExport *global_export = var->export_list.add_one();
memset(global_export, 0, sizeof(GlobalExport));
buf_init_from_buf(&global_export->name, symbol_name);
global_export->linkage = linkage;
}
void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc) {
if (ccc) {
if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {
@ -2731,8 +2738,8 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
}
}
FnExport *fn_export = fn_table_entry->export_list.add_one();
memset(fn_export, 0, sizeof(FnExport));
GlobalExport *fn_export = fn_table_entry->export_list.add_one();
memset(fn_export, 0, sizeof(GlobalExport));
buf_init_from_buf(&fn_export->name, symbol_name);
fn_export->linkage = linkage;
}
@ -2780,12 +2787,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry);
if (fn_proto->section_expr != nullptr) {
if (fn_table_entry->body_node == nullptr) {
add_node_error(g, fn_proto->section_expr,
buf_sprintf("cannot set section of external function '%s'", buf_ptr(&fn_table_entry->symbol_name)));
} else {
analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name);
}
analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name);
}
if (fn_table_entry->type_entry->id == ZigTypeIdInvalid) {
@ -3024,6 +3026,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeContainerInitExpr:
case NodeTypeStructValueField:
case NodeTypeArrayType:
case NodeTypeInferredArrayType:
case NodeTypeErrorType:
case NodeTypeIfErrorExpr:
case NodeTypeIfOptional:
@ -3193,15 +3196,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
assert(!is_export || !is_extern);
VarLinkage linkage;
if (is_export) {
linkage = VarLinkageExportStrong;
} else if (is_extern) {
linkage = VarLinkageExternal;
} else {
linkage = VarLinkageInternal;
}
ConstExprValue *init_value = nullptr;
// TODO more validation for types that can't be used for export/extern variables
@ -3216,7 +3210,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
if (implicit_type->id == ZigTypeIdUnreachable) {
add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
implicit_type = g->builtin_types.entry_invalid;
} else if ((!is_const || linkage == VarLinkageExternal) &&
} else if ((!is_const || is_extern) &&
(implicit_type->id == ZigTypeIdComptimeFloat ||
implicit_type->id == ZigTypeIdComptimeInt ||
implicit_type->id == ZigTypeIdEnumLiteral))
@ -3231,7 +3225,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
implicit_type = g->builtin_types.entry_invalid;
}
assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
} else if (linkage != VarLinkageExternal) {
} else if (!is_extern) {
add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
implicit_type = g->builtin_types.entry_invalid;
}
@ -3243,7 +3237,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
is_const, init_val, &tld_var->base, type);
tld_var->var->linkage = linkage;
tld_var->var->is_thread_local = is_thread_local;
if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
@ -3257,10 +3250,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
}
if (var_decl->section_expr != nullptr) {
if (var_decl->is_extern) {
add_node_error(g, var_decl->section_expr,
buf_sprintf("cannot set section of external variable '%s'", buf_ptr(var_decl->symbol)));
} else if (!analyze_const_string(g, tld_var->base.parent_scope, var_decl->section_expr, &tld_var->section_name)) {
if (!analyze_const_string(g, tld_var->base.parent_scope, var_decl->section_expr, &tld_var->section_name)) {
tld_var->section_name = nullptr;
}
}
@ -3269,6 +3259,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant"));
}
if (is_export) {
add_var_export(g, tld_var->var, &tld_var->var->name, GlobalLinkageIdStrong);
}
g->global_vars.append(tld_var);
}

View File

@ -198,6 +198,7 @@ ZigPackage *new_anonymous_package(void);
Buf *const_value_to_buffer(ConstExprValue *const_val);
void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);
void add_var_export(CodeGen *g, ZigVar *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage);
ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);

View File

@ -239,6 +239,8 @@ static const char *node_type_str(NodeType node_type) {
return "ContainerInitExpr";
case NodeTypeArrayType:
return "ArrayType";
case NodeTypeInferredArrayType:
return "InferredArrayType";
case NodeTypeErrorType:
return "ErrorType";
case NodeTypeIfErrorExpr:
@ -848,6 +850,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
render_node_ungrouped(ar, node->data.array_type.child_type);
break;
}
case NodeTypeInferredArrayType:
{
fprintf(ar->f, "[_]");
render_node_ungrouped(ar, node->data.inferred_array_type.child_type);
break;
}
case NodeTypePromiseType:
{
fprintf(ar->f, "promise");

View File

@ -27,11 +27,13 @@ Buf *buf_sprintf(const char *format, ...)
Buf *buf_vprintf(const char *format, va_list ap);
static inline size_t buf_len(Buf *buf) {
assert(buf);
assert(buf->list.length);
return buf->list.length - 1;
}
static inline char *buf_ptr(Buf *buf) {
assert(buf);
assert(buf->list.length);
return buf->list.items;
}

View File

@ -203,6 +203,10 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
get_target_triple(&g->triple_str, g->zig_target);
g->pointer_size_bytes = target_arch_pointer_bit_width(g->zig_target->arch) / 8;
if (!target_has_debug_info(g->zig_target)) {
g->strip_debug_symbols = true;
}
return g;
}
@ -248,6 +252,9 @@ void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) {
void codegen_set_strip(CodeGen *g, bool strip) {
g->strip_debug_symbols = strip;
if (!target_has_debug_info(g->zig_target)) {
g->strip_debug_symbols = true;
}
}
void codegen_set_out_name(CodeGen *g, Buf *out_name) {
@ -475,7 +482,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
symbol_name = get_mangled_name(g, unmangled_name, false);
linkage = GlobalLinkageIdInternal;
} else {
FnExport *fn_export = &fn_table_entry->export_list.items[0];
GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
symbol_name = &fn_export->name;
linkage = fn_export->linkage;
}
@ -529,7 +536,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
}
for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {
FnExport *fn_export = &fn_table_entry->export_list.items[i];
GlobalExport *fn_export = &fn_table_entry->export_list.items[i];
LLVMAddAlias(g->module, LLVMTypeOf(fn_table_entry->llvm_value),
fn_table_entry->llvm_value, buf_ptr(&fn_export->name));
}
@ -6691,27 +6698,14 @@ static void validate_inline_fns(CodeGen *g) {
}
static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
if (var->is_thread_local && (!g->is_single_threaded || var->linkage != VarLinkageInternal)) {
bool is_extern = var->decl_node->data.variable_declaration.is_extern;
bool is_export = var->decl_node->data.variable_declaration.is_export;
bool is_internal_linkage = !is_extern && !is_export;
if (var->is_thread_local && (!g->is_single_threaded || !is_internal_linkage)) {
LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
}
}
static LLVMLinkage var_linkage_to_llvm(VarLinkage var_linkage) {
switch (var_linkage) {
case VarLinkageInternal:
return LLVMInternalLinkage;
case VarLinkageExportStrong:
return LLVMExternalLinkage;
case VarLinkageExportWeak:
return LLVMWeakODRLinkage;
case VarLinkageExportLinkOnce:
return LLVMLinkOnceODRLinkage;
case VarLinkageExternal:
return LLVMExternalLinkage;
}
zig_unreachable();
}
static void do_code_gen(CodeGen *g) {
assert(!g->errors.length);
@ -6761,31 +6755,48 @@ static void do_code_gen(CodeGen *g) {
assert(var->decl_node);
GlobalLinkageId linkage;
Buf *unmangled_name = &var->name;
Buf *symbol_name;
if (var->export_list.length == 0) {
if (var->decl_node->data.variable_declaration.is_extern) {
symbol_name = unmangled_name;
linkage = GlobalLinkageIdStrong;
} else {
symbol_name = get_mangled_name(g, unmangled_name, false);
linkage = GlobalLinkageIdInternal;
}
} else {
GlobalExport *global_export = &var->export_list.items[0];
symbol_name = &global_export->name;
linkage = global_export->linkage;
}
LLVMValueRef global_value;
if (var->linkage == VarLinkageExternal) {
LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
bool externally_initialized = var->decl_node->data.variable_declaration.expr == nullptr;
if (externally_initialized) {
LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(symbol_name));
if (existing_llvm_var) {
global_value = LLVMConstBitCast(existing_llvm_var,
LLVMPointerType(get_llvm_type(g, var->var_type), 0));
} else {
global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(&var->name));
global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(symbol_name));
// TODO debug info for the extern variable
LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
LLVMSetLinkage(global_value, to_llvm_linkage(linkage));
maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
LLVMSetAlignment(global_value, var->align_bytes);
LLVMSetGlobalConstant(global_value, var->gen_is_const);
set_global_tls(g, var, global_value);
}
} else {
bool exported = (var->linkage != VarLinkageInternal);
const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
render_const_val(g, var->const_value, mangled_name);
render_const_val_global(g, var->const_value, mangled_name);
bool exported = (linkage != GlobalLinkageIdInternal);
render_const_val(g, var->const_value, buf_ptr(symbol_name));
render_const_val_global(g, var->const_value, buf_ptr(symbol_name));
global_value = var->const_value->global_refs->llvm_global;
if (exported) {
LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
LLVMSetLinkage(global_value, to_llvm_linkage(linkage));
maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
}
if (tld_var->section_name) {
@ -6805,6 +6816,11 @@ static void do_code_gen(CodeGen *g) {
}
var->value_ref = global_value;
for (size_t export_i = 1; export_i < var->export_list.length; export_i += 1) {
GlobalExport *global_export = &var->export_list.items[export_i];
LLVMAddAlias(g->module, LLVMTypeOf(var->value_ref), var->value_ref, buf_ptr(&global_export->name));
}
}
// Generate function definitions.
@ -7505,7 +7521,7 @@ static bool detect_single_threaded(CodeGen *g) {
}
static bool detect_err_ret_tracing(CodeGen *g) {
return !target_is_wasm(g->zig_target) &&
return !g->strip_debug_symbols &&
g->build_mode != BuildModeFastRelease &&
g->build_mode != BuildModeSmallRelease;
}
@ -7939,6 +7955,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g)));
buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
{
TargetSubsystem detected_subsystem = detect_subsystem(g);
@ -7979,6 +7996,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
// Only a few things affect builtin.zig
cache_buf(&cache_hash, compiler_id);
cache_int(&cache_hash, g->build_mode);
cache_bool(&cache_hash, g->strip_debug_symbols);
cache_bool(&cache_hash, g->is_test_build);
cache_bool(&cache_hash, g->is_single_threaded);
cache_int(&cache_hash, g->zig_target->is_native);
@ -8783,6 +8801,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
Termination term;
ZigList<const char *> args = {};
args.append(buf_ptr(self_exe_path));
args.append("cc");
Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));
@ -8801,7 +8820,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
if (g->verbose_cc) {
print_zig_cc_cmd("zig", &args);
}
os_spawn_process(buf_ptr(self_exe_path), args, &term);
os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nThe following command failed:\n");
print_zig_cc_cmd(buf_ptr(self_exe_path), &args);
@ -9168,7 +9187,7 @@ static void gen_h_file(CodeGen *g) {
if (fn_table_entry->export_list.length == 0) {
symbol_name = &fn_table_entry->symbol_name;
} else {
FnExport *fn_export = &fn_table_entry->export_list.items[0];
GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
symbol_name = &fn_export->name;
}

View File

@ -1427,15 +1427,17 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
}
static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *container_type, size_t item_count, IrInstruction **items)
IrInstruction *container_type, IrInstruction *elem_type, size_t item_count, IrInstruction **items)
{
IrInstructionContainerInitList *container_init_list_instruction =
ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
container_init_list_instruction->container_type = container_type;
container_init_list_instruction->elem_type = elem_type;
container_init_list_instruction->item_count = item_count;
container_init_list_instruction->items = items;
if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);
if (elem_type != nullptr) ir_ref_instruction(elem_type, irb->current_basic_block);
for (size_t i = 0; i < item_count; i += 1) {
ir_ref_instruction(items[i], irb->current_basic_block);
}
@ -5396,11 +5398,25 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
ContainerInitKind kind = container_init_expr->kind;
IrInstruction *container_type = ir_gen_node(irb, container_init_expr->type, scope);
if (container_type == irb->codegen->invalid_instruction)
return container_type;
IrInstruction *container_type = nullptr;
IrInstruction *elem_type = nullptr;
if (container_init_expr->type->type == NodeTypeInferredArrayType) {
elem_type = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.child_type, scope);
if (elem_type == irb->codegen->invalid_instruction)
return elem_type;
} else {
container_type = ir_gen_node(irb, container_init_expr->type, scope);
if (container_type == irb->codegen->invalid_instruction)
return container_type;
}
if (kind == ContainerInitKindStruct) {
if (elem_type != nullptr) {
add_node_error(irb->codegen, container_init_expr->type,
buf_sprintf("initializing array with struct syntax"));
return irb->codegen->invalid_instruction;
}
size_t field_count = container_init_expr->entries.length;
IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
for (size_t i = 0; i < field_count; i += 1) {
@ -5429,7 +5445,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
values[i] = expr_value;
}
return ir_build_container_init_list(irb, scope, node, container_type, item_count, values);
return ir_build_container_init_list(irb, scope, node, container_type, elem_type, item_count, values);
} else {
zig_unreachable();
}
@ -7693,6 +7709,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval);
case NodeTypeEnumLiteral:
return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval);
case NodeTypeInferredArrayType:
add_node_error(irb->codegen, node,
buf_sprintf("inferred array size invalid here"));
return irb->codegen->invalid_instruction;
}
zig_unreachable();
}
@ -13771,20 +13791,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
}
static VarLinkage global_linkage_to_var_linkage(GlobalLinkageId id) {
switch (id) {
case GlobalLinkageIdStrong:
return VarLinkageExportStrong;
case GlobalLinkageIdWeak:
return VarLinkageExportWeak;
case GlobalLinkageIdLinkOnce:
return VarLinkageExportLinkOnce;
case GlobalLinkageIdInternal:
return VarLinkageInternal;
}
zig_unreachable();
}
static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
IrInstruction *name = instruction->name->child;
Buf *symbol_name = ir_resolve_str(ira, name);
@ -13881,6 +13887,15 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
want_var_export = true;
}
break;
case ZigTypeIdArray:
if (!type_allowed_in_extern(ira->codegen, target->value.type->data.array.child_type)) {
ir_add_error(ira, target,
buf_sprintf("array element type '%s' not extern-compatible",
buf_ptr(&target->value.type->data.array.child_type->name)));
} else {
want_var_export = true;
}
break;
case ZigTypeIdMetaType: {
ZigType *type_value = target->value.data.x_type;
switch (type_value->id) {
@ -13948,7 +13963,6 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case ZigTypeIdInt:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
case ZigTypeIdUndefined:
@ -13974,7 +13988,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
if (load_ptr->ptr->id == IrInstructionIdVarPtr) {
IrInstructionVarPtr *var_ptr = reinterpret_cast<IrInstructionVarPtr *>(load_ptr->ptr);
ZigVar *var = var_ptr->var;
var->linkage = global_linkage_to_var_linkage(global_linkage_id);
add_var_export(ira->codegen, var, symbol_name, global_linkage_id);
}
}
@ -14267,7 +14281,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
ConstExprValue *mem_slot = nullptr;
bool comptime_var_mem = ir_get_var_is_comptime(var);
bool linkage_makes_it_runtime = var->linkage == VarLinkageExternal;
bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern;
bool is_const = var->src_is_const;
bool is_volatile = false;
@ -16780,7 +16794,9 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdPromise:
case ZigTypeIdVector:
{
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
ResolveStatus needed_status = (align_bytes == 0) ?
ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
if ((err = type_resolve(ira->codegen, child_type, needed_status)))
return ira->codegen->invalid_instruction;
ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0, is_allow_zero);
@ -17961,16 +17977,31 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
{
Error err;
ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
if (type_is_invalid(container_type))
return ira->codegen->invalid_instruction;
size_t elem_count = instruction->item_count;
if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
ZigType *container_type;
if (instruction->container_type != nullptr) {
container_type = ir_resolve_type(ira, instruction->container_type->child);
if (type_is_invalid(container_type))
return ira->codegen->invalid_instruction;
} else {
ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child);
if (type_is_invalid(elem_type))
return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) {
return ira->codegen->invalid_instruction;
}
container_type = get_array_type(ira->codegen, elem_type, elem_count);
}
if (is_slice(container_type)) {
ir_add_error(ira, &instruction->base,
buf_sprintf("expected array type or [_], found slice"));
return ira->codegen->invalid_instruction;
} else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
0, nullptr);
} else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
} else if (container_type->id == ZigTypeIdArray) {
// array is same as slice init but we make a compile error if the length is wrong
ZigType *child_type;
if (container_type->id == ZigTypeIdArray) {
@ -18057,7 +18088,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
instruction->base.scope, instruction->base.source_node,
nullptr, elem_count, new_items);
nullptr, nullptr, elem_count, new_items);
new_instruction->value.type = fixed_size_array_type;
ir_add_alloca(ira, new_instruction, fixed_size_array_type);
return new_instruction;
@ -18584,10 +18615,11 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
true, false, PtrLenUnknown,
0, 0, 0, false);
fn_decl_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {
if (fn_node->is_extern && fn_node->lib_name != nullptr && buf_len(fn_node->lib_name) > 0) {
fn_decl_fields[6].data.x_optional = create_const_vals(1);
ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name);
init_const_slice(ira->codegen, fn_decl_fields[6].data.x_optional, lib_name, 0, buf_len(fn_node->lib_name), true);
init_const_slice(ira->codegen, fn_decl_fields[6].data.x_optional, lib_name, 0,
buf_len(fn_node->lib_name), true);
} else {
fn_decl_fields[6].data.x_optional = nullptr;
}

View File

@ -153,6 +153,7 @@ static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, b
const char *cc_exe = getenv("CC");
cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe;
ZigList<const char *> args = {};
args.append(cc_exe);
args.append("-E");
args.append("-Wp,-v");
args.append("-xc");
@ -166,7 +167,7 @@ static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, b
Buf *out_stderr = buf_alloc();
Buf *out_stdout = buf_alloc();
Error err;
if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) {
if (verbose) {
fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err));
}
@ -277,12 +278,13 @@ Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirnam
const char *cc_exe = getenv("CC");
cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe;
ZigList<const char *> args = {};
args.append(cc_exe);
args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file)));
Termination term;
Buf *out_stderr = buf_alloc();
Buf *out_stdout = buf_alloc();
Error err;
if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) {
if (err == ErrorFileNotFound)
return ErrorNoCCompilerInstalled;
if (verbose) {

View File

@ -1721,10 +1721,11 @@ void codegen_link(CodeGen *g) {
if (g->system_linker_hack && g->zig_target->os == OsMacOSX) {
Termination term;
ZigList<const char *> args = {};
args.append("ld");
for (size_t i = 1; i < lj.args.length; i += 1) {
args.append(lj.args.at(i));
}
os_spawn_process("ld", args, &term);
os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
exit(1);
}

View File

@ -467,6 +467,7 @@ int main(int argc, char **argv) {
init_all_targets();
ZigList<const char *> args = {0};
args.append(NULL); // placeholder
args.append(zig_exe_path);
args.append(NULL); // placeholder
args.append(NULL); // placeholder
@ -525,8 +526,8 @@ int main(int argc, char **argv) {
g->enable_time_report = timing_info;
codegen_set_out_name(g, buf_create_from_str("build"));
args.items[1] = buf_ptr(&build_file_dirname);
args.items[2] = buf_ptr(&full_cache_dir);
args.items[2] = buf_ptr(&build_file_dirname);
args.items[3] = buf_ptr(&full_cache_dir);
bool build_file_exists;
if ((err = os_file_exists(&build_file_abs, &build_file_exists))) {
@ -580,12 +581,14 @@ int main(int argc, char **argv) {
codegen_build_and_link(g);
Termination term;
os_spawn_process(buf_ptr(&g->output_file_path), args, &term);
args.items[0] = buf_ptr(&g->output_file_path);
os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nBuild failed. The following command failed:\n");
fprintf(stderr, "%s", buf_ptr(&g->output_file_path));
const char *prefix = "";
for (size_t i = 0; i < args.length; i += 1) {
fprintf(stderr, " %s", args.at(i));
fprintf(stderr, "%s%s", prefix, args.at(i));
prefix = " ";
}
fprintf(stderr, "\n");
}
@ -954,6 +957,7 @@ int main(int argc, char **argv) {
case CmdBuiltin: {
CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,
out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr);
codegen_set_strip(g, strip);
g->subsystem = subsystem;
g->valgrind_support = valgrind_support;
g->want_pic = want_pic;
@ -1160,7 +1164,7 @@ int main(int argc, char **argv) {
args.pop();
Termination term;
os_spawn_process(exec_path, args, &term);
os_spawn_process(args, &term);
return term.code;
} else if (cmd == CmdBuild) {
if (g->enable_cache) {
@ -1212,17 +1216,10 @@ int main(int argc, char **argv) {
}
Termination term;
if (test_exec_args.length > 0) {
ZigList<const char *> rest_args = {0};
for (size_t i = 1; i < test_exec_args.length; i += 1) {
rest_args.append(test_exec_args.at(i));
}
os_spawn_process(test_exec_args.items[0], rest_args, &term);
} else {
ZigList<const char *> no_args = {0};
os_spawn_process(buf_ptr(test_exe_path), no_args, &term);
if (test_exec_args.length == 0) {
test_exec_args.append(buf_ptr(test_exe_path));
}
os_spawn_process(test_exec_args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");
fprintf(stderr, "%s\n", buf_ptr(test_exe_path));

View File

@ -105,16 +105,15 @@ static void populate_termination(Termination *term, int status) {
}
}
static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, Termination *term) {
const char **argv = allocate<const char *>(args.length + 2);
argv[0] = exe;
argv[args.length + 1] = nullptr;
static void os_spawn_process_posix(ZigList<const char *> &args, Termination *term) {
const char **argv = allocate<const char *>(args.length + 1);
for (size_t i = 0; i < args.length; i += 1) {
argv[i + 1] = args.at(i);
argv[i] = args.at(i);
}
argv[args.length] = nullptr;
pid_t pid;
int rc = posix_spawnp(&pid, exe, nullptr, nullptr, const_cast<char *const*>(argv), environ);
int rc = posix_spawnp(&pid, args.at(0), nullptr, nullptr, const_cast<char *const*>(argv), environ);
if (rc != 0) {
zig_panic("posix_spawn failed: %s", strerror(rc));
}
@ -126,16 +125,14 @@ static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args,
#endif
#if defined(ZIG_OS_WINDOWS)
static void os_windows_create_command_line(Buf *command_line, const char *exe, ZigList<const char *> &args) {
static void os_windows_create_command_line(Buf *command_line, ZigList<const char *> &args) {
buf_resize(command_line, 0);
buf_append_char(command_line, '\"');
buf_append_str(command_line, exe);
buf_append_char(command_line, '\"');
const char *prefix = "\"";
for (size_t arg_i = 0; arg_i < args.length; arg_i += 1) {
buf_append_str(command_line, " \"");
const char *arg = args.at(arg_i);
buf_append_str(command_line, prefix);
prefix = " \"";
size_t arg_len = strlen(arg);
for (size_t c_i = 0; c_i < arg_len; c_i += 1) {
if (arg[c_i] == '\"') {
@ -147,14 +144,15 @@ static void os_windows_create_command_line(Buf *command_line, const char *exe, Z
}
}
static void os_spawn_process_windows(const char *exe, ZigList<const char *> &args, Termination *term) {
static void os_spawn_process_windows(ZigList<const char *> &args, Termination *term) {
Buf command_line = BUF_INIT;
os_windows_create_command_line(&command_line, exe, args);
os_windows_create_command_line(&command_line, args);
PROCESS_INFORMATION piProcInfo = {0};
STARTUPINFO siStartInfo = {0};
siStartInfo.cb = sizeof(STARTUPINFO);
const char *exe = args.at(0);
BOOL success = CreateProcessA(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,
&siStartInfo, &piProcInfo);
@ -173,11 +171,11 @@ static void os_spawn_process_windows(const char *exe, ZigList<const char *> &arg
}
#endif
void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term) {
void os_spawn_process(ZigList<const char *> &args, Termination *term) {
#if defined(ZIG_OS_WINDOWS)
os_spawn_process_windows(exe, args, term);
os_spawn_process_windows(args, term);
#elif defined(ZIG_OS_POSIX)
os_spawn_process_posix(exe, args, term);
os_spawn_process_posix(args, term);
#else
#error "missing os_spawn_process implementation"
#endif
@ -785,7 +783,7 @@ Error os_file_exists(Buf *full_path, bool *result) {
}
#if defined(ZIG_OS_POSIX)
static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,
static Error os_exec_process_posix(ZigList<const char *> &args,
Termination *term, Buf *out_stderr, Buf *out_stdout)
{
int stdin_pipe[2];
@ -817,13 +815,12 @@ static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,
if (dup2(stderr_pipe[1], STDERR_FILENO) == -1)
zig_panic("dup2 failed");
const char **argv = allocate<const char *>(args.length + 2);
argv[0] = exe;
argv[args.length + 1] = nullptr;
const char **argv = allocate<const char *>(args.length + 1);
argv[args.length] = nullptr;
for (size_t i = 0; i < args.length; i += 1) {
argv[i + 1] = args.at(i);
argv[i] = args.at(i);
}
execvp(exe, const_cast<char * const *>(argv));
execvp(argv[0], const_cast<char * const *>(argv));
Error report_err = ErrorUnexpected;
if (errno == ENOENT) {
report_err = ErrorFileNotFound;
@ -874,11 +871,11 @@ static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,
// LocalFree(messageBuffer);
//}
static Error os_exec_process_windows(const char *exe, ZigList<const char *> &args,
static Error os_exec_process_windows(ZigList<const char *> &args,
Termination *term, Buf *out_stderr, Buf *out_stdout)
{
Buf command_line = BUF_INIT;
os_windows_create_command_line(&command_line, exe, args);
os_windows_create_command_line(&command_line, args);
HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
@ -925,6 +922,7 @@ static Error os_exec_process_windows(const char *exe, ZigList<const char *> &arg
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
const char *exe = args.at(0);
BOOL success = CreateProcess(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,
&siStartInfo, &piProcInfo);
@ -1005,13 +1003,13 @@ Error os_execv(const char *exe, const char **argv) {
#endif
}
Error os_exec_process(const char *exe, ZigList<const char *> &args,
Error os_exec_process(ZigList<const char *> &args,
Termination *term, Buf *out_stderr, Buf *out_stdout)
{
#if defined(ZIG_OS_WINDOWS)
return os_exec_process_windows(exe, args, term, out_stderr, out_stdout);
return os_exec_process_windows(args, term, out_stderr, out_stdout);
#elif defined(ZIG_OS_POSIX)
return os_exec_process_posix(exe, args, term, out_stderr, out_stdout);
return os_exec_process_posix(args, term, out_stderr, out_stdout);
#else
#error "missing os_exec_process implementation"
#endif

View File

@ -100,8 +100,8 @@ struct OsFileAttr {
int os_init(void);
void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term);
Error os_exec_process(const char *exe, ZigList<const char *> &args,
void os_spawn_process(ZigList<const char *> &args, Termination *term);
Error os_exec_process(ZigList<const char *> &args,
Termination *term, Buf *out_stderr, Buf *out_stdout);
Error os_execv(const char *exe, const char **argv);

View File

@ -288,6 +288,9 @@ static AstNode *ast_parse_prefix_op_expr(
case NodeTypeArrayType:
right = &prefix->data.array_type.child_type;
break;
case NodeTypeInferredArrayType:
right = &prefix->data.inferred_array_type.child_type;
break;
case NodeTypePointerType: {
// We might get two pointers from *_ptr_type_start
AstNode *child = prefix->data.pointer_type.op_expr;
@ -887,6 +890,11 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
body = ast_parse_assign_expr(pc);
}
if (body == nullptr) {
Token *tok = eat_token(pc);
ast_error(pc, tok, "expected if body, found '%s'", token_name(tok->id));
}
Token *err_payload = nullptr;
AstNode *else_body = nullptr;
if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
@ -991,6 +999,11 @@ static AstNode *ast_parse_for_statement(ParseContext *pc) {
body = ast_parse_assign_expr(pc);
}
if (body == nullptr) {
Token *tok = eat_token(pc);
ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id));
}
AstNode *else_body = nullptr;
if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
else_body = ast_expect(pc, ast_parse_statement);
@ -1020,6 +1033,11 @@ static AstNode *ast_parse_while_statement(ParseContext *pc) {
body = ast_parse_assign_expr(pc);
}
if (body == nullptr) {
Token *tok = eat_token(pc);
ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id));
}
Token *err_payload = nullptr;
AstNode *else_body = nullptr;
if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
@ -1852,11 +1870,15 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) {
// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
if (eat_token_if(pc, TokenIdLBracket) == nullptr)
return nullptr;
Token *sym_name = expect_token(pc, TokenIdSymbol);
expect_token(pc, TokenIdRBracket);
Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
if (sym_name == nullptr) {
if (eat_token_if(pc, TokenIdLBracket) == nullptr) {
return nullptr;
} else {
sym_name = expect_token(pc, TokenIdSymbol);
expect_token(pc, TokenIdRBracket);
}
}
Token *str = expect_token(pc, TokenIdStringLiteral);
expect_token(pc, TokenIdLParen);
@ -1871,7 +1893,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
expect_token(pc, TokenIdRParen);
AsmOutput *res = allocate<AsmOutput>(1);
res->asm_symbolic_name = token_buf(sym_name);
res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);
res->constraint = token_buf(str);
res->variable_name = token_buf(var_name);
res->return_type = return_type;
@ -1894,18 +1916,23 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) {
// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
if (eat_token_if(pc, TokenIdLBracket) == nullptr)
return nullptr;
Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
if (sym_name == nullptr) {
if (eat_token_if(pc, TokenIdLBracket) == nullptr) {
return nullptr;
} else {
sym_name = expect_token(pc, TokenIdSymbol);
expect_token(pc, TokenIdRBracket);
}
}
Token *sym_name = expect_token(pc, TokenIdSymbol);
expect_token(pc, TokenIdRBracket);
Token *constraint = expect_token(pc, TokenIdStringLiteral);
expect_token(pc, TokenIdLParen);
AstNode *expr = ast_expect(pc, ast_parse_expr);
expect_token(pc, TokenIdRParen);
AsmInput *res = allocate<AsmInput>(1);
res->asm_symbolic_name = token_buf(sym_name);
res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);
res->constraint = token_buf(constraint);
res->expr = expr;
return res;
@ -2597,6 +2624,12 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
return ptr;
}
Token *arr_init = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
if (arr_init != nullptr) {
return ast_create_node(pc, NodeTypeInferredArrayType, arr_init);
}
return nullptr;
}
@ -3003,6 +3036,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.array_type.child_type, visit, context);
visit_field(&node->data.array_type.align_expr, visit, context);
break;
case NodeTypeInferredArrayType:
visit_field(&node->data.array_type.child_type, visit, context);
break;
case NodeTypePromiseType:
visit_field(&node->data.promise_type.payload_type, visit, context);
break;

View File

@ -1585,3 +1585,7 @@ void target_libc_enum(size_t index, ZigTarget *out_target) {
out_target->vendor = ZigLLVM_UnknownVendor;
out_target->is_native = false;
}
bool target_has_debug_info(const ZigTarget *target) {
return !target_is_wasm(target);
}

View File

@ -177,6 +177,7 @@ bool target_is_musl(const ZigTarget *target);
bool target_is_wasm(const ZigTarget *target);
bool target_is_single_threaded(const ZigTarget *target);
bool target_supports_stack_probing(const ZigTarget *target);
bool target_has_debug_info(const ZigTarget *target);
uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);

View File

@ -224,6 +224,7 @@ enum TokenizeState {
TokenizeStateLBracket,
TokenizeStateLBracketStar,
TokenizeStateLBracketStarC,
TokenizeStateLBracketUnderscore,
};
@ -774,6 +775,9 @@ void tokenize(Buf *buf, Tokenization *out) {
case '*':
t.state = TokenizeStateLBracketStar;
break;
case '_':
t.state = TokenizeStateLBracketUnderscore;
break;
default:
// reinterpret as just an lbracket
t.pos -= 1;
@ -782,6 +786,21 @@ void tokenize(Buf *buf, Tokenization *out) {
continue;
}
break;
case TokenizeStateLBracketUnderscore:
switch (c) {
case ']':
set_token_id(&t, t.cur_tok, TokenIdBracketUnderscoreBracket);
end_token(&t);
t.state = TokenizeStateStart;
break;
default:
// reinterpret as just an lbracket
t.pos -= 2;
end_token(&t);
t.state = TokenizeStateStart;
continue;
}
break;
case TokenizeStateLBracketStar:
switch (c) {
case 'c':
@ -1443,6 +1462,7 @@ void tokenize(Buf *buf, Tokenization *out) {
case TokenizeStateLineStringContinueC:
case TokenizeStateLBracketStar:
case TokenizeStateLBracketStarC:
case TokenizeStateLBracketUnderscore:
tokenize_error(&t, "unexpected EOF");
break;
case TokenizeStateLineComment:
@ -1581,6 +1601,7 @@ const char * token_name(TokenId id) {
case TokenIdTimesPercent: return "*%";
case TokenIdTimesPercentEq: return "*%=";
case TokenIdBarBarEq: return "||=";
case TokenIdBracketUnderscoreBracket: return "[_]";
case TokenIdCount:
zig_unreachable();
}

View File

@ -30,6 +30,7 @@ enum TokenId {
TokenIdBitXorEq,
TokenIdBracketStarBracket,
TokenIdBracketStarCBracket,
TokenIdBracketUnderscoreBracket,
TokenIdCharLiteral,
TokenIdCmpEq,
TokenIdCmpGreaterOrEq,

View File

@ -23,7 +23,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
/// Deinitialize with `deinit` or use `toOwnedSlice`.
pub fn init(allocator: *Allocator) Self {
return Self{
.items = []align(A) T{},
.items = [_]T{},
.len = 0,
.allocator = allocator,
};
@ -265,7 +265,7 @@ test "std.ArrayList.basic" {
testing.expect(list.pop() == 10);
testing.expect(list.len == 9);
list.appendSlice([]const i32{
list.appendSlice([_]i32{
1,
2,
3,
@ -276,7 +276,7 @@ test "std.ArrayList.basic" {
testing.expect(list.pop() == 1);
testing.expect(list.len == 9);
list.appendSlice([]const i32{}) catch unreachable;
list.appendSlice([_]i32{}) catch unreachable;
testing.expect(list.len == 9);
// can only set on indices < self.len
@ -423,7 +423,7 @@ test "std.ArrayList.insertSlice" {
try list.append(2);
try list.append(3);
try list.append(4);
try list.insertSlice(1, []const i32{
try list.insertSlice(1, [_]i32{
9,
8,
});
@ -434,7 +434,7 @@ test "std.ArrayList.insertSlice" {
testing.expect(list.items[4] == 3);
testing.expect(list.items[5] == 4);
const items = []const i32{1};
const items = [_]i32{1};
try list.insertSlice(0, items[0..0]);
testing.expect(list.len == 6);
testing.expect(list.items[0] == 1);

View File

@ -28,7 +28,7 @@ const combinedTable = init: {
const std = @import("std");
const mem = std.mem;
const alpha = []u1{
const alpha = [_]u1{
// 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -40,7 +40,7 @@ const combinedTable = init: {
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
};
const lower = []u1{
const lower = [_]u1{
// 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -52,7 +52,7 @@ const combinedTable = init: {
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
};
const upper = []u1{
const upper = [_]u1{
// 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -64,7 +64,7 @@ const combinedTable = init: {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
const digit = []u1{
const digit = [_]u1{
// 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -76,7 +76,7 @@ const combinedTable = init: {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
const hex = []u1{
const hex = [_]u1{
// 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -88,7 +88,7 @@ const combinedTable = init: {
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
const space = []u1{
const space = [_]u1{
// 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -100,7 +100,7 @@ const combinedTable = init: {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
const punct = []u1{
const punct = [_]u1{
// 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -112,7 +112,7 @@ const combinedTable = init: {
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
};
const graph = []u1{
const graph = [_]u1{
// 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

View File

@ -14,7 +14,7 @@ pub fn Queue(comptime T: type) type {
mutex: std.Mutex,
pub const Self = @This();
pub const Node = std.LinkedList(T).Node;
pub const Node = std.TailQueue(T).Node;
pub fn init() Self {
return Self{
@ -100,7 +100,7 @@ pub fn Queue(comptime T: type) type {
pub fn isEmpty(self: *Self) bool {
const held = self.mutex.acquire();
defer held.release();
return self.head != null;
return self.head == null;
}
pub fn dump(self: *Self) void {
@ -152,11 +152,8 @@ const puts_per_thread = 500;
const put_thread_count = 3;
test "std.atomic.Queue" {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var plenty_of_memory = try direct_allocator.allocator.alloc(u8, 300 * 1024);
defer direct_allocator.allocator.free(plenty_of_memory);
var plenty_of_memory = try std.heap.direct_allocator.alloc(u8, 300 * 1024);
defer std.heap.direct_allocator.free(plenty_of_memory);
var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory);
var a = &fixed_buffer_allocator.allocator;
@ -172,12 +169,14 @@ test "std.atomic.Queue" {
};
if (builtin.single_threaded) {
expect(context.queue.isEmpty());
{
var i: usize = 0;
while (i < put_thread_count) : (i += 1) {
expect(startPuts(&context) == 0);
}
}
expect(!context.queue.isEmpty());
context.puts_done = 1;
{
var i: usize = 0;
@ -185,7 +184,10 @@ test "std.atomic.Queue" {
expect(startGets(&context) == 0);
}
}
expect(context.queue.isEmpty());
} else {
expect(context.queue.isEmpty());
var putters: [put_thread_count]*std.Thread = undefined;
for (putters) |*t| {
t.* = try std.Thread.spawn(&context, startPuts);
@ -200,6 +202,8 @@ test "std.atomic.Queue" {
_ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
for (getters) |t|
t.wait();
expect(context.queue.isEmpty());
}
if (context.put_sum != context.get_sum) {
@ -250,6 +254,7 @@ fn startGets(ctx: *Context) u8 {
test "std.atomic.Queue single-threaded" {
var queue = Queue(i32).init();
expect(queue.isEmpty());
var node_0 = Queue(i32).Node{
.data = 0,
@ -257,6 +262,7 @@ test "std.atomic.Queue single-threaded" {
.prev = undefined,
};
queue.put(&node_0);
expect(!queue.isEmpty());
var node_1 = Queue(i32).Node{
.data = 1,
@ -264,8 +270,10 @@ test "std.atomic.Queue single-threaded" {
.prev = undefined,
};
queue.put(&node_1);
expect(!queue.isEmpty());
expect(queue.get().?.data == 0);
expect(!queue.isEmpty());
var node_2 = Queue(i32).Node{
.data = 2,
@ -273,6 +281,7 @@ test "std.atomic.Queue single-threaded" {
.prev = undefined,
};
queue.put(&node_2);
expect(!queue.isEmpty());
var node_3 = Queue(i32).Node{
.data = 3,
@ -280,10 +289,13 @@ test "std.atomic.Queue single-threaded" {
.prev = undefined,
};
queue.put(&node_3);
expect(!queue.isEmpty());
expect(queue.get().?.data == 1);
expect(!queue.isEmpty());
expect(queue.get().?.data == 2);
expect(!queue.isEmpty());
var node_4 = Queue(i32).Node{
.data = 4,
@ -291,13 +303,17 @@ test "std.atomic.Queue single-threaded" {
.prev = undefined,
};
queue.put(&node_4);
expect(!queue.isEmpty());
expect(queue.get().?.data == 3);
node_3.next = null;
expect(!queue.isEmpty());
expect(queue.get().?.data == 4);
expect(queue.isEmpty());
expect(queue.get() == null);
expect(queue.isEmpty());
}
test "std.atomic.Queue dump" {

View File

@ -86,11 +86,8 @@ const puts_per_thread = 500;
const put_thread_count = 3;
test "std.atomic.stack" {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var plenty_of_memory = try direct_allocator.allocator.alloc(u8, 300 * 1024);
defer direct_allocator.allocator.free(plenty_of_memory);
var plenty_of_memory = try std.heap.direct_allocator.alloc(u8, 300 * 1024);
defer std.heap.direct_allocator.free(plenty_of_memory);
var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory);
var a = &fixed_buffer_allocator.allocator;

View File

@ -14,7 +14,7 @@ pub const Base64Encoder = struct {
/// a bunch of assertions, then simply pass the data right through.
pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64Encoder {
assert(alphabet_chars.len == 64);
var char_in_alphabet = []bool{false} ** 256;
var char_in_alphabet = [_]bool{false} ** 256;
for (alphabet_chars) |c| {
assert(!char_in_alphabet[c]);
assert(c != pad_char);
@ -92,7 +92,7 @@ pub const Base64Decoder = struct {
var result = Base64Decoder{
.char_to_index = undefined,
.char_in_alphabet = []bool{false} ** 256,
.char_in_alphabet = [_]bool{false} ** 256,
.pad_char = pad_char,
};
@ -160,7 +160,7 @@ pub const Base64DecoderWithIgnore = struct {
pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) Base64DecoderWithIgnore {
var result = Base64DecoderWithIgnore{
.decoder = Base64Decoder.init(alphabet_chars, pad_char),
.char_is_ignored = []bool{false} ** 256,
.char_is_ignored = [_]bool{false} ** 256,
};
for (ignore_chars) |c| {

View File

@ -83,10 +83,7 @@ pub const BufMap = struct {
};
test "BufMap" {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var bufmap = BufMap.init(&direct_allocator.allocator);
var bufmap = BufMap.init(std.heap.direct_allocator);
defer bufmap.deinit();
try bufmap.set("x", "1");

View File

@ -65,10 +65,7 @@ pub const BufSet = struct {
};
test "BufSet" {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var bufset = BufSet.init(&direct_allocator.allocator);
var bufset = BufSet.init(std.heap.direct_allocator);
defer bufset.deinit();
try bufset.put("x");

View File

@ -153,8 +153,8 @@ pub const Builder = struct {
pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void {
self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default
self.lib_dir = fs.path.join(self.allocator, [][]const u8{ self.prefix, "lib" }) catch unreachable;
self.exe_dir = fs.path.join(self.allocator, [][]const u8{ self.prefix, "bin" }) catch unreachable;
self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ self.prefix, "lib" }) catch unreachable;
self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ self.prefix, "bin" }) catch unreachable;
}
pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
@ -653,7 +653,7 @@ pub const Builder = struct {
pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep {
const full_dest_path = fs.path.resolve(
self.allocator,
[][]const u8{ self.prefix, dest_rel_path },
[_][]const u8{ self.prefix, dest_rel_path },
) catch unreachable;
self.pushInstalledFile(full_dest_path);
@ -689,7 +689,7 @@ pub const Builder = struct {
}
fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 {
return fs.path.resolve(self.allocator, [][]const u8{ self.build_root, rel_path }) catch unreachable;
return fs.path.resolve(self.allocator, [_][]const u8{ self.build_root, rel_path }) catch unreachable;
}
pub fn fmt(self: *Builder, comptime format: []const u8, args: ...) []u8 {
@ -704,7 +704,7 @@ pub const Builder = struct {
if (fs.path.isAbsolute(name)) {
return name;
}
const full_path = try fs.path.join(self.allocator, [][]const u8{ search_prefix, "bin", self.fmt("{}{}", name, exe_extension) });
const full_path = try fs.path.join(self.allocator, [_][]const u8{ search_prefix, "bin", self.fmt("{}{}", name, exe_extension) });
if (fs.path.real(self.allocator, full_path)) |real_path| {
return real_path;
} else |_| {
@ -719,7 +719,7 @@ pub const Builder = struct {
}
var it = mem.tokenize(PATH, []u8{fs.path.delimiter});
while (it.next()) |path| {
const full_path = try fs.path.join(self.allocator, [][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
const full_path = try fs.path.join(self.allocator, [_][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
if (fs.path.real(self.allocator, full_path)) |real_path| {
return real_path;
} else |_| {
@ -733,7 +733,7 @@ pub const Builder = struct {
return name;
}
for (paths) |path| {
const full_path = try fs.path.join(self.allocator, [][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
const full_path = try fs.path.join(self.allocator, [_][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
if (fs.path.real(self.allocator, full_path)) |real_path| {
return real_path;
} else |_| {
@ -928,7 +928,7 @@ const CSourceFile = struct {
};
fn isLibCLibrary(name: []const u8) bool {
const libc_libraries = [][]const u8{ "c", "m", "dl", "rt", "pthread" };
const libc_libraries = [_][]const u8{ "c", "m", "dl", "rt", "pthread" };
for (libc_libraries) |libc_lib_name| {
if (mem.eql(u8, name, libc_lib_name))
return true;
@ -1247,7 +1247,7 @@ pub const LibExeObjStep = struct {
pub fn getOutputPath(self: *LibExeObjStep) []const u8 {
return fs.path.join(
self.builder.allocator,
[][]const u8{ self.output_dir.?, self.out_filename },
[_][]const u8{ self.output_dir.?, self.out_filename },
) catch unreachable;
}
@ -1257,7 +1257,7 @@ pub const LibExeObjStep = struct {
assert(self.kind == Kind.Lib);
return fs.path.join(
self.builder.allocator,
[][]const u8{ self.output_dir.?, self.out_lib_filename },
[_][]const u8{ self.output_dir.?, self.out_lib_filename },
) catch unreachable;
}
@ -1268,7 +1268,7 @@ pub const LibExeObjStep = struct {
assert(!self.disable_gen_h);
return fs.path.join(
self.builder.allocator,
[][]const u8{ self.output_dir.?, self.out_h_filename },
[_][]const u8{ self.output_dir.?, self.out_h_filename },
) catch unreachable;
}
@ -1410,7 +1410,7 @@ pub const LibExeObjStep = struct {
if (self.build_options_contents.len() > 0) {
const build_options_file = try fs.path.join(
builder.allocator,
[][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", self.name) },
[_][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", self.name) },
);
try std.io.writeFile(build_options_file, self.build_options_contents.toSliceConst());
try zig_args.append("--pkg-begin");
@ -1737,7 +1737,7 @@ const InstallArtifactStep = struct {
.artifact = artifact,
.dest_file = fs.path.join(
builder.allocator,
[][]const u8{ dest_dir, artifact.out_filename },
[_][]const u8{ dest_dir, artifact.out_filename },
) catch unreachable,
};
self.step.dependOn(&artifact.step);
@ -1745,11 +1745,11 @@ const InstallArtifactStep = struct {
if (self.artifact.kind == LibExeObjStep.Kind.Lib and self.artifact.is_dynamic) {
builder.pushInstalledFile(fs.path.join(
builder.allocator,
[][]const u8{ builder.lib_dir, artifact.major_only_filename },
[_][]const u8{ builder.lib_dir, artifact.major_only_filename },
) catch unreachable);
builder.pushInstalledFile(fs.path.join(
builder.allocator,
[][]const u8{ builder.lib_dir, artifact.name_only_filename },
[_][]const u8{ builder.lib_dir, artifact.name_only_filename },
) catch unreachable);
}
return self;
@ -1909,7 +1909,7 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj
// sym link for libfoo.so.1 to libfoo.so.1.2.3
const major_only_path = fs.path.join(
allocator,
[][]const u8{ out_dir, filename_major_only },
[_][]const u8{ out_dir, filename_major_only },
) catch unreachable;
fs.atomicSymLink(allocator, out_basename, major_only_path) catch |err| {
warn("Unable to symlink {} -> {}\n", major_only_path, out_basename);
@ -1918,7 +1918,7 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj
// sym link for libfoo.so to libfoo.so.1
const name_only_path = fs.path.join(
allocator,
[][]const u8{ out_dir, filename_name_only },
[_][]const u8{ out_dir, filename_name_only },
) catch unreachable;
fs.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| {
warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only);

View File

@ -37,7 +37,7 @@ const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header;
pub extern "c" var _mh_execute_header: mach_hdr = undefined;
comptime {
if (std.os.darwin.is_the_target) {
@export("__mh_execute_header", _mh_execute_header, .Weak);
@export("_mh_execute_header", _mh_execute_header, .Weak);
}
}

View File

@ -13,7 +13,7 @@ const BufMap = std.BufMap;
const Buffer = std.Buffer;
const builtin = @import("builtin");
const Os = builtin.Os;
const LinkedList = std.LinkedList;
const TailQueue = std.TailQueue;
const maxInt = std.math.maxInt;
pub const ChildProcess = struct {
@ -48,7 +48,7 @@ pub const ChildProcess = struct {
pub cwd: ?[]const u8,
err_pipe: if (os.windows.is_the_target) void else [2]os.fd_t,
llnode: if (os.windows.is_the_target) void else LinkedList(*ChildProcess).Node,
llnode: if (os.windows.is_the_target) void else TailQueue(*ChildProcess).Node,
pub const SpawnError = error{OutOfMemory} || os.ExecveError || os.SetIdError ||
os.ChangeCurDirError || windows.CreateProcessError;
@ -388,7 +388,7 @@ pub const ChildProcess = struct {
self.pid = pid;
self.err_pipe = err_pipe;
self.llnode = LinkedList(*ChildProcess).Node.init(self);
self.llnode = TailQueue(*ChildProcess).Node.init(self);
self.term = null;
if (self.stdin_behavior == StdIo.Pipe) {
@ -523,7 +523,7 @@ pub const ChildProcess = struct {
// to match posix semantics
const app_name = x: {
if (self.cwd) |cwd| {
const resolved = try fs.path.resolve(self.allocator, [][]const u8{ cwd, self.argv[0] });
const resolved = try fs.path.resolve(self.allocator, [_][]const u8{ cwd, self.argv[0] });
defer self.allocator.free(resolved);
break :x try cstr.addNullByte(self.allocator, resolved);
} else {
@ -543,25 +543,32 @@ pub const ChildProcess = struct {
const PATH = try process.getEnvVarOwned(self.allocator, "PATH");
defer self.allocator.free(PATH);
const PATHEXT = try process.getEnvVarOwned(self.allocator, "PATHEXT");
defer self.allocator.free(PATHEXT);
var it = mem.tokenize(PATH, ";");
while (it.next()) |search_path| {
const joined_path = try fs.path.join(self.allocator, [][]const u8{ search_path, app_name });
defer self.allocator.free(joined_path);
retry: while (it.next()) |search_path| {
var ext_it = mem.tokenize(PATHEXT, ";");
while (ext_it.next()) |app_ext| {
const app_basename = try mem.concat(self.allocator, u8, [_][]const u8{app_name[0..app_name.len - 1], app_ext});
defer self.allocator.free(app_basename);
const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, joined_path);
defer self.allocator.free(joined_path_w);
const joined_path = try fs.path.join(self.allocator, [_][]const u8{ search_path, app_basename });
defer self.allocator.free(joined_path);
if (windowsCreateProcess(joined_path_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo)) |_| {
break;
} else |err| if (err == error.FileNotFound) {
continue;
} else {
return err;
const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, joined_path);
defer self.allocator.free(joined_path_w);
if (windowsCreateProcess(joined_path_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo)) |_| {
break :retry;
} else |err| switch (err) {
error.FileNotFound => { continue; },
error.AccessDenied => { continue; },
else => { return err; },
}
}
} else {
// Every other error would have been returned earlier.
return error.FileNotFound;
return no_path_err; // return the original error
}
};

View File

@ -57,7 +57,7 @@ pub const Coff = struct {
var pe_header_magic: [4]u8 = undefined;
try in.readNoEof(pe_header_magic[0..]);
if (!mem.eql(u8, pe_header_magic, []u8{ 'P', 'E', 0, 0 }))
if (!mem.eql(u8, pe_header_magic, [_]u8{ 'P', 'E', 0, 0 }))
return error.InvalidPEHeader;
self.coff_header = CoffHeader{

View File

@ -13,6 +13,8 @@ pub const Sha3_256 = sha3.Sha3_256;
pub const Sha3_384 = sha3.Sha3_384;
pub const Sha3_512 = sha3.Sha3_512;
pub const gimli = @import("crypto/gimli.zig");
const blake2 = @import("crypto/blake2.zig");
pub const Blake2s224 = blake2.Blake2s224;
pub const Blake2s256 = blake2.Blake2s256;
@ -38,6 +40,7 @@ pub const randomBytes = std.os.getrandom;
test "crypto" {
_ = @import("crypto/blake2.zig");
_ = @import("crypto/chacha20.zig");
_ = @import("crypto/gimli.zig");
_ = @import("crypto/hmac.zig");
_ = @import("crypto/md5.zig");
_ = @import("crypto/poly1305.zig");

View File

@ -49,16 +49,16 @@ fn Blake2s(comptime out_len: usize) type {
};
const sigma = [10][16]u8{
[]const u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[]const u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
[]const u8{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
[]const u8{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
[]const u8{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
[]const u8{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
[]const u8{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
[]const u8{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
[]const u8{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
[]const u8{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
[_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[_]u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
[_]u8{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
[_]u8{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
[_]u8{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
[_]u8{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
[_]u8{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
[_]u8{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
[_]u8{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
[_]u8{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
};
h: [8]u32,
@ -149,7 +149,7 @@ fn Blake2s(comptime out_len: usize) type {
v[13] ^= @intCast(u32, d.t >> 32);
if (last) v[14] = ~v[14];
const rounds = comptime []RoundParam{
const rounds = comptime [_]RoundParam{
Rp(0, 4, 8, 12, 0, 1),
Rp(1, 5, 9, 13, 2, 3),
Rp(2, 6, 10, 14, 4, 5),
@ -252,7 +252,7 @@ test "blake2s256 streaming" {
}
test "blake2s256 aligned final" {
var block = []u8{0} ** Blake2s256.block_length;
var block = [_]u8{0} ** Blake2s256.block_length;
var out: [Blake2s256.digest_length]u8 = undefined;
var h = Blake2s256.init();
@ -284,18 +284,18 @@ fn Blake2b(comptime out_len: usize) type {
};
const sigma = [12][16]u8{
[]const u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[]const u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
[]const u8{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
[]const u8{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
[]const u8{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
[]const u8{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
[]const u8{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
[]const u8{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
[]const u8{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
[]const u8{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
[]const u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[]const u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
[_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[_]u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
[_]u8{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
[_]u8{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
[_]u8{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
[_]u8{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
[_]u8{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
[_]u8{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
[_]u8{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
[_]u8{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
[_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[_]u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
};
h: [8]u64,
@ -383,7 +383,7 @@ fn Blake2b(comptime out_len: usize) type {
v[13] ^= @intCast(u64, d.t >> 64);
if (last) v[14] = ~v[14];
const rounds = comptime []RoundParam{
const rounds = comptime [_]RoundParam{
Rp(0, 4, 8, 12, 0, 1),
Rp(1, 5, 9, 13, 2, 3),
Rp(2, 6, 10, 14, 4, 5),
@ -486,7 +486,7 @@ test "blake2b512 streaming" {
}
test "blake2b512 aligned final" {
var block = []u8{0} ** Blake2b512.block_length;
var block = [_]u8{0} ** Blake2b512.block_length;
var out: [Blake2b512.digest_length]u8 = undefined;
var h = Blake2b512.init();

View File

@ -33,7 +33,7 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
for (x) |_, i|
x[i] = input[i];
const rounds = comptime []QuarterRound{
const rounds = comptime [_]QuarterRound{
Rp(0, 4, 8, 12),
Rp(1, 5, 9, 13),
Rp(2, 6, 10, 14),
@ -71,7 +71,7 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
var cursor: usize = 0;
const c = "expand 32-byte k";
const constant_le = []u32{
const constant_le = [_]u32{
mem.readIntSliceLittle(u32, c[0..4]),
mem.readIntSliceLittle(u32, c[4..8]),
mem.readIntSliceLittle(u32, c[8..12]),
@ -186,7 +186,7 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
// https://tools.ietf.org/html/rfc7539#section-2.4.2
test "crypto.chacha20 test vector sunscreen" {
const expected_result = []u8{
const expected_result = [_]u8{
0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80,
0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81,
0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2,
@ -205,13 +205,13 @@ test "crypto.chacha20 test vector sunscreen" {
};
const input = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
var result: [114]u8 = undefined;
const key = []u8{
const key = [_]u8{
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
};
const nonce = []u8{
const nonce = [_]u8{
0, 0, 0, 0,
0, 0, 0, 0x4a,
0, 0, 0, 0,
@ -228,7 +228,7 @@ test "crypto.chacha20 test vector sunscreen" {
// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
test "crypto.chacha20 test vector 1" {
const expected_result = []u8{
const expected_result = [_]u8{
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
@ -238,7 +238,7 @@ test "crypto.chacha20 test vector 1" {
0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
};
const input = []u8{
const input = [_]u8{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -249,20 +249,20 @@ test "crypto.chacha20 test vector 1" {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
var result: [64]u8 = undefined;
const key = []u8{
const key = [_]u8{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
testing.expectEqualSlices(u8, expected_result, result);
}
test "crypto.chacha20 test vector 2" {
const expected_result = []u8{
const expected_result = [_]u8{
0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
@ -272,7 +272,7 @@ test "crypto.chacha20 test vector 2" {
0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
};
const input = []u8{
const input = [_]u8{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -283,20 +283,20 @@ test "crypto.chacha20 test vector 2" {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
var result: [64]u8 = undefined;
const key = []u8{
const key = [_]u8{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1,
};
const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
testing.expectEqualSlices(u8, expected_result, result);
}
test "crypto.chacha20 test vector 3" {
const expected_result = []u8{
const expected_result = [_]u8{
0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
@ -306,7 +306,7 @@ test "crypto.chacha20 test vector 3" {
0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
0x44, 0x5f, 0x41, 0xe3,
};
const input = []u8{
const input = [_]u8{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -317,20 +317,20 @@ test "crypto.chacha20 test vector 3" {
0x00, 0x00, 0x00, 0x00,
};
var result: [60]u8 = undefined;
const key = []u8{
const key = [_]u8{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 1 };
const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 1 };
chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
testing.expectEqualSlices(u8, expected_result, result);
}
test "crypto.chacha20 test vector 4" {
const expected_result = []u8{
const expected_result = [_]u8{
0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
@ -340,7 +340,7 @@ test "crypto.chacha20 test vector 4" {
0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
};
const input = []u8{
const input = [_]u8{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -351,20 +351,20 @@ test "crypto.chacha20 test vector 4" {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
var result: [64]u8 = undefined;
const key = []u8{
const key = [_]u8{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const nonce = []u8{ 1, 0, 0, 0, 0, 0, 0, 0 };
const nonce = [_]u8{ 1, 0, 0, 0, 0, 0, 0, 0 };
chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
testing.expectEqualSlices(u8, expected_result, result);
}
test "crypto.chacha20 test vector 5" {
const expected_result = []u8{
const expected_result = [_]u8{
0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
@ -401,7 +401,7 @@ test "crypto.chacha20 test vector 5" {
0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
};
const input = []u8{
const input = [_]u8{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -421,13 +421,13 @@ test "crypto.chacha20 test vector 5" {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
var result: [256]u8 = undefined;
const key = []u8{
const key = [_]u8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
const nonce = []u8{
const nonce = [_]u8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
};

168
std/crypto/gimli.zig Normal file
View File

@ -0,0 +1,168 @@
// Gimli is a 384-bit permutation designed to achieve high security with high
// performance across a broad range of platforms, including 64-bit Intel/AMD
// server CPUs, 64-bit and 32-bit ARM smartphone CPUs, 32-bit ARM
// microcontrollers, 8-bit AVR microcontrollers, FPGAs, ASICs without
// side-channel protection, and ASICs with side-channel protection.
//
// https://gimli.cr.yp.to/
// https://csrc.nist.gov/CSRC/media/Projects/Lightweight-Cryptography/documents/round-1/spec-doc/gimli-spec.pdf
const std = @import("../std.zig");
const mem = std.mem;
const math = std.math;
const debug = std.debug;
const assert = std.debug.assert;
const testing = std.testing;
const htest = @import("test.zig");
pub const State = struct {
pub const BLOCKBYTES = 48;
pub const RATE = 16;
// TODO: https://github.com/ziglang/zig/issues/2673#issuecomment-501763017
data: [BLOCKBYTES / 4]u32,
const Self = @This();
pub fn toSlice(self: *Self) []u8 {
return @sliceToBytes(self.data[0..]);
}
pub fn toSliceConst(self: *Self) []const u8 {
return @sliceToBytes(self.data[0..]);
}
pub fn permute(self: *Self) void {
const state = &self.data;
var round = u32(24);
while (round > 0) : (round -= 1) {
var column = usize(0);
while (column < 4) : (column += 1) {
const x = math.rotl(u32, state[column], 24);
const y = math.rotl(u32, state[4 + column], 9);
const z = state[8 + column];
state[8 + column] = ((x ^ (z << 1)) ^ ((y & z) << 2));
state[4 + column] = ((y ^ x) ^ ((x | z) << 1));
state[column] = ((z ^ y) ^ ((x & y) << 3));
}
switch (round & 3) {
0 => {
mem.swap(u32, &state[0], &state[1]);
mem.swap(u32, &state[2], &state[3]);
state[0] ^= round | 0x9e377900;
},
2 => {
mem.swap(u32, &state[0], &state[2]);
mem.swap(u32, &state[1], &state[3]);
},
else => {},
}
}
}
pub fn squeeze(self: *Self, out: []u8) void {
var i = usize(0);
while (i + RATE <= out.len) : (i += RATE) {
self.permute();
mem.copy(u8, out[i..], self.toSliceConst()[0..RATE]);
}
const leftover = out.len - i;
if (leftover != 0) {
self.permute();
mem.copy(u8, out[i..], self.toSliceConst()[0..leftover]);
}
}
};
test "permute" {
// test vector from gimli-20170627
var state = State{
.data = blk: {
var input: [12]u32 = undefined;
var i = u32(0);
while (i < 12) : (i += 1) {
input[i] = i * i * i + i *% 0x9e3779b9;
}
testing.expectEqualSlices(u32, input, [_]u32{
0x00000000, 0x9e3779ba, 0x3c6ef37a, 0xdaa66d46,
0x78dde724, 0x1715611a, 0xb54cdb2e, 0x53845566,
0xf1bbcfc8, 0x8ff34a5a, 0x2e2ac522, 0xcc624026,
});
break :blk input;
},
};
state.permute();
testing.expectEqualSlices(u32, state.data, [_]u32{
0xba11c85a, 0x91bad119, 0x380ce880, 0xd24c2c68,
0x3eceffea, 0x277a921c, 0x4f73a0bd, 0xda5a9cd8,
0x84b673f0, 0x34e52ff7, 0x9e2bef49, 0xf41bb8d6,
});
}
pub const Hash = struct {
state: State,
buf_off: usize,
const Self = @This();
pub fn init() Self {
return Self{
.state = State{
.data = [_]u32{0} ** (State.BLOCKBYTES / 4),
},
.buf_off = 0,
};
}
/// Also known as 'absorb'
pub fn update(self: *Self, data: []const u8) void {
const buf = self.state.toSlice();
var in = data;
while (in.len > 0) {
var left = State.RATE - self.buf_off;
if (left == 0) {
self.state.permute();
self.buf_off = 0;
left = State.RATE;
}
const ps = math.min(in.len, left);
for (buf[self.buf_off .. self.buf_off + ps]) |*p, i| {
p.* ^= in[i];
}
self.buf_off += ps;
in = in[ps..];
}
}
/// Finish the current hashing operation, writing the hash to `out`
///
/// From 4.9 "Application to hashing"
/// By default, Gimli-Hash provides a fixed-length output of 32 bytes
/// (the concatenation of two 16-byte blocks). However, Gimli-Hash can
/// be used as an extendable one-way function (XOF).
pub fn final(self: *Self, out: []u8) void {
const buf = self.state.toSlice();
// XOR 1 into the next byte of the state
buf[self.buf_off] ^= 1;
// XOR 1 into the last byte of the state, position 47.
buf[buf.len - 1] ^= 1;
self.state.squeeze(out);
}
};
pub fn hash(out: []u8, in: []const u8) void {
var st = Hash.init();
st.update(in);
st.final(out);
}
test "hash" {
// a test vector (30) from NIST KAT submission.
var msg: [58 / 2]u8 = undefined;
try std.fmt.hexToBytes(&msg, "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C");
var md: [32]u8 = undefined;
hash(&md, msg);
htest.assertEqual("1C9A03DC6A5DDC5444CFC6F4B154CFF5CF081633B2CEA4D7D0AE7CCFED5AAA44", md);
}

View File

@ -132,14 +132,14 @@ pub const Md5 = struct {
s[i] |= u32(b[i * 4 + 3]) << 24;
}
var v: [4]u32 = []u32{
var v: [4]u32 = [_]u32{
d.s[0],
d.s[1],
d.s[2],
d.s[3],
};
const round0 = comptime []RoundParam{
const round0 = comptime [_]RoundParam{
Rp(0, 1, 2, 3, 0, 7, 0xD76AA478),
Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756),
Rp(2, 3, 0, 1, 2, 17, 0x242070DB),
@ -162,7 +162,7 @@ pub const Md5 = struct {
v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
}
const round1 = comptime []RoundParam{
const round1 = comptime [_]RoundParam{
Rp(0, 1, 2, 3, 1, 5, 0xF61E2562),
Rp(3, 0, 1, 2, 6, 9, 0xC040B340),
Rp(2, 3, 0, 1, 11, 14, 0x265E5A51),
@ -185,7 +185,7 @@ pub const Md5 = struct {
v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
}
const round2 = comptime []RoundParam{
const round2 = comptime [_]RoundParam{
Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942),
Rp(3, 0, 1, 2, 8, 11, 0x8771F681),
Rp(2, 3, 0, 1, 11, 16, 0x6D9D6122),
@ -208,7 +208,7 @@ pub const Md5 = struct {
v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
}
const round3 = comptime []RoundParam{
const round3 = comptime [_]RoundParam{
Rp(0, 1, 2, 3, 0, 6, 0xF4292244),
Rp(3, 0, 1, 2, 7, 10, 0x432AFF97),
Rp(2, 3, 0, 1, 14, 15, 0xAB9423A7),
@ -272,7 +272,7 @@ test "md5 streaming" {
}
test "md5 aligned final" {
var block = []u8{0} ** Md5.block_length;
var block = [_]u8{0} ** Md5.block_length;
var out: [Md5.digest_length]u8 = undefined;
var h = Md5.init();

View File

@ -119,7 +119,7 @@ pub const Sha1 = struct {
var s: [16]u32 = undefined;
var v: [5]u32 = []u32{
var v: [5]u32 = [_]u32{
d.s[0],
d.s[1],
d.s[2],
@ -127,7 +127,7 @@ pub const Sha1 = struct {
d.s[4],
};
const round0a = comptime []RoundParam{
const round0a = comptime [_]RoundParam{
Rp(0, 1, 2, 3, 4, 0),
Rp(4, 0, 1, 2, 3, 1),
Rp(3, 4, 0, 1, 2, 2),
@ -152,7 +152,7 @@ pub const Sha1 = struct {
v[r.b] = math.rotl(u32, v[r.b], u32(30));
}
const round0b = comptime []RoundParam{
const round0b = comptime [_]RoundParam{
Rp(4, 0, 1, 2, 3, 16),
Rp(3, 4, 0, 1, 2, 17),
Rp(2, 3, 4, 0, 1, 18),
@ -166,7 +166,7 @@ pub const Sha1 = struct {
v[r.b] = math.rotl(u32, v[r.b], u32(30));
}
const round1 = comptime []RoundParam{
const round1 = comptime [_]RoundParam{
Rp(0, 1, 2, 3, 4, 20),
Rp(4, 0, 1, 2, 3, 21),
Rp(3, 4, 0, 1, 2, 22),
@ -196,7 +196,7 @@ pub const Sha1 = struct {
v[r.b] = math.rotl(u32, v[r.b], u32(30));
}
const round2 = comptime []RoundParam{
const round2 = comptime [_]RoundParam{
Rp(0, 1, 2, 3, 4, 40),
Rp(4, 0, 1, 2, 3, 41),
Rp(3, 4, 0, 1, 2, 42),
@ -226,7 +226,7 @@ pub const Sha1 = struct {
v[r.b] = math.rotl(u32, v[r.b], u32(30));
}
const round3 = comptime []RoundParam{
const round3 = comptime [_]RoundParam{
Rp(0, 1, 2, 3, 4, 60),
Rp(4, 0, 1, 2, 3, 61),
Rp(3, 4, 0, 1, 2, 62),
@ -293,7 +293,7 @@ test "sha1 streaming" {
}
test "sha1 aligned final" {
var block = []u8{0} ** Sha1.block_length;
var block = [_]u8{0} ** Sha1.block_length;
var out: [Sha1.digest_length]u8 = undefined;
var h = Sha1.init();

View File

@ -189,7 +189,7 @@ fn Sha2_32(comptime params: Sha2Params32) type {
s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u32, s[i - 15], u32(7)) ^ math.rotr(u32, s[i - 15], u32(18)) ^ (s[i - 15] >> 3)) +% (math.rotr(u32, s[i - 2], u32(17)) ^ math.rotr(u32, s[i - 2], u32(19)) ^ (s[i - 2] >> 10));
}
var v: [8]u32 = []u32{
var v: [8]u32 = [_]u32{
d.s[0],
d.s[1],
d.s[2],
@ -200,7 +200,7 @@ fn Sha2_32(comptime params: Sha2Params32) type {
d.s[7],
};
const round0 = comptime []RoundParam256{
const round0 = comptime [_]RoundParam256{
Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98),
Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491),
Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF),
@ -339,7 +339,7 @@ test "sha256 streaming" {
}
test "sha256 aligned final" {
var block = []u8{0} ** Sha256.block_length;
var block = [_]u8{0} ** Sha256.block_length;
var out: [Sha256.digest_length]u8 = undefined;
var h = Sha256.init();
@ -535,7 +535,7 @@ fn Sha2_64(comptime params: Sha2Params64) type {
s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u64, s[i - 15], u64(1)) ^ math.rotr(u64, s[i - 15], u64(8)) ^ (s[i - 15] >> 7)) +% (math.rotr(u64, s[i - 2], u64(19)) ^ math.rotr(u64, s[i - 2], u64(61)) ^ (s[i - 2] >> 6));
}
var v: [8]u64 = []u64{
var v: [8]u64 = [_]u64{
d.s[0],
d.s[1],
d.s[2],
@ -546,7 +546,7 @@ fn Sha2_64(comptime params: Sha2Params64) type {
d.s[7],
};
const round0 = comptime []RoundParam512{
const round0 = comptime [_]RoundParam512{
Rp512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22),
Rp512(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x7137449123EF65CD),
Rp512(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCFEC4D3B2F),
@ -717,7 +717,7 @@ test "sha512 streaming" {
}
test "sha512 aligned final" {
var block = []u8{0} ** Sha512.block_length;
var block = [_]u8{0} ** Sha512.block_length;
var out: [Sha512.digest_length]u8 = undefined;
var h = Sha512.init();

View File

@ -86,7 +86,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
};
}
const RC = []const u64{
const RC = [_]u64{
0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
@ -95,15 +95,15 @@ const RC = []const u64{
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
};
const ROTC = []const usize{
const ROTC = [_]usize{
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
};
const PIL = []const usize{
const PIL = [_]usize{
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
};
const M5 = []const usize{
const M5 = [_]usize{
0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
};
@ -115,9 +115,9 @@ fn keccak_f(comptime F: usize, d: []u8) void {
break :x 12 + 2 * math.log2(B);
};
var s = []const u64{0} ** 25;
var t = []const u64{0} ** 1;
var c = []const u64{0} ** 5;
var s = [_]u64{0} ** 25;
var t = [_]u64{0} ** 1;
var c = [_]u64{0} ** 5;
for (s) |*r, i| {
r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]);
@ -225,7 +225,7 @@ test "sha3-256 streaming" {
}
test "sha3-256 aligned final" {
var block = []u8{0} ** Sha3_256.block_length;
var block = [_]u8{0} ** Sha3_256.block_length;
var out: [Sha3_256.digest_length]u8 = undefined;
var h = Sha3_256.init();
@ -296,7 +296,7 @@ test "sha3-512 streaming" {
}
test "sha3-512 aligned final" {
var block = []u8{0} ** Sha3_512.block_length;
var block = [_]u8{0} ** Sha3_512.block_length;
var out: [Sha3_512.digest_length]u8 = undefined;
var h = Sha3_512.init();

View File

@ -116,7 +116,7 @@ pub const X25519 = struct {
}
pub fn createPublicKey(public_key: []u8, private_key: []const u8) bool {
var base_point = []u8{9} ++ []u8{0} ** 31;
var base_point = [_]u8{9} ++ [_]u8{0} ** 31;
return create(public_key, private_key, base_point);
}
};

View File

@ -85,8 +85,8 @@ fn wantTtyColor() bool {
/// TODO multithreaded awareness
pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
const stderr = getStderrStream() catch return;
if (os.wasi.is_the_target) {
stderr.print("Unable to dump stack trace: unimplemented on WASI\n") catch return;
if (builtin.strip_debug_info) {
stderr.print("Unable to dump stack trace: debug info stripped\n") catch return;
return;
}
const debug_info = getSelfDebugInfo() catch |err| {
@ -151,8 +151,8 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace
/// TODO multithreaded awareness
pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void {
const stderr = getStderrStream() catch return;
if (os.wasi.is_the_target) {
stderr.print("Unable to dump stack trace: unimplemented on WASI\n") catch return;
if (builtin.strip_debug_info) {
stderr.print("Unable to dump stack trace: debug info stripped\n") catch return;
return;
}
const debug_info = getSelfDebugInfo() catch |err| {
@ -223,6 +223,7 @@ pub fn writeStackTrace(
debug_info: *DebugInfo,
tty_color: bool,
) !void {
if (builtin.strip_debug_info) return error.MissingDebugInfo;
var frame_index: usize = 0;
var frames_left: usize = std.math.min(stack_trace.index, stack_trace.instruction_addresses.len);
@ -783,6 +784,8 @@ pub const OpenSelfDebugInfoError = error{
};
pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
if (builtin.strip_debug_info)
return error.MissingDebugInfo;
if (windows.is_the_target) {
return openSelfDebugInfoWindows(allocator);
}
@ -820,7 +823,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
const len = try di.coff.getPdbPath(path_buf[0..]);
const raw_path = path_buf[0..len];
const path = try fs.path.resolve(allocator, [][]const u8{raw_path});
const path = try fs.path.resolve(allocator, [_][]const u8{raw_path});
try di.pdb.openFile(di.coff, path);
@ -1418,7 +1421,7 @@ const LineNumberProgram = struct {
return error.InvalidDebugInfo;
} else
self.include_dirs[file_entry.dir_index];
const file_name = try fs.path.join(self.file_entries.allocator, [][]const u8{ dir_name, file_entry.file_name });
const file_name = try fs.path.join(self.file_entries.allocator, [_][]const u8{ dir_name, file_entry.file_name });
errdefer self.file_entries.allocator.free(file_name);
return LineInfo{
.line = if (self.prev_line >= 0) @intCast(u64, self.prev_line) else 0,
@ -2224,8 +2227,9 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
// TODO https://github.com/ziglang/zig/issues/863
const result = mem.readIntSlice(T, ptr.*[0..@sizeOf(T)], endian);
ptr.* += @sizeOf(T);
const size = (T.bit_count + 7) / 8;
const result = mem.readIntSlice(T, ptr.*[0..size], endian);
ptr.* += size;
return result;
}
@ -2279,13 +2283,11 @@ var global_allocator_mem: [100 * 1024]u8 = undefined;
/// TODO multithreaded awareness
var debug_info_allocator: ?*mem.Allocator = null;
var debug_info_direct_allocator: std.heap.DirectAllocator = undefined;
var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined;
fn getDebugInfoAllocator() *mem.Allocator {
if (debug_info_allocator) |a| return a;
debug_info_direct_allocator = std.heap.DirectAllocator.init();
debug_info_arena_allocator = std.heap.ArenaAllocator.init(&debug_info_direct_allocator.allocator);
debug_info_arena_allocator = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
debug_info_allocator = &debug_info_arena_allocator.allocator;
return &debug_info_arena_allocator.allocator;
}

View File

@ -324,10 +324,7 @@ test "std.event.Channel" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
var da = std.heap.DirectAllocator.init();
defer da.deinit();
const allocator = &da.allocator;
const allocator = std.heap.direct_allocator;
var loop: Loop = undefined;
// TODO make a multi threaded test

View File

@ -698,7 +698,7 @@ pub async fn readFile(loop: *Loop, file_path: []const u8, max_size: usize) ![]u8
while (true) {
try list.ensureCapacity(list.len + mem.page_size);
const buf = list.items[list.len..];
const buf_array = [][]u8{buf};
const buf_array = [_][]u8{buf};
const amt = try await (async preadv(loop, fd, buf_array, list.len) catch unreachable);
list.len += amt;
if (list.len > max_size) {
@ -887,7 +887,7 @@ pub fn Watch(comptime V: type) type {
}
async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V {
const resolved_path = try std.fs.path.resolve(self.channel.loop.allocator, [][]const u8{file_path});
const resolved_path = try std.fs.path.resolve(self.channel.loop.allocator, [_][]const u8{file_path});
var resolved_path_consumed = false;
defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);
@ -1310,10 +1310,7 @@ const test_tmp_dir = "std_event_fs_test";
// TODO this test is disabled until the coroutine rewrite is finished.
//test "write a file, watch it, write it again" {
// return error.SkipZigTest;
// var da = std.heap.DirectAllocator.init();
// defer da.deinit();
//
// const allocator = &da.allocator;
// const allocator = std.heap.direct_allocator;
//
// // TODO move this into event loop too
// try os.makePath(allocator, test_tmp_dir);

View File

@ -88,10 +88,7 @@ test "std.event.Future" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded or builtin.os != builtin.Os.linux) return error.SkipZigTest;
var da = std.heap.DirectAllocator.init();
defer da.deinit();
const allocator = &da.allocator;
const allocator = std.heap.direct_allocator;
var loop: Loop = undefined;
try loop.initMultiThreaded(allocator);

View File

@ -125,10 +125,7 @@ test "std.event.Group" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
var da = std.heap.DirectAllocator.init();
defer da.deinit();
const allocator = &da.allocator;
const allocator = std.heap.direct_allocator;
var loop: Loop = undefined;
try loop.initMultiThreaded(allocator);

View File

@ -126,10 +126,7 @@ test "std.event.Lock" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
var da = std.heap.DirectAllocator.init();
defer da.deinit();
const allocator = &da.allocator;
const allocator = std.heap.direct_allocator;
var loop: Loop = undefined;
try loop.initMultiThreaded(allocator);

View File

@ -143,7 +143,7 @@ pub const Loop = struct {
Thread.SpawnError || os.EpollCtlError || os.KEventError ||
windows.CreateIoCompletionPortError;
const wakeup_bytes = []u8{0x1} ** 8;
const wakeup_bytes = [_]u8{0x1} ** 8;
fn initOsData(self: *Loop, extra_thread_count: usize) InitOsDataError!void {
switch (builtin.os) {
@ -866,10 +866,7 @@ test "std.event.Loop - basic" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded or builtin.os != builtin.Os.linux) return error.SkipZigTest;
var da = std.heap.DirectAllocator.init();
defer da.deinit();
const allocator = &da.allocator;
const allocator = std.heap.direct_allocator;
var loop: Loop = undefined;
try loop.initMultiThreaded(allocator);
@ -882,10 +879,7 @@ test "std.event.Loop - call" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded or builtin.os != builtin.Os.linux) return error.SkipZigTest;
var da = std.heap.DirectAllocator.init();
defer da.deinit();
const allocator = &da.allocator;
const allocator = std.heap.direct_allocator;
var loop: Loop = undefined;
try loop.initMultiThreaded(allocator);

View File

@ -19,7 +19,7 @@ pub const Server = struct {
waiting_for_emfile_node: PromiseNode,
listen_resume_node: event.Loop.ResumeNode,
const PromiseNode = std.LinkedList(promise).Node;
const PromiseNode = std.TailQueue(promise).Node;
pub fn init(loop: *Loop) Server {
// TODO can't initialize handler coroutine here because we need well defined copy elision

View File

@ -215,10 +215,7 @@ test "std.event.RwLock" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded or builtin.os != builtin.Os.linux) return error.SkipZigTest;
var da = std.heap.DirectAllocator.init();
defer da.deinit();
const allocator = &da.allocator;
const allocator = std.heap.direct_allocator;
var loop: Loop = undefined;
try loop.initMultiThreaded(allocator);

View File

@ -13,7 +13,13 @@ pub const default_max_depth = 3;
/// Renders fmt string with args, calling output with slices of bytes.
/// If `output` returns an error, the error is returned from `format` and
/// `output` is not called again.
pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void, comptime fmt: []const u8, args: ...) Errors!void {
pub fn format(
context: var,
comptime Errors: type,
output: fn (@typeOf(context), []const u8) Errors!void,
comptime fmt: []const u8,
args: ...,
) Errors!void {
const State = enum {
Start,
OpenBrace,
@ -28,7 +34,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
inline for (fmt) |c, i| {
switch (state) {
State.Start => switch (c) {
.Start => switch (c) {
'{' => {
if (start_index < i) {
try output(context, fmt[start_index..i]);
@ -45,7 +51,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
},
else => {},
},
State.OpenBrace => switch (c) {
.OpenBrace => switch (c) {
'{' => {
state = State.Start;
start_index = i;
@ -61,14 +67,14 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
state = State.FormatString;
},
},
State.CloseBrace => switch (c) {
.CloseBrace => switch (c) {
'}' => {
state = State.Start;
start_index = i;
},
else => @compileError("Single '}' encountered in format string"),
},
State.FormatString => switch (c) {
.FormatString => switch (c) {
'}' => {
const s = start_index + 1;
try formatType(args[next_arg], fmt[s..i], context, Errors, output, default_max_depth);
@ -78,7 +84,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
},
else => {},
},
State.Pointer => switch (c) {
.Pointer => switch (c) {
'}' => {
try output(context, @typeName(@typeOf(args[next_arg]).Child));
try output(context, "@");
@ -114,88 +120,93 @@ pub fn formatType(
) Errors!void {
const T = @typeOf(value);
switch (@typeInfo(T)) {
builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => {
.ComptimeInt, .Int, .Float => {
return formatValue(value, fmt, context, Errors, output);
},
builtin.TypeId.Void => {
.Void => {
return output(context, "void");
},
builtin.TypeId.Bool => {
.Bool => {
return output(context, if (value) "true" else "false");
},
builtin.TypeId.Optional => {
.Optional => {
if (value) |payload| {
return formatType(payload, fmt, context, Errors, output, max_depth);
} else {
return output(context, "null");
}
},
builtin.TypeId.ErrorUnion => {
.ErrorUnion => {
if (value) |payload| {
return formatType(payload, fmt, context, Errors, output, max_depth);
} else |err| {
return formatType(err, fmt, context, Errors, output, max_depth);
}
},
builtin.TypeId.ErrorSet => {
.ErrorSet => {
try output(context, "error.");
return output(context, @errorName(value));
},
builtin.TypeId.Promise => {
.Promise => {
return format(context, Errors, output, "promise@{x}", @ptrToInt(value));
},
builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
if (comptime std.meta.trait.hasFn("format")(T)) return value.format(fmt, context, Errors, output);
.Enum => {
if (comptime std.meta.trait.hasFn("format")(T)) {
return value.format(fmt, context, Errors, output);
}
try output(context, @typeName(T));
switch (comptime @typeId(T)) {
builtin.TypeId.Enum => {
try output(context, ".");
try formatType(@tagName(value), "", context, Errors, output, max_depth);
return;
},
builtin.TypeId.Struct => {
if (max_depth == 0) {
return output(context, "{ ... }");
}
comptime var field_i = 0;
inline while (field_i < @memberCount(T)) : (field_i += 1) {
if (field_i == 0) {
try output(context, "{ .");
} else {
try output(context, ", .");
}
try output(context, @memberName(T, field_i));
try output(context, " = ");
try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output, max_depth - 1);
}
try output(context, " }");
},
builtin.TypeId.Union => {
if (max_depth == 0) {
return output(context, "{ ... }");
}
const info = @typeInfo(T).Union;
if (info.tag_type) |UnionTagType| {
try output(context, "{ .");
try output(context, @tagName(UnionTagType(value)));
try output(context, " = ");
inline for (info.fields) |u_field| {
if (@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) {
try formatType(@field(value, u_field.name), "", context, Errors, output, max_depth - 1);
}
}
try output(context, " }");
} else {
try format(context, Errors, output, "@{x}", @ptrToInt(&value));
}
},
else => unreachable,
}
return;
try output(context, ".");
return formatType(@tagName(value), "", context, Errors, output, max_depth);
},
builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) {
builtin.TypeInfo.Pointer.Size.One => switch (@typeInfo(ptr_info.child)) {
.Union => {
if (comptime std.meta.trait.hasFn("format")(T)) {
return value.format(fmt, context, Errors, output);
}
try output(context, @typeName(T));
if (max_depth == 0) {
return output(context, "{ ... }");
}
const info = @typeInfo(T).Union;
if (info.tag_type) |UnionTagType| {
try output(context, "{ .");
try output(context, @tagName(UnionTagType(value)));
try output(context, " = ");
inline for (info.fields) |u_field| {
if (@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) {
try formatType(@field(value, u_field.name), "", context, Errors, output, max_depth - 1);
}
}
try output(context, " }");
} else {
try format(context, Errors, output, "@{x}", @ptrToInt(&value));
}
},
.Struct => {
if (comptime std.meta.trait.hasFn("format")(T)) {
return value.format(fmt, context, Errors, output);
}
try output(context, @typeName(T));
if (max_depth == 0) {
return output(context, "{ ... }");
}
comptime var field_i = 0;
inline while (field_i < @memberCount(T)) : (field_i += 1) {
if (field_i == 0) {
try output(context, "{ .");
} else {
try output(context, ", .");
}
try output(context, @memberName(T, field_i));
try output(context, " = ");
try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output, max_depth - 1);
}
try output(context, " }");
},
.Pointer => |ptr_info| switch (ptr_info.size) {
.One => switch (@typeInfo(ptr_info.child)) {
builtin.TypeId.Array => |info| {
if (info.child == u8) {
return formatText(value, fmt, context, Errors, output);
@ -207,7 +218,7 @@ pub fn formatType(
},
else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),
},
builtin.TypeInfo.Pointer.Size.Many => {
.Many => {
if (ptr_info.child == u8) {
if (fmt.len > 0 and fmt[0] == 's') {
const len = mem.len(u8, value);
@ -216,7 +227,7 @@ pub fn formatType(
}
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
},
builtin.TypeInfo.Pointer.Size.Slice => {
.Slice => {
if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
return formatText(value, fmt, context, Errors, output);
}
@ -225,17 +236,17 @@ pub fn formatType(
}
return format(context, Errors, output, "{}@{x}", @typeName(ptr_info.child), @ptrToInt(value.ptr));
},
builtin.TypeInfo.Pointer.Size.C => {
.C => {
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
},
},
builtin.TypeId.Array => |info| {
.Array => |info| {
if (info.child == u8) {
return formatText(value, fmt, context, Errors, output);
}
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
},
builtin.TypeId.Fn => {
.Fn => {
return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value));
},
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
@ -249,24 +260,24 @@ fn formatValue(
comptime Errors: type,
output: fn (@typeOf(context), []const u8) Errors!void,
) Errors!void {
if (fmt.len > 0) {
if (fmt[0] == 'B') {
comptime var width: ?usize = null;
if (fmt.len > 1) {
if (fmt[1] == 'i') {
if (fmt.len > 2) width = comptime (parseUnsigned(usize, fmt[2..], 10) catch unreachable);
return formatBytes(value, width, 1024, context, Errors, output);
if (fmt.len > 0 and fmt[0] == 'B') {
comptime var width: ?usize = null;
if (fmt.len > 1) {
if (fmt[1] == 'i') {
if (fmt.len > 2) {
width = comptime (parseUnsigned(usize, fmt[2..], 10) catch unreachable);
}
width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
return formatBytes(value, width, 1024, context, Errors, output);
}
return formatBytes(value, width, 1000, context, Errors, output);
width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
}
return formatBytes(value, width, 1000, context, Errors, output);
}
const T = @typeOf(value);
switch (@typeId(T)) {
builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
builtin.TypeId.Int, builtin.TypeId.ComptimeInt => return formatIntValue(value, fmt, context, Errors, output),
.Float => return formatFloatValue(value, fmt, context, Errors, output),
.Int, .ComptimeInt => return formatIntValue(value, fmt, context, Errors, output),
else => comptime unreachable,
}
}
@ -293,7 +304,7 @@ pub fn formatIntValue(
'c' => {
if (@typeOf(int_value).bit_count <= 8) {
if (fmt.len > 1)
@compileError("Unknown format character: " ++ []u8{fmt[1]});
@compileError("Unknown format character: " ++ [_]u8{fmt[1]});
return formatAsciiChar(u8(int_value), context, Errors, output);
}
},
@ -317,7 +328,7 @@ pub fn formatIntValue(
uppercase = true;
width = 0;
},
else => @compileError("Unknown format character: " ++ []u8{fmt[0]}),
else => @compileError("Unknown format character: " ++ [_]u8{fmt[0]}),
}
if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
}
@ -341,7 +352,7 @@ fn formatFloatValue(
switch (float_fmt) {
'e' => try formatFloatScientific(value, width, context, Errors, output),
'.' => try formatFloatDecimal(value, width, context, Errors, output),
else => @compileError("Unknown format character: " ++ []u8{float_fmt}),
else => @compileError("Unknown format character: " ++ [_]u8{float_fmt}),
}
}
@ -362,7 +373,7 @@ pub fn formatText(
try formatInt(c, 16, fmt[0] == 'X', 2, context, Errors, output);
}
return;
} else @compileError("Unknown format character: " ++ []u8{fmt[0]});
} else @compileError("Unknown format character: " ++ [_]u8{fmt[0]});
}
return output(context, bytes);
}
@ -668,8 +679,8 @@ pub fn formatBytes(
}
const buf = switch (radix) {
1000 => []u8{ suffix, 'B' },
1024 => []u8{ suffix, 'i', 'B' },
1000 => [_]u8{ suffix, 'B' },
1024 => [_]u8{ suffix, 'i', 'B' },
else => unreachable,
};
return output(context, buf);
@ -797,7 +808,7 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
}
}
test "fmt.parseInt" {
test "parseInt" {
testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
@ -828,7 +839,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
return x;
}
test "fmt.parseUnsigned" {
test "parseUnsigned" {
testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
@ -913,7 +924,7 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
size.* += bytes.len;
}
test "buf print int" {
test "bufPrintInt" {
var buffer: [100]u8 = undefined;
const buf = buffer[0..];
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110"));
@ -949,7 +960,7 @@ test "parse unsigned comptime" {
}
}
test "fmt.format" {
test "fmt.optional" {
{
const value: ?i32 = 1234;
try testFmt("optional: 1234\n", "optional: {}\n", value);
@ -958,6 +969,9 @@ test "fmt.format" {
const value: ?i32 = null;
try testFmt("optional: null\n", "optional: {}\n", value);
}
}
test "fmt.error" {
{
const value: anyerror!i32 = 1234;
try testFmt("error union: 1234\n", "error union: {}\n", value);
@ -966,10 +980,16 @@ test "fmt.format" {
const value: anyerror!i32 = error.InvalidChar;
try testFmt("error union: error.InvalidChar\n", "error union: {}\n", value);
}
}
test "fmt.int.small" {
{
const value: u3 = 0b101;
try testFmt("u3: 5\n", "u3: {}\n", value);
}
}
test "fmt.int.specifier" {
{
const value: u8 = 'a';
try testFmt("u8: a\n", "u8: {c}\n", value);
@ -978,6 +998,9 @@ test "fmt.format" {
const value: u8 = 0b1100;
try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);
}
}
test "fmt.buffer" {
{
var buf1: [32]u8 = undefined;
var context = BufPrintContext{ .remaining = buf1[0..] };
@ -995,6 +1018,9 @@ test "fmt.format" {
res = buf1[0 .. buf1.len - context.remaining.len];
testing.expect(mem.eql(u8, res, "1100"));
}
}
test "fmt.array" {
{
const value: [3]u8 = "abc";
try testFmt("array: abc\n", "array: {}\n", value);
@ -1007,6 +1033,9 @@ test "fmt.format" {
&value,
);
}
}
test "fmt.slice" {
{
const value: []const u8 = "abc";
try testFmt("slice: abc\n", "slice: {}\n", value);
@ -1015,6 +1044,12 @@ test "fmt.format" {
const value = @intToPtr([*]const []const u8, 0xdeadbeef)[0..0];
try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", value);
}
try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
}
test "fmt.pointer" {
{
const value = @intToPtr(*i32, 0xdeadbeef);
try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
@ -1028,12 +1063,19 @@ test "fmt.format" {
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");
}
test "fmt.cstr" {
try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
try testFmt("cstr: Test C \n", "cstr: {s10}\n", c"Test C");
}
test "fmt.filesize" {
try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));
try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024));
}
test "fmt.struct" {
{
const Struct = struct {
field: u8,
@ -1050,15 +1092,19 @@ test "fmt.format" {
const value = Struct{ .a = 0, .b = 1 };
try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", value);
}
{
const Enum = enum {
One,
Two,
};
const value = Enum.Two;
try testFmt("enum: Enum.Two\n", "enum: {}\n", value);
try testFmt("enum: Enum.Two\n", "enum: {}\n", &value);
}
}
test "fmt.enum" {
const Enum = enum {
One,
Two,
};
const value = Enum.Two;
try testFmt("enum: Enum.Two\n", "enum: {}\n", value);
try testFmt("enum: Enum.Two\n", "enum: {}\n", &value);
}
test "fmt.float.scientific" {
{
var buf1: [32]u8 = undefined;
const value: f32 = 1.34;
@ -1088,6 +1134,9 @@ test "fmt.format" {
testing.expect(mem.eql(u8, result, "f64: 9.99996e-40\n"));
}
}
}
test "fmt.float.scientific.precision" {
{
var buf1: [32]u8 = undefined;
const value: f64 = 1.409706e-42;
@ -1114,6 +1163,9 @@ test "fmt.format" {
const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
testing.expect(mem.eql(u8, result, "f64: 1.00001e+05\n"));
}
}
test "fmt.float.special" {
{
var buf1: [32]u8 = undefined;
const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64);
@ -1136,6 +1188,9 @@ test "fmt.format" {
const result = try bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64);
testing.expect(mem.eql(u8, result, "f64: -inf\n"));
}
}
test "fmt.float.decimal" {
{
var buf1: [64]u8 = undefined;
const value: f64 = 1.52314e+29;
@ -1216,7 +1271,9 @@ test "fmt.format" {
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
}
// libc checks
}
test "fmt.float.libc.sanity" {
{
var buf1: [32]u8 = undefined;
const value: f64 = f64(@bitCast(f32, u32(916964781)));
@ -1267,127 +1324,127 @@ test "fmt.format" {
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
testing.expect(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));
}
//custom type format
{
const Vec2 = struct {
const SelfType = @This();
x: f32,
y: f32,
}
pub fn format(
self: SelfType,
comptime fmt: []const u8,
context: var,
comptime Errors: type,
output: fn (@typeOf(context), []const u8) Errors!void,
) Errors!void {
switch (fmt.len) {
0 => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y),
1 => switch (fmt[0]) {
//point format
'p' => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y),
//dimension format
'd' => return std.fmt.format(context, Errors, output, "{.3}x{.3}", self.x, self.y),
else => unreachable,
},
test "fmt.custom" {
const Vec2 = struct {
const SelfType = @This();
x: f32,
y: f32,
pub fn format(
self: SelfType,
comptime fmt: []const u8,
context: var,
comptime Errors: type,
output: fn (@typeOf(context), []const u8) Errors!void,
) Errors!void {
switch (fmt.len) {
0 => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y),
1 => switch (fmt[0]) {
//point format
'p' => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y),
//dimension format
'd' => return std.fmt.format(context, Errors, output, "{.3}x{.3}", self.x, self.y),
else => unreachable,
}
},
else => unreachable,
}
};
}
};
var buf1: [32]u8 = undefined;
var value = Vec2{
.x = 10.2,
.y = 2.22,
};
try testFmt("point: (10.200,2.220)\n", "point: {}\n", &value);
try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", &value);
var buf1: [32]u8 = undefined;
var value = Vec2{
.x = 10.2,
.y = 2.22,
};
try testFmt("point: (10.200,2.220)\n", "point: {}\n", &value);
try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", &value);
// same thing but not passing a pointer
try testFmt("point: (10.200,2.220)\n", "point: {}\n", value);
try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", value);
}
//struct format
{
const S = struct {
a: u32,
b: anyerror,
};
// same thing but not passing a pointer
try testFmt("point: (10.200,2.220)\n", "point: {}\n", value);
try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", value);
}
const inst = S{
.a = 456,
.b = error.Unused,
};
test "fmt.struct" {
const S = struct {
a: u32,
b: anyerror,
};
try testFmt("S{ .a = 456, .b = error.Unused }", "{}", inst);
}
//union format
{
const TU = union(enum) {
float: f32,
int: u32,
};
const inst = S{
.a = 456,
.b = error.Unused,
};
const UU = union {
float: f32,
int: u32,
};
try testFmt("S{ .a = 456, .b = error.Unused }", "{}", inst);
}
const EU = extern union {
float: f32,
int: u32,
};
test "fmt.union" {
const TU = union(enum) {
float: f32,
int: u32,
};
const tu_inst = TU{ .int = 123 };
const uu_inst = UU{ .int = 456 };
const eu_inst = EU{ .float = 321.123 };
const UU = union {
float: f32,
int: u32,
};
try testFmt("TU{ .int = 123 }", "{}", tu_inst);
const EU = extern union {
float: f32,
int: u32,
};
var buf: [100]u8 = undefined;
const uu_result = try bufPrint(buf[0..], "{}", uu_inst);
testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
const tu_inst = TU{ .int = 123 };
const uu_inst = UU{ .int = 456 };
const eu_inst = EU{ .float = 321.123 };
const eu_result = try bufPrint(buf[0..], "{}", eu_inst);
testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
}
//enum format
{
const E = enum {
One,
Two,
Three,
};
try testFmt("TU{ .int = 123 }", "{}", tu_inst);
const inst = E.Two;
var buf: [100]u8 = undefined;
const uu_result = try bufPrint(buf[0..], "{}", uu_inst);
testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
try testFmt("E.Two", "{}", inst);
}
//self-referential struct format
{
const S = struct {
const SelfType = @This();
a: ?*SelfType,
};
const eu_result = try bufPrint(buf[0..], "{}", eu_inst);
testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
}
var inst = S{
.a = null,
};
inst.a = &inst;
test "fmt.enum" {
const E = enum {
One,
Two,
Three,
};
try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst);
}
//print bytes as hex
{
const some_bytes = "\xCA\xFE\xBA\xBE";
try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", some_bytes);
try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", some_bytes);
//Test Slices
try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", some_bytes[0..2]);
try testFmt("lowercase: babe\n", "lowercase: {x}\n", some_bytes[2..]);
const bytes_with_zeros = "\x00\x0E\xBA\xBE";
try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", bytes_with_zeros);
}
const inst = E.Two;
try testFmt("E.Two", "{}", inst);
}
test "fmt.struct.self-referential" {
const S = struct {
const SelfType = @This();
a: ?*SelfType,
};
var inst = S{
.a = null,
};
inst.a = &inst;
try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst);
}
test "fmt.bytes.hex" {
const some_bytes = "\xCA\xFE\xBA\xBE";
try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", some_bytes);
try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", some_bytes);
//Test Slices
try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", some_bytes[0..2]);
try testFmt("lowercase: babe\n", "lowercase: {x}\n", some_bytes[2..]);
const bytes_with_zeros = "\x00\x0E\xBA\xBE";
try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", bytes_with_zeros);
}
fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {

View File

@ -415,7 +415,7 @@ fn fpprev(val: f64) f64 {
return @bitCast(f64, @bitCast(u64, val) -% 1);
}
pub const c_digits_lut = []u8{
pub const c_digits_lut = [_]u8{
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6',
'0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3',
'1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0',

View File

@ -1,4 +1,4 @@
pub const enum3 = []u64{
pub const enum3 = [_]u64{
0x4e2e2785c3a2a20b,
0x240a28877a09a4e1,
0x728fca36c06cf106,
@ -445,7 +445,7 @@ fn slab(str: []const u8, exp: i32) Slab {
};
}
pub const enum3_data = []Slab{
pub const enum3_data = [_]Slab{
slab("40648030339495312", 69),
slab("4498645355592131", -134),
slab("678321594594593", 244),

View File

@ -2,7 +2,7 @@ pub const HP = struct {
val: f64,
off: f64,
};
pub const lookup_table = []HP{
pub const lookup_table = [_]HP{
HP{ .val = 1.000000e+308, .off = -1.097906362944045488e+291 },
HP{ .val = 1.000000e+307, .off = 1.396894023974354241e+290 },
HP{ .val = 1.000000e+306, .off = -1.721606459673645508e+289 },

View File

@ -390,7 +390,7 @@ test "fmt.parseFloat" {
const approxEq = std.math.approxEq;
const epsilon = 1e-7;
inline for ([]type{ f16, f32, f64, f128 }) |T| {
inline for ([_]type{ f16, f32, f64, f128 }) |T| {
const Z = @IntType(false, T.bit_count);
testing.expectError(error.InvalidCharacter, parseFloat(T, ""));

View File

@ -209,7 +209,7 @@ pub fn makeDirW(dir_path: [*]const u16) !void {
/// have been modified regardless.
/// TODO determine if we can remove the allocator requirement from this function
pub fn makePath(allocator: *Allocator, full_path: []const u8) !void {
const resolved_path = try path.resolve(allocator, [][]const u8{full_path});
const resolved_path = try path.resolve(allocator, [_][]const u8{full_path});
defer allocator.free(resolved_path);
var end_index: usize = resolved_path.len;
@ -447,13 +447,13 @@ pub const Dir = struct {
.seek = 0,
.index = 0,
.end_index = 0,
.buf = []u8{},
.buf = [_]u8{},
},
.linux => Handle{
.fd = try os.open(dir_path, os.O_RDONLY | os.O_DIRECTORY | os.O_CLOEXEC, 0),
.index = 0,
.end_index = 0,
.buf = []u8{},
.buf = [_]u8{},
},
else => @compileError("unimplemented"),
},
@ -550,7 +550,7 @@ pub const Dir = struct {
return null;
}
const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);
if (mem.eql(u16, name_utf16le, []u16{'.'}) or mem.eql(u16, name_utf16le, []u16{ '.', '.' }))
if (mem.eql(u16, name_utf16le, [_]u16{'.'}) or mem.eql(u16, name_utf16le, [_]u16{ '.', '.' }))
continue;
// Trust that Windows gives us valid UTF-16LE
const name_utf8_len = std.unicode.utf16leToUtf8(self.handle.name_data[0..], name_utf16le) catch unreachable;

View File

@ -31,7 +31,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
error.OutOfMemory => return error.OutOfMemory,
};
defer allocator.free(global_dir);
return fs.path.join(allocator, [][]const u8{ global_dir, appname });
return fs.path.join(allocator, [_][]const u8{ global_dir, appname });
},
os.windows.E_OUTOFMEMORY => return error.OutOfMemory,
else => return error.AppDataDirUnavailable,
@ -42,14 +42,14 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
// TODO look in /etc/passwd
return error.AppDataDirUnavailable;
};
return fs.path.join(allocator, [][]const u8{ home_dir, "Library", "Application Support", appname });
return fs.path.join(allocator, [_][]const u8{ home_dir, "Library", "Application Support", appname });
},
.linux, .freebsd, .netbsd => {
const home_dir = os.getenv("HOME") orelse {
// TODO look in /etc/passwd
return error.AppDataDirUnavailable;
};
return fs.path.join(allocator, [][]const u8{ home_dir, ".local", "share", appname });
return fs.path.join(allocator, [_][]const u8{ home_dir, ".local", "share", appname });
},
else => @compileError("Unsupported OS"),
}

View File

@ -101,31 +101,31 @@ fn testJoinPosix(paths: []const []const u8, expected: []const u8) void {
}
test "join" {
testJoinWindows([][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c");
testJoinWindows([][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c");
testJoinWindows([][]const u8{ "c:\\a\\b\\", "c" }, "c:\\a\\b\\c");
testJoinWindows([_][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c");
testJoinWindows([_][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c");
testJoinWindows([_][]const u8{ "c:\\a\\b\\", "c" }, "c:\\a\\b\\c");
testJoinWindows([][]const u8{ "c:\\", "a", "b\\", "c" }, "c:\\a\\b\\c");
testJoinWindows([][]const u8{ "c:\\a\\", "b\\", "c" }, "c:\\a\\b\\c");
testJoinWindows([_][]const u8{ "c:\\", "a", "b\\", "c" }, "c:\\a\\b\\c");
testJoinWindows([_][]const u8{ "c:\\a\\", "b\\", "c" }, "c:\\a\\b\\c");
testJoinWindows(
[][]const u8{ "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig" },
[_][]const u8{ "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig" },
"c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig",
);
testJoinPosix([][]const u8{ "/a/b", "c" }, "/a/b/c");
testJoinPosix([][]const u8{ "/a/b/", "c" }, "/a/b/c");
testJoinPosix([_][]const u8{ "/a/b", "c" }, "/a/b/c");
testJoinPosix([_][]const u8{ "/a/b/", "c" }, "/a/b/c");
testJoinPosix([][]const u8{ "/", "a", "b/", "c" }, "/a/b/c");
testJoinPosix([][]const u8{ "/a/", "b/", "c" }, "/a/b/c");
testJoinPosix([_][]const u8{ "/", "a", "b/", "c" }, "/a/b/c");
testJoinPosix([_][]const u8{ "/a/", "b/", "c" }, "/a/b/c");
testJoinPosix(
[][]const u8{ "/home/andy/dev/zig/build/lib/zig/std", "io.zig" },
[_][]const u8{ "/home/andy/dev/zig/build/lib/zig/std", "io.zig" },
"/home/andy/dev/zig/build/lib/zig/std/io.zig",
);
testJoinPosix([][]const u8{ "a", "/c" }, "a/c");
testJoinPosix([][]const u8{ "a/", "/c" }, "a/c");
testJoinPosix([_][]const u8{ "a", "/c" }, "a/c");
testJoinPosix([_][]const u8{ "a/", "/c" }, "a/c");
}
pub fn isAbsolute(path: []const u8) bool {
@ -227,7 +227,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
}
const relative_path = WindowsPath{
.kind = WindowsPath.Kind.None,
.disk_designator = []u8{},
.disk_designator = [_]u8{},
.is_abs = false,
};
if (path.len < "//a/b".len) {
@ -237,13 +237,13 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
// TODO when I combined these together with `inline for` the compiler crashed
{
const this_sep = '/';
const two_sep = []u8{ this_sep, this_sep };
const two_sep = [_]u8{ this_sep, this_sep };
if (mem.startsWith(u8, path, two_sep)) {
if (path[2] == this_sep) {
return relative_path;
}
var it = mem.tokenize(path, []u8{this_sep});
var it = mem.tokenize(path, [_]u8{this_sep});
_ = (it.next() orelse return relative_path);
_ = (it.next() orelse return relative_path);
return WindowsPath{
@ -255,13 +255,13 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
}
{
const this_sep = '\\';
const two_sep = []u8{ this_sep, this_sep };
const two_sep = [_]u8{ this_sep, this_sep };
if (mem.startsWith(u8, path, two_sep)) {
if (path[2] == this_sep) {
return relative_path;
}
var it = mem.tokenize(path, []u8{this_sep});
var it = mem.tokenize(path, [_]u8{this_sep});
_ = (it.next() orelse return relative_path);
_ = (it.next() orelse return relative_path);
return WindowsPath{
@ -323,8 +323,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool {
const sep1 = ns1[0];
const sep2 = ns2[0];
var it1 = mem.tokenize(ns1, []u8{sep1});
var it2 = mem.tokenize(ns2, []u8{sep2});
var it1 = mem.tokenize(ns1, [_]u8{sep1});
var it2 = mem.tokenize(ns2, [_]u8{sep2});
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
return asciiEqlIgnoreCase(it1.next().?, it2.next().?);
@ -344,8 +344,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8
const sep1 = p1[0];
const sep2 = p2[0];
var it1 = mem.tokenize(p1, []u8{sep1});
var it2 = mem.tokenize(p2, []u8{sep2});
var it1 = mem.tokenize(p1, [_]u8{sep1});
var it2 = mem.tokenize(p2, [_]u8{sep2});
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
return asciiEqlIgnoreCase(it1.next().?, it2.next().?) and asciiEqlIgnoreCase(it1.next().?, it2.next().?);
@ -638,10 +638,10 @@ test "resolve" {
if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
cwd[0] = asciiUpper(cwd[0]);
}
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{"."}), cwd));
} else {
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "a/b/c/", "../../.." }), cwd));
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"."}), cwd));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{ "a/b/c/", "../../.." }), cwd));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{"."}), cwd));
}
}
@ -650,8 +650,8 @@ test "resolveWindows" {
const cwd = try process.getCwdAlloc(debug.global_allocator);
const parsed_cwd = windowsParsePath(cwd);
{
const result = testResolveWindows([][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" });
const expected = try join(debug.global_allocator, [][]const u8{
const result = testResolveWindows([_][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" });
const expected = try join(debug.global_allocator, [_][]const u8{
parsed_cwd.disk_designator,
"usr\\local\\lib\\zig\\std\\array_list.zig",
});
@ -661,8 +661,8 @@ test "resolveWindows" {
testing.expect(mem.eql(u8, result, expected));
}
{
const result = testResolveWindows([][]const u8{ "usr/local", "lib\\zig" });
const expected = try join(debug.global_allocator, [][]const u8{
const result = testResolveWindows([_][]const u8{ "usr/local", "lib\\zig" });
const expected = try join(debug.global_allocator, [_][]const u8{
cwd,
"usr\\local\\lib\\zig",
});
@ -673,32 +673,32 @@ test "resolveWindows" {
}
}
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }), "C:\\blah\\a"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }), "C:\\blah\\a"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//" }), "C:\\"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//dir" }), "C:\\dir"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server//share" }), "\\\\server\\share\\"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir"));
testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }), "C:\\blah\\a"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }), "C:\\blah\\a"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:/", "//" }), "C:\\"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:/", "//dir" }), "C:\\dir"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:/", "//server//share" }), "\\\\server\\share\\"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir"));
testing.expect(mem.eql(u8, testResolveWindows([_][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js"));
}
test "resolvePosix" {
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c" }), "/a/b/c"));
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e"));
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b/c", "..", "../" }), "/a"));
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/", "..", ".." }), "/"));
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"/a/b/c/"}), "/a/b/c"));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{ "/a/b", "c" }), "/a/b/c"));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e"));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{ "/a/b/c", "..", "../" }), "/a"));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{ "/", "..", ".." }), "/"));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{"/a/b/c/"}), "/a/b/c"));
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "../", "file/" }), "/var/file"));
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "/../", "file/" }), "/file"));
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute"));
testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js"));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{ "/var/lib", "../", "file/" }), "/var/file"));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{ "/var/lib", "/../", "file/" }), "/file"));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute"));
testing.expect(mem.eql(u8, testResolvePosix([_][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js"));
}
fn testResolveWindows(paths: []const []const u8) []u8 {
@ -853,12 +853,12 @@ pub fn basename(path: []const u8) []const u8 {
pub fn basenamePosix(path: []const u8) []const u8 {
if (path.len == 0)
return []u8{};
return [_]u8{};
var end_index: usize = path.len - 1;
while (path[end_index] == '/') {
if (end_index == 0)
return []u8{};
return [_]u8{};
end_index -= 1;
}
var start_index: usize = end_index;
@ -874,19 +874,19 @@ pub fn basenamePosix(path: []const u8) []const u8 {
pub fn basenameWindows(path: []const u8) []const u8 {
if (path.len == 0)
return []u8{};
return [_]u8{};
var end_index: usize = path.len - 1;
while (true) {
const byte = path[end_index];
if (byte == '/' or byte == '\\') {
if (end_index == 0)
return []u8{};
return [_]u8{};
end_index -= 1;
continue;
}
if (byte == ':' and end_index == 1) {
return []u8{};
return [_]u8{};
}
break;
}
@ -968,11 +968,11 @@ pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {
}
pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {
const resolved_from = try resolveWindows(allocator, [][]const u8{from});
const resolved_from = try resolveWindows(allocator, [_][]const u8{from});
defer allocator.free(resolved_from);
var clean_up_resolved_to = true;
const resolved_to = try resolveWindows(allocator, [][]const u8{to});
const resolved_to = try resolveWindows(allocator, [_][]const u8{to});
defer if (clean_up_resolved_to) allocator.free(resolved_to);
const parsed_from = windowsParsePath(resolved_from);
@ -1037,14 +1037,14 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
return result[0..result_index];
}
return []u8{};
return [_]u8{};
}
pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {
const resolved_from = try resolvePosix(allocator, [][]const u8{from});
const resolved_from = try resolvePosix(allocator, [_][]const u8{from});
defer allocator.free(resolved_from);
const resolved_to = try resolvePosix(allocator, [][]const u8{to});
const resolved_to = try resolvePosix(allocator, [_][]const u8{to});
defer allocator.free(resolved_to);
var from_it = mem.tokenize(resolved_from, "/");
@ -1082,7 +1082,7 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![
return result;
}
return []u8{};
return [_]u8{};
}
test "relative" {

View File

@ -94,14 +94,14 @@ test "adler32 sanity" {
}
test "adler32 long" {
const long1 = []u8{1} ** 1024;
const long1 = [_]u8{1} ** 1024;
testing.expect(Adler32.hash(long1[0..]) == 0x06780401);
const long2 = []u8{1} ** 1025;
const long2 = [_]u8{1} ** 1025;
testing.expect(Adler32.hash(long2[0..]) == 0x0a7a0402);
}
test "adler32 very long" {
const long = []u8{1} ** 5553;
const long = [_]u8{1} ** 5553;
testing.expect(Adler32.hash(long[0..]) == 0x707f15b2);
}

View File

@ -163,7 +163,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 = [][8]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
@ -242,7 +242,7 @@ test "siphash64-2-4 sanity" {
}
test "siphash128-2-4 sanity" {
const vectors = [][16]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",

View File

@ -77,7 +77,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
pub fn init(allocator: *Allocator) Self {
return Self{
.entries = []Entry{},
.entries = [_]Entry{},
.allocator = allocator,
.size = 0,
.max_distance_from_start_index = 0,
@ -157,8 +157,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
fn ensureCapacityExact(self: *Self, new_capacity: usize) !void {
// capacity must always be a power of two to allow for modulo
// optimization in the constrainIndex fn
const is_power_of_two = new_capacity & (new_capacity - 1) == 0;
assert(is_power_of_two);
assert(math.isPowerOfTwo(new_capacity));
if (new_capacity <= self.entries.len) {
return;
@ -184,6 +183,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
return putAssumeCapacity(self, key, value);
}
/// Calls put() and asserts that no kv pair is clobbered.
pub fn putNoClobber(self: *Self, key: K, value: V) !void {
assert((try self.put(key, value)) == null);
}
pub fn putAssumeCapacity(self: *Self, key: K, value: V) ?KV {
assert(self.count() < self.entries.len);
self.incrementModificationCount();
@ -200,10 +204,15 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
return hm.internalGet(key);
}
pub fn getValue(hm: *const Self, key: K) ?V {
return if (hm.get(key)) |kv| kv.value else null;
}
pub fn contains(hm: *const Self, key: K) bool {
return hm.get(key) != null;
}
/// Returns any kv pair that was removed.
pub fn remove(hm: *Self, key: K) ?KV {
if (hm.entries.len == 0) return null;
hm.incrementModificationCount();
@ -237,6 +246,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
return null;
}
/// Calls remove(), asserts that a kv pair is removed, and discards it.
pub fn removeAssertDiscard(hm: *Self, key: K) void {
assert(hm.remove(key) != null);
}
pub fn iterator(hm: *const Self) Iterator {
return Iterator{
.hm = hm,
@ -251,7 +265,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
try other.initCapacity(self.entries.len);
var it = self.iterator();
while (it.next()) |entry| {
assert((try other.put(entry.key, entry.value)) == null);
try other.putNoClobber(entry.key, entry.value);
}
return other;
}
@ -383,18 +397,15 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
}
test "basic hash map usage" {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
var map = AutoHashMap(i32, i32).init(std.heap.direct_allocator);
defer map.deinit();
testing.expect((try map.put(1, 11)) == null);
testing.expect((try map.put(2, 22)) == null);
testing.expect((try map.put(3, 33)) == null);
testing.expect((try map.put(4, 44)) == null);
testing.expect((try map.put(5, 55)) == null);
try map.putNoClobber(5, 55);
testing.expect((try map.put(5, 66)).?.value == 55);
testing.expect((try map.put(5, 55)).?.value == 66);
@ -417,31 +428,32 @@ test "basic hash map usage" {
testing.expect(map.contains(2));
testing.expect(map.get(2).?.value == 22);
testing.expect(map.getValue(2).? == 22);
const rmv1 = map.remove(2);
testing.expect(rmv1.?.key == 2);
testing.expect(rmv1.?.value == 22);
testing.expect(map.remove(2) == null);
testing.expect(map.get(2) == null);
testing.expect(map.getValue(2) == null);
map.removeAssertDiscard(3);
}
test "iterator hash map" {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
var reset_map = AutoHashMap(i32, i32).init(std.heap.direct_allocator);
defer reset_map.deinit();
testing.expect((try reset_map.put(1, 11)) == null);
testing.expect((try reset_map.put(2, 22)) == null);
testing.expect((try reset_map.put(3, 33)) == null);
try reset_map.putNoClobber(1, 11);
try reset_map.putNoClobber(2, 22);
try reset_map.putNoClobber(3, 33);
var keys = []i32{
var keys = [_]i32{
3,
2,
1,
};
var values = []i32{
var values = [_]i32{
33,
22,
11,
@ -473,10 +485,7 @@ test "iterator hash map" {
}
test "ensure capacity" {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
var map = AutoHashMap(i32, i32).init(std.heap.direct_allocator);
defer map.deinit();
try map.ensureCapacity(20);
@ -546,12 +555,12 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
},
builtin.TypeId.Float => |info| {
return autoHash(@bitCast(@IntType(false, info.bits), key), rng);
return autoHash(@bitCast(@IntType(false, info.bits), key), rng, HashInt);
},
builtin.TypeId.Bool => return autoHash(@boolToInt(key), rng),
builtin.TypeId.Enum => return autoHash(@enumToInt(key), rng),
builtin.TypeId.ErrorSet => return autoHash(@errorToInt(key), rng),
builtin.TypeId.Promise, builtin.TypeId.Fn => return autoHash(@ptrToInt(key), rng),
builtin.TypeId.Bool => return autoHash(@boolToInt(key), rng, HashInt),
builtin.TypeId.Enum => return autoHash(@enumToInt(key), rng, HashInt),
builtin.TypeId.ErrorSet => return autoHash(@errorToInt(key), rng, HashInt),
builtin.TypeId.Promise, builtin.TypeId.Fn => return autoHash(@ptrToInt(key), rng, HashInt),
builtin.TypeId.BoundFn,
builtin.TypeId.ComptimeFloat,

View File

@ -31,22 +31,14 @@ fn cShrink(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new
/// This allocator makes a syscall directly for every allocation and free.
/// Thread-safe and lock-free.
pub const DirectAllocator = struct {
allocator: Allocator,
pub fn init() DirectAllocator {
return DirectAllocator{
.allocator = Allocator{
.reallocFn = realloc,
.shrinkFn = shrink,
},
};
}
pub fn deinit(self: *DirectAllocator) void {}
pub const direct_allocator = &direct_allocator_state;
var direct_allocator_state = Allocator{
.reallocFn = DirectAllocator.realloc,
.shrinkFn = DirectAllocator.shrink,
};
const DirectAllocator = struct {
fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
if (n == 0)
return (([*]u8)(undefined))[0..0];
@ -347,10 +339,10 @@ pub const ArenaAllocator = struct {
pub allocator: Allocator,
child_allocator: *Allocator,
buffer_list: std.LinkedList([]u8),
buffer_list: std.SinglyLinkedList([]u8),
end_index: usize,
const BufNode = std.LinkedList([]u8).Node;
const BufNode = std.SinglyLinkedList([]u8).Node;
pub fn init(child_allocator: *Allocator) ArenaAllocator {
return ArenaAllocator{
@ -359,7 +351,7 @@ pub const ArenaAllocator = struct {
.shrinkFn = shrink,
},
.child_allocator = child_allocator,
.buffer_list = std.LinkedList([]u8).init(),
.buffer_list = std.SinglyLinkedList([]u8).init(),
.end_index = 0,
};
}
@ -387,10 +379,9 @@ pub const ArenaAllocator = struct {
const buf_node = &buf_node_slice[0];
buf_node.* = BufNode{
.data = buf,
.prev = null,
.next = null,
};
self.buffer_list.append(buf_node);
self.buffer_list.prepend(buf_node);
self.end_index = 0;
return buf_node;
}
@ -398,7 +389,7 @@ pub const ArenaAllocator = struct {
fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
const self = @fieldParentPtr(ArenaAllocator, "allocator", allocator);
var cur_node = if (self.buffer_list.last) |last_node| last_node else try self.createNode(0, n + alignment);
var cur_node = if (self.buffer_list.first) |first_node| first_node else try self.createNode(0, n + alignment);
while (true) {
const cur_buf = cur_node.data[@sizeOf(BufNode)..];
const addr = @ptrToInt(cur_buf.ptr) + self.end_index;
@ -731,10 +722,7 @@ test "c_allocator" {
}
test "DirectAllocator" {
var direct_allocator = DirectAllocator.init();
defer direct_allocator.deinit();
const allocator = &direct_allocator.allocator;
const allocator = direct_allocator;
try testAllocator(allocator);
try testAllocatorAligned(allocator, 16);
try testAllocatorLargeAlignment(allocator);
@ -766,10 +754,7 @@ test "HeapAllocator" {
}
test "ArenaAllocator" {
var direct_allocator = DirectAllocator.init();
defer direct_allocator.deinit();
var arena_allocator = ArenaAllocator.init(&direct_allocator.allocator);
var arena_allocator = ArenaAllocator.init(direct_allocator);
defer arena_allocator.deinit();
try testAllocator(&arena_allocator.allocator);

View File

@ -164,32 +164,32 @@ pub fn InStream(comptime ReadError: type) type {
/// Reads a native-endian integer
pub fn readIntNative(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
var bytes: [(T.bit_count + 7 )/ 8]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;
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntForeign(T, &bytes);
}
pub fn readIntLittle(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntLittle(T, &bytes);
}
pub fn readIntBig(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntBig(T, &bytes);
}
pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readInt(T, &bytes, endian);
}
@ -249,32 +249,32 @@ pub fn OutStream(comptime WriteError: type) type {
/// Write a native-endian integer.
pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
var bytes: [(T.bit_count + 7 )/ 8]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;
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
mem.writeIntForeign(T, &bytes, value);
return self.writeFn(self, bytes);
}
pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
mem.writeIntLittle(T, &bytes, value);
return self.writeFn(self, bytes);
}
pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
mem.writeIntBig(T, &bytes, value);
return self.writeFn(self, bytes);
}
pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
mem.writeInt(T, &bytes, value, endian);
return self.writeFn(self, bytes);
}

View File

@ -76,7 +76,7 @@ test "BufferOutStream" {
}
test "SliceInStream" {
const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7 };
const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7 };
var ss = io.SliceInStream.init(bytes);
var dest: [4]u8 = undefined;
@ -94,7 +94,7 @@ test "SliceInStream" {
}
test "PeekStream" {
const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
var ss = io.SliceInStream.init(bytes);
var ps = io.PeekStream(2, io.SliceInStream.Error).init(&ss.stream);
@ -147,8 +147,8 @@ test "SliceOutStream" {
}
test "BitInStream" {
const mem_be = []u8{ 0b11001101, 0b00001011 };
const mem_le = []u8{ 0b00011101, 0b10010101 };
const mem_be = [_]u8{ 0b11001101, 0b00001011 };
const mem_le = [_]u8{ 0b00011101, 0b10010101 };
var mem_in_be = io.SliceInStream.init(mem_be[0..]);
const InError = io.SliceInStream.Error;
@ -219,8 +219,8 @@ test "BitInStream" {
}
test "BitOutStream" {
var mem_be = []u8{0} ** 2;
var mem_le = []u8{0} ** 2;
var mem_be = [_]u8{0} ** 2;
var mem_le = [_]u8{0} ** 2;
var mem_out_be = io.SliceOutStream.init(mem_be[0..]);
const OutError = io.SliceOutStream.Error;

View File

@ -5,8 +5,192 @@ const testing = std.testing;
const mem = std.mem;
const Allocator = mem.Allocator;
/// Generic doubly linked list.
pub fn LinkedList(comptime T: type) type {
/// A singly-linked list is headed by a single forward pointer. The elements
/// are singly linked for minimum space and pointer manipulation overhead at
/// the expense of O(n) removal for arbitrary elements. New elements can be
/// added to the list after an existing element or at the head of the list.
/// A singly-linked list may only be traversed in the forward direction.
/// Singly-linked lists are ideal for applications with large datasets and
/// few or no removals or for implementing a LIFO queue.
pub fn SinglyLinkedList(comptime T: type) type {
return struct {
const Self = @This();
/// Node inside the linked list wrapping the actual data.
pub const Node = struct {
next: ?*Node,
data: T,
pub fn init(data: T) Node {
return Node{
.next = null,
.data = data,
};
}
/// Insert a new node after the current one.
///
/// Arguments:
/// new_node: Pointer to the new node to insert.
pub fn insertAfter(node: *Node, new_node: *Node) void {
new_node.next = node.next;
node.next = new_node;
}
/// Remove a node from the list.
///
/// Arguments:
/// node: Pointer to the node to be removed.
/// Returns:
/// node removed
pub fn removeNext(node: *Node) ?*Node {
const next_node = node.next orelse return null;
node.next = next_node.next;
return next_node;
}
};
first: ?*Node,
/// Initialize a linked list.
///
/// Returns:
/// An empty linked list.
pub fn init() Self {
return Self{
.first = null,
};
}
/// Insert a new node after an existing one.
///
/// Arguments:
/// node: Pointer to a node in the list.
/// new_node: Pointer to the new node to insert.
pub fn insertAfter(list: *Self, node: *Node, new_node: *Node) void {
node.insertAfter(new_node);
}
/// Insert a new node at the head.
///
/// Arguments:
/// new_node: Pointer to the new node to insert.
pub fn prepend(list: *Self, new_node: *Node) void {
new_node.next = list.first;
list.first = new_node;
}
/// Remove a node from the list.
///
/// Arguments:
/// node: Pointer to the node to be removed.
pub fn remove(list: *Self, node: *Node) void {
if (list.first == node) {
list.first = node.next;
} else {
var current_elm = list.first.?;
while (current_elm.next != node) {
current_elm = current_elm.next.?;
}
current_elm.next = node.next;
}
}
/// Remove and return the first node in the list.
///
/// Returns:
/// A pointer to the first node in the list.
pub fn popFirst(list: *Self) ?*Node {
const first = list.first orelse return null;
list.first = first.next;
return first;
}
/// Allocate a new node.
///
/// Arguments:
/// allocator: Dynamic memory allocator.
///
/// Returns:
/// A pointer to the new node.
pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node {
return allocator.create(Node);
}
/// Deallocate a node.
///
/// Arguments:
/// node: Pointer to the node to deallocate.
/// allocator: Dynamic memory allocator.
pub fn destroyNode(list: *Self, node: *Node, allocator: *Allocator) void {
allocator.destroy(node);
}
/// Allocate and initialize a node and its data.
///
/// Arguments:
/// data: The data to put inside the node.
/// allocator: Dynamic memory allocator.
///
/// Returns:
/// A pointer to the new node.
pub fn createNode(list: *Self, data: T, allocator: *Allocator) !*Node {
var node = try list.allocateNode(allocator);
node.* = Node.init(data);
return node;
}
};
}
test "basic SinglyLinkedList test" {
const allocator = debug.global_allocator;
var list = SinglyLinkedList(u32).init();
var one = try list.createNode(1, allocator);
var two = try list.createNode(2, allocator);
var three = try list.createNode(3, allocator);
var four = try list.createNode(4, allocator);
var five = try list.createNode(5, allocator);
defer {
list.destroyNode(one, allocator);
list.destroyNode(two, allocator);
list.destroyNode(three, allocator);
list.destroyNode(four, allocator);
list.destroyNode(five, allocator);
}
list.prepend(two); // {2}
list.insertAfter(two, five); // {2, 5}
list.prepend(one); // {1, 2, 5}
list.insertAfter(two, three); // {1, 2, 3, 5}
list.insertAfter(three, four); // {1, 2, 3, 4, 5}
// Traverse forwards.
{
var it = list.first;
var index: u32 = 1;
while (it) |node| : (it = node.next) {
testing.expect(node.data == index);
index += 1;
}
}
_ = list.popFirst(); // {2, 3, 4, 5}
_ = list.remove(five); // {2, 3, 4}
_ = two.removeNext(); // {2, 4}
testing.expect(list.first.?.data == 2);
testing.expect(list.first.?.next.?.data == 4);
testing.expect(list.first.?.next.?.next == null);
}
/// A tail queue is headed by a pair of pointers, one to the head of the
/// list and the other to the tail of the list. The elements are doubly
/// linked so that an arbitrary element can be removed without a need to
/// traverse the list. New elements can be added to the list before or
/// after an existing element, at the head of the list, or at the end of
/// the list. A tail queue may be traversed in either direction.
pub fn TailQueue(comptime T: type) type {
return struct {
const Self = @This();
@ -219,9 +403,9 @@ pub fn LinkedList(comptime T: type) type {
};
}
test "basic linked list test" {
test "basic TailQueue test" {
const allocator = debug.global_allocator;
var list = LinkedList(u32).init();
var list = TailQueue(u32).init();
var one = try list.createNode(1, allocator);
var two = try list.createNode(2, allocator);
@ -271,10 +455,10 @@ test "basic linked list test" {
testing.expect(list.len == 2);
}
test "linked list concatenation" {
test "TailQueue concatenation" {
const allocator = debug.global_allocator;
var list1 = LinkedList(u32).init();
var list2 = LinkedList(u32).init();
var list1 = TailQueue(u32).init();
var list2 = TailQueue(u32).init();
var one = try list1.createNode(1, allocator);
defer list1.destroyNode(one, allocator);

View File

@ -288,10 +288,8 @@ pub fn shl(comptime T: type, a: T, shift_amt: var) T {
const abs_shift_amt = absCast(shift_amt);
const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else @intCast(Log2Int(T), abs_shift_amt);
if (@typeOf(shift_amt).is_signed) {
if (shift_amt >= 0) {
return a << casted_shift_amt;
} else {
if (@typeOf(shift_amt) == comptime_int or @typeOf(shift_amt).is_signed) {
if (shift_amt < 0) {
return a >> casted_shift_amt;
}
}
@ -304,6 +302,10 @@ test "math.shl" {
testing.expect(shl(u8, 0b11111111, usize(8)) == 0);
testing.expect(shl(u8, 0b11111111, usize(9)) == 0);
testing.expect(shl(u8, 0b11111111, isize(-2)) == 0b00111111);
testing.expect(shl(u8, 0b11111111, 3) == 0b11111000);
testing.expect(shl(u8, 0b11111111, 8) == 0);
testing.expect(shl(u8, 0b11111111, 9) == 0);
testing.expect(shl(u8, 0b11111111, -2) == 0b00111111);
}
/// Shifts right. Overflowed bits are truncated.
@ -312,7 +314,7 @@ pub fn shr(comptime T: type, a: T, shift_amt: var) T {
const abs_shift_amt = absCast(shift_amt);
const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else @intCast(Log2Int(T), abs_shift_amt);
if (@typeOf(shift_amt).is_signed) {
if (@typeOf(shift_amt) == comptime_int or @typeOf(shift_amt).is_signed) {
if (shift_amt >= 0) {
return a >> casted_shift_amt;
} else {
@ -328,6 +330,10 @@ test "math.shr" {
testing.expect(shr(u8, 0b11111111, usize(8)) == 0);
testing.expect(shr(u8, 0b11111111, usize(9)) == 0);
testing.expect(shr(u8, 0b11111111, isize(-2)) == 0b11111100);
testing.expect(shr(u8, 0b11111111, 3) == 0b00011111);
testing.expect(shr(u8, 0b11111111, 8) == 0);
testing.expect(shr(u8, 0b11111111, 9) == 0);
testing.expect(shr(u8, 0b11111111, -2) == 0b11111100);
}
/// Rotates right. Only unsigned values can be rotated.
@ -476,7 +482,16 @@ fn testAbsInt() void {
testing.expect((absInt(i32(10)) catch unreachable) == 10);
}
pub const absFloat = @import("fabs.zig").fabs;
pub const absFloat = fabs;
test "math.absFloat" {
testAbsFloat();
comptime testAbsFloat();
}
fn testAbsFloat() void {
testing.expect(absFloat(f32(-10.05)) == 10.05);
testing.expect(absFloat(f32(10.05)) == 10.05);
}
pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
@setRuntimeSafety(false);
@ -680,6 +695,11 @@ pub fn alignCast(comptime alignment: u29, ptr: var) AlignCastError!@typeOf(@alig
return @alignCast(alignment, ptr);
}
pub fn isPowerOfTwo(v: var) bool {
assert(v != 0);
return (v & (v - 1)) == 0;
}
pub fn floorPowerOfTwo(comptime T: type, value: T) T {
var x = value;

View File

@ -23,21 +23,21 @@ pub fn atan(x: var) @typeOf(x) {
}
fn atan32(x_: f32) f32 {
const atanhi = []const f32{
const atanhi = [_]f32{
4.6364760399e-01, // atan(0.5)hi
7.8539812565e-01, // atan(1.0)hi
9.8279368877e-01, // atan(1.5)hi
1.5707962513e+00, // atan(inf)hi
};
const atanlo = []const f32{
const atanlo = [_]f32{
5.0121582440e-09, // atan(0.5)lo
3.7748947079e-08, // atan(1.0)lo
3.4473217170e-08, // atan(1.5)lo
7.5497894159e-08, // atan(inf)lo
};
const aT = []const f32{
const aT = [_]f32{
3.3333328366e-01,
-1.9999158382e-01,
1.4253635705e-01,
@ -114,21 +114,21 @@ fn atan32(x_: f32) f32 {
}
fn atan64(x_: f64) f64 {
const atanhi = []const f64{
const atanhi = [_]f64{
4.63647609000806093515e-01, // atan(0.5)hi
7.85398163397448278999e-01, // atan(1.0)hi
9.82793723247329054082e-01, // atan(1.5)hi
1.57079632679489655800e+00, // atan(inf)hi
};
const atanlo = []const f64{
const atanlo = [_]f64{
2.26987774529616870924e-17, // atan(0.5)lo
3.06161699786838301793e-17, // atan(1.0)lo
1.39033110312309984516e-17, // atan(1.5)lo
6.12323399573676603587e-17, // atan(inf)lo
};
const aT = []const f64{
const aT = [_]f64{
3.33333333333329318027e-01,
-1.99999999998764832476e-01,
1.42857142725034663711e-01,

View File

@ -415,13 +415,13 @@ pub const Int = struct {
i += 1;
}
const ap_base = Int.initFixed(([]Limb{base})[0..]);
const ap_base = Int.initFixed(([_]Limb{base})[0..]);
try self.set(0);
for (value[i..]) |ch| {
const d = try charToDigit(ch, base);
const ap_d = Int.initFixed(([]Limb{d})[0..]);
const ap_d = Int.initFixed(([_]Limb{d})[0..]);
try self.mul(self.*, ap_base);
try self.add(self.*, ap_d);
@ -447,7 +447,7 @@ pub const Int = struct {
}
// Power of two: can do a single pass and use masks to extract digits.
if (base & (base - 1) == 0) {
if (math.isPowerOfTwo(base)) {
const base_shift = math.log2_int(Limb, base);
for (self.limbs[0..self.len()]) |limb| {
@ -828,7 +828,7 @@ pub const Int = struct {
// Trunc -> Floor.
if (!q.isPositive()) {
const one = Int.initFixed(([]Limb{1})[0..]);
const one = Int.initFixed(([_]Limb{1})[0..]);
try q.sub(q.*, one);
try r.add(q.*, one);
}

View File

@ -102,7 +102,7 @@ pub const Rational = struct {
if (point) |i| {
try self.p.setString(10, str[0..i]);
const base = Int.initFixed(([]Limb{10})[0..]);
const base = Int.initFixed(([_]Limb{10})[0..]);
var j: usize = start;
while (j < str.len - i - 1) : (j += 1) {
@ -452,7 +452,7 @@ pub const Rational = struct {
try gcd(&a, r.p, r.q);
r.p.setSign(sign);
const one = Int.initFixed(([]Limb{1})[0..]);
const one = Int.initFixed(([_]Limb{1})[0..]);
if (a.cmp(one) != 0) {
var unused = try Int.init(r.p.allocator.?);
defer unused.deinit();

View File

@ -24,7 +24,7 @@ pub fn exp(x: var) @typeOf(x) {
}
fn exp32(x_: f32) f32 {
const half = []f32{ 0.5, -0.5 };
const half = [_]f32{ 0.5, -0.5 };
const ln2hi = 6.9314575195e-1;
const ln2lo = 1.4286067653e-6;
const invln2 = 1.4426950216e+0;
@ -99,7 +99,7 @@ fn exp32(x_: f32) f32 {
}
fn exp64(x_: f64) f64 {
const half = []const f64{ 0.5, -0.5 };
const half = [_]f64{ 0.5, -0.5 };
const ln2hi: f64 = 6.93147180369123816490e-01;
const ln2lo: f64 = 1.90821492927058770002e-10;
const invln2: f64 = 1.44269504088896338700e+00;

View File

@ -22,7 +22,7 @@ pub fn exp2(x: var) @typeOf(x) {
};
}
const exp2ft = []const f64{
const exp2ft = [_]f64{
0x1.6a09e667f3bcdp-1,
0x1.7a11473eb0187p-1,
0x1.8ace5422aa0dbp-1,
@ -96,7 +96,7 @@ fn exp2_32(x: f32) f32 {
return @floatCast(f32, r * uk);
}
const exp2dt = []f64{
const exp2dt = [_]f64{
// exp2(z + eps) eps
0x1.6a09e667f3d5dp-1, 0x1.9880p-44,
0x1.6b052fa751744p-1, 0x1.8000p-50,

View File

@ -262,8 +262,8 @@ pub fn secureZero(comptime T: type, s: []T) void {
}
test "mem.secureZero" {
var a = []u8{0xfe} ** 8;
var b = []u8{0xfe} ** 8;
var a = [_]u8{0xfe} ** 8;
var b = [_]u8{0xfe} ** 8;
set(u8, a[0..], 0);
secureZero(u8, b[0..]);
@ -598,23 +598,23 @@ test "comptime read/write int" {
}
test "readIntBig and readIntLittle" {
testing.expect(readIntSliceBig(u0, []u8{}) == 0x0);
testing.expect(readIntSliceLittle(u0, []u8{}) == 0x0);
testing.expect(readIntSliceBig(u0, [_]u8{}) == 0x0);
testing.expect(readIntSliceLittle(u0, [_]u8{}) == 0x0);
testing.expect(readIntSliceBig(u8, []u8{0x32}) == 0x32);
testing.expect(readIntSliceLittle(u8, []u8{0x12}) == 0x12);
testing.expect(readIntSliceBig(u8, [_]u8{0x32}) == 0x32);
testing.expect(readIntSliceLittle(u8, [_]u8{0x12}) == 0x12);
testing.expect(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234);
testing.expect(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412);
testing.expect(readIntSliceBig(u16, [_]u8{ 0x12, 0x34 }) == 0x1234);
testing.expect(readIntSliceLittle(u16, [_]u8{ 0x12, 0x34 }) == 0x3412);
testing.expect(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
testing.expect(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
testing.expect(readIntSliceBig(u72, [_]u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
testing.expect(readIntSliceLittle(u72, [_]u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
testing.expect(readIntSliceBig(i8, []u8{0xff}) == -1);
testing.expect(readIntSliceLittle(i8, []u8{0xfe}) == -2);
testing.expect(readIntSliceBig(i8, [_]u8{0xff}) == -1);
testing.expect(readIntSliceLittle(i8, [_]u8{0xfe}) == -2);
testing.expect(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3);
testing.expect(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4);
testing.expect(readIntSliceBig(i16, [_]u8{ 0xff, 0xfd }) == -3);
testing.expect(readIntSliceLittle(i16, [_]u8{ 0xfc, 0xff }) == -4);
}
/// Writes an integer to memory, storing it in twos-complement.
@ -723,34 +723,34 @@ test "writeIntBig and writeIntLittle" {
var buf9: [9]u8 = undefined;
writeIntBig(u0, &buf0, 0x0);
testing.expect(eql_slice_u8(buf0[0..], []u8{}));
testing.expect(eql_slice_u8(buf0[0..], [_]u8{}));
writeIntLittle(u0, &buf0, 0x0);
testing.expect(eql_slice_u8(buf0[0..], []u8{}));
testing.expect(eql_slice_u8(buf0[0..], [_]u8{}));
writeIntBig(u8, &buf1, 0x12);
testing.expect(eql_slice_u8(buf1[0..], []u8{0x12}));
testing.expect(eql_slice_u8(buf1[0..], [_]u8{0x12}));
writeIntLittle(u8, &buf1, 0x34);
testing.expect(eql_slice_u8(buf1[0..], []u8{0x34}));
testing.expect(eql_slice_u8(buf1[0..], [_]u8{0x34}));
writeIntBig(u16, &buf2, 0x1234);
testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0x12, 0x34 }));
writeIntLittle(u16, &buf2, 0x5678);
testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0x78, 0x56 }));
writeIntBig(u72, &buf9, 0x123456789abcdef024);
testing.expect(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
testing.expect(eql_slice_u8(buf9[0..], [_]u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);
testing.expect(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
testing.expect(eql_slice_u8(buf9[0..], [_]u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
writeIntBig(i8, &buf1, -1);
testing.expect(eql_slice_u8(buf1[0..], []u8{0xff}));
testing.expect(eql_slice_u8(buf1[0..], [_]u8{0xff}));
writeIntLittle(i8, &buf1, -2);
testing.expect(eql_slice_u8(buf1[0..], []u8{0xfe}));
testing.expect(eql_slice_u8(buf1[0..], [_]u8{0xfe}));
writeIntBig(i16, &buf2, -3);
testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0xff, 0xfd }));
writeIntLittle(i16, &buf2, -4);
testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0xfc, 0xff }));
}
pub fn hash_slice_u8(k: []const u8) u32 {
@ -991,9 +991,46 @@ pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []cons
test "mem.join" {
var buf: [1024]u8 = undefined;
const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
testing.expect(eql(u8, try join(a, ",", [][]const u8{ "a", "b", "c" }), "a,b,c"));
testing.expect(eql(u8, try join(a, ",", [][]const u8{"a"}), "a"));
testing.expect(eql(u8, try join(a, ",", [][]const u8{ "a", "", "b", "", "c" }), "a,,b,,c"));
testing.expect(eql(u8, try join(a, ",", [_][]const u8{ "a", "b", "c" }), "a,b,c"));
testing.expect(eql(u8, try join(a, ",", [_][]const u8{"a"}), "a"));
testing.expect(eql(u8, try join(a, ",", [_][]const u8{ "a", "", "b", "", "c" }), "a,,b,,c"));
}
/// Copies each T from slices into a new slice that exactly holds all the elements.
pub fn concat(allocator: *Allocator, comptime T: type, slices: []const []const T) ![]T {
if (slices.len == 0) return (([*]T)(undefined))[0..0];
const total_len = blk: {
var sum: usize = 0;
for (slices) |slice| {
sum += slice.len;
}
break :blk sum;
};
const buf = try allocator.alloc(T, total_len);
errdefer allocator.free(buf);
var buf_index: usize = 0;
for (slices) |slice| {
copy(T, buf[buf_index..], slice);
buf_index += slice.len;
}
// No need for shrink since buf is exactly the correct size.
return buf;
}
test "concat" {
var buf: [1024]u8 = undefined;
const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
testing.expect(eql(u8, try concat(a, u8, [_][]const u8{ "abc", "def", "ghi" }), "abcdefghi"));
testing.expect(eql(u32, try concat(a, u32, [_][]const u32{
[_]u32{ 0, 1 },
[_]u32{ 2, 3, 4 },
[_]u32{},
[_]u32{5},
}), [_]u32{ 0, 1, 2, 3, 4, 5 }));
}
test "testStringEquality" {
@ -1008,7 +1045,7 @@ test "testReadInt" {
}
fn testReadIntImpl() void {
{
const bytes = []u8{
const bytes = [_]u8{
0x12,
0x34,
0x56,
@ -1022,7 +1059,7 @@ fn testReadIntImpl() void {
testing.expect(readIntLittle(i32, &bytes) == 0x78563412);
}
{
const buf = []u8{
const buf = [_]u8{
0x00,
0x00,
0x12,
@ -1032,7 +1069,7 @@ fn testReadIntImpl() void {
testing.expect(answer == 0x00001234);
}
{
const buf = []u8{
const buf = [_]u8{
0x12,
0x34,
0x00,
@ -1042,7 +1079,7 @@ fn testReadIntImpl() void {
testing.expect(answer == 0x00003412);
}
{
const bytes = []u8{
const bytes = [_]u8{
0xff,
0xfe,
};
@ -1061,19 +1098,19 @@ fn testWriteIntImpl() void {
var bytes: [8]u8 = undefined;
writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big);
testing.expect(eql(u8, bytes, []u8{
testing.expect(eql(u8, bytes, [_]u8{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}));
writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little);
testing.expect(eql(u8, bytes, []u8{
testing.expect(eql(u8, bytes, [_]u8{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}));
writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big);
testing.expect(eql(u8, bytes, []u8{
testing.expect(eql(u8, bytes, [_]u8{
0x12,
0x34,
0x56,
@ -1085,7 +1122,7 @@ fn testWriteIntImpl() void {
}));
writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little);
testing.expect(eql(u8, bytes, []u8{
testing.expect(eql(u8, bytes, [_]u8{
0x12,
0x34,
0x56,
@ -1097,7 +1134,7 @@ fn testWriteIntImpl() void {
}));
writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big);
testing.expect(eql(u8, bytes, []u8{
testing.expect(eql(u8, bytes, [_]u8{
0x00,
0x00,
0x00,
@ -1109,7 +1146,7 @@ fn testWriteIntImpl() void {
}));
writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little);
testing.expect(eql(u8, bytes, []u8{
testing.expect(eql(u8, bytes, [_]u8{
0x12,
0x34,
0x56,
@ -1121,7 +1158,7 @@ fn testWriteIntImpl() void {
}));
writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big);
testing.expect(eql(u8, bytes, []u8{
testing.expect(eql(u8, bytes, [_]u8{
0x00,
0x00,
0x00,
@ -1133,7 +1170,7 @@ fn testWriteIntImpl() void {
}));
writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little);
testing.expect(eql(u8, bytes, []u8{
testing.expect(eql(u8, bytes, [_]u8{
0x34,
0x12,
0x00,
@ -1185,7 +1222,7 @@ pub fn reverse(comptime T: type, items: []T) void {
}
test "reverse" {
var arr = []i32{
var arr = [_]i32{
5,
3,
1,
@ -1194,7 +1231,7 @@ test "reverse" {
};
reverse(i32, arr[0..]);
testing.expect(eql(i32, arr, []i32{
testing.expect(eql(i32, arr, [_]i32{
4,
2,
1,
@ -1212,7 +1249,7 @@ pub fn rotate(comptime T: type, items: []T, amount: usize) void {
}
test "rotate" {
var arr = []i32{
var arr = [_]i32{
5,
3,
1,
@ -1221,7 +1258,7 @@ test "rotate" {
};
rotate(i32, arr[0..], 2);
testing.expect(eql(i32, arr, []i32{
testing.expect(eql(i32, arr, [_]i32{
1,
2,
4,

View File

@ -184,7 +184,7 @@ test "std.meta.declarations" {
fn a() void {}
};
const decls = comptime [][]TypeInfo.Declaration{
const decls = comptime [_][]TypeInfo.Declaration{
declarations(E1),
declarations(S1),
declarations(U1),
@ -220,7 +220,7 @@ test "std.meta.declarationInfo" {
fn a() void {}
};
const infos = comptime []TypeInfo.Declaration{
const infos = comptime [_]TypeInfo.Declaration{
declarationInfo(E1, "a"),
declarationInfo(S1, "a"),
declarationInfo(U1, "a"),

View File

@ -46,7 +46,7 @@ test "std.meta.trait.multiTrait" {
}
};
const isVector = multiTrait(TraitList{
const isVector = multiTrait([_]TraitFn{
hasFn("add"),
hasField("x"),
hasField("y"),
@ -235,7 +235,7 @@ pub fn isSingleItemPtr(comptime T: type) bool {
}
test "std.meta.trait.isSingleItemPtr" {
const array = []u8{0} ** 10;
const array = [_]u8{0} ** 10;
testing.expect(isSingleItemPtr(@typeOf(&array[0])));
testing.expect(!isSingleItemPtr(@typeOf(array)));
testing.expect(!isSingleItemPtr(@typeOf(array[0..1])));
@ -251,7 +251,7 @@ pub fn isManyItemPtr(comptime T: type) bool {
}
test "std.meta.trait.isManyItemPtr" {
const array = []u8{0} ** 10;
const array = [_]u8{0} ** 10;
const mip = @ptrCast([*]const u8, &array[0]);
testing.expect(isManyItemPtr(@typeOf(mip)));
testing.expect(!isManyItemPtr(@typeOf(array)));
@ -268,7 +268,7 @@ pub fn isSlice(comptime T: type) bool {
}
test "std.meta.trait.isSlice" {
const array = []u8{0} ** 10;
const array = [_]u8{0} ** 10;
testing.expect(isSlice(@typeOf(array[0..])));
testing.expect(!isSlice(@typeOf(array)));
testing.expect(!isSlice(@typeOf(&array[0])));
@ -288,7 +288,7 @@ pub fn isIndexable(comptime T: type) bool {
}
test "std.meta.trait.isIndexable" {
const array = []u8{0} ** 10;
const array = [_]u8{0} ** 10;
const slice = array[0..];
testing.expect(isIndexable(@typeOf(array)));

View File

@ -130,11 +130,8 @@ const TestContext = struct {
};
test "std.Mutex" {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var plenty_of_memory = try direct_allocator.allocator.alloc(u8, 300 * 1024);
defer direct_allocator.allocator.free(plenty_of_memory);
var plenty_of_memory = try std.heap.direct_allocator.alloc(u8, 300 * 1024);
defer std.heap.direct_allocator.free(plenty_of_memory);
var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory);
var a = &fixed_buffer_allocator.allocator;

View File

@ -25,7 +25,7 @@ pub const Address = struct {
.family = os.AF_INET,
.port = mem.nativeToBig(u16, _port),
.addr = ip4,
.zero = []u8{0} ** 8,
.zero = [_]u8{0} ** 8,
},
},
};

View File

@ -1223,7 +1223,7 @@ pub fn isCygwinPty(handle: fd_t) bool {
if (!windows.is_the_target) return false;
const size = @sizeOf(windows.FILE_NAME_INFO);
var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = []u8{0} ** (size + windows.MAX_PATH);
var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (size + windows.MAX_PATH);
if (windows.kernel32.GetFileInformationByHandleEx(
handle,
@ -1237,8 +1237,8 @@ pub fn isCygwinPty(handle: fd_t) bool {
const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]);
const name_bytes = name_info_bytes[size .. size + usize(name_info.FileNameLength)];
const name_wide = @bytesToSlice(u16, name_bytes);
return mem.indexOf(u16, name_wide, []u16{ 'm', 's', 'y', 's', '-' }) != null or
mem.indexOf(u16, name_wide, []u16{ '-', 'p', 't', 'y' }) != null;
return mem.indexOf(u16, name_wide, [_]u16{ 'm', 's', 'y', 's', '-' }) != null or
mem.indexOf(u16, name_wide, [_]u16{ '-', 'p', 't', 'y' }) != null;
}
pub const SocketError = error{
@ -2335,7 +2335,7 @@ pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPa
// Windows returns \\?\ prepended to the path.
// We strip it to make this function consistent across platforms.
const prefix = []u16{ '\\', '\\', '?', '\\' };
const prefix = [_]u16{ '\\', '\\', '?', '\\' };
const start_index = if (mem.startsWith(u16, wide_slice, prefix)) prefix.len else 0;
// Trust that Windows gives us valid UTF-16LE.

View File

@ -119,6 +119,23 @@ pub const O_RDONLY = 0o0;
pub const O_WRONLY = 0o1;
pub const O_RDWR = 0o2;
pub const kernel_rwf = u32;
/// high priority request, poll if possible
pub const RWF_HIPRI = kernel_rwf(0x00000001);
/// per-IO O_DSYNC
pub const RWF_DSYNC = kernel_rwf(0x00000002);
/// per-IO O_SYNC
pub const RWF_SYNC = kernel_rwf(0x00000004);
/// per-IO, return -EAGAIN if operation would block
pub const RWF_NOWAIT = kernel_rwf(0x00000008);
/// per-IO O_APPEND
pub const RWF_APPEND = kernel_rwf(0x00000010);
pub const SEEK_SET = 0;
pub const SEEK_CUR = 1;
pub const SEEK_END = 2;
@ -691,8 +708,8 @@ pub const winsize = extern struct {
pub const NSIG = 65;
pub const sigset_t = [128 / @sizeOf(usize)]usize;
pub const all_mask = []u32{ 0xffffffff, 0xffffffff };
pub const app_mask = []u32{ 0xfffffffc, 0x7fffffff };
pub const all_mask = [_]u32{ 0xffffffff, 0xffffffff };
pub const app_mask = [_]u32{ 0xfffffffc, 0x7fffffff };
pub const k_sigaction = extern struct {
handler: extern fn (i32) void,
@ -711,7 +728,7 @@ pub const Sigaction = struct {
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);
pub const empty_sigset = []usize{0} ** sigset_t.len;
pub const empty_sigset = [_]usize{0} ** sigset_t.len;
pub const in_port_t = u16;
pub const sa_family_t = u16;
@ -950,3 +967,129 @@ pub const stack_t = extern struct {
ss_flags: i32,
ss_size: isize,
};
pub const io_uring_params = extern struct {
sq_entries: u32,
cq_entries: u32,
flags: u32,
sq_thread_cpu: u32,
sq_thread_idle: u32,
resv: [5]u32,
sq_off: io_sqring_offsets,
cq_off: io_cqring_offsets,
};
// io_uring_params.flags
/// io_context is polled
pub const IORING_SETUP_IOPOLL = (1 << 0);
/// SQ poll thread
pub const IORING_SETUP_SQPOLL = (1 << 1);
/// sq_thread_cpu is valid
pub const IORING_SETUP_SQ_AFF = (1 << 2);
pub const io_sqring_offsets = extern struct {
/// offset of ring head
head: u32,
/// offset of ring tail
tail: u32,
/// ring mask value
ring_mask: u32,
/// entries in ring
ring_entries: u32,
/// ring flags
flags: u32,
/// number of sqes not submitted
dropped: u32,
/// sqe index array
array: u32,
resv1: u32,
resv2: u64,
};
// io_sqring_offsets.flags
/// needs io_uring_enter wakeup
pub const IORING_SQ_NEED_WAKEUP = 1 << 0;
pub const io_cqring_offsets = extern struct {
head: u32,
tail: u32,
ring_mask: u32,
ring_entries: u32,
overflow: u32,
cqes: u32,
resv: [2]u64,
};
pub const io_uring_sqe = extern struct {
opcode: u8,
flags: u8,
ioprio: u16,
fd: i32,
off: u64,
addr: u64,
len: u32,
pub const union1 = extern union {
rw_flags: kernel_rwf,
fsync_flags: u32,
poll_event: u16,
};
union1: union1,
user_data: u64,
pub const union2 = extern union {
buf_index: u16,
__pad2: [3]u64,
};
union2: union2,
};
// io_uring_sqe.flags
/// use fixed fileset
pub const IOSQE_FIXED_FILE = (1 << 0);
pub const IORING_OP_NOP = 0;
pub const IORING_OP_READV = 1;
pub const IORING_OP_WRITEV = 2;
pub const IORING_OP_FSYNC = 3;
pub const IORING_OP_READ_FIXED = 4;
pub const IORING_OP_WRITE_FIXED = 5;
pub const IORING_OP_POLL_ADD = 6;
pub const IORING_OP_POLL_REMOVE = 7;
// io_uring_sqe.fsync_flags
pub const IORING_FSYNC_DATASYNC = (1 << 0);
// IO completion data structure (Completion Queue Entry)
pub const io_uring_cqe = extern struct {
/// io_uring_sqe.data submission passed back
user_data: u64,
/// result code for this event
res: i32,
flags: u32,
};
pub const IORING_OFF_SQ_RING = 0;
pub const IORING_OFF_CQ_RING = 0x8000000;
pub const IORING_OFF_SQES = 0x10000000;
// io_uring_enter flags
pub const IORING_ENTER_GETEVENTS = (1 << 0);
pub const IORING_ENTER_SQ_WAKEUP = (1 << 1);
// io_uring_register opcodes and arguments
pub const IORING_REGISTER_BUFFERS = 0;
pub const IORING_UNREGISTER_BUFFERS = 1;
pub const IORING_REGISTER_FILES = 2;
pub const IORING_UNREGISTER_FILES = 3;

View File

@ -189,6 +189,10 @@ pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
}
pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: u64, flags: kernel_rwf) usize {
return syscall5(SYS_preadv2, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset, flags);
}
pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
}
@ -201,6 +205,10 @@ pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) us
return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
}
pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64, flags: kernel_rwf) usize {
return syscall5(SYS_pwritev2, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset, flags);
}
// TODO https://github.com/ziglang/zig/issues/265
pub fn rmdir(path: [*]const u8) usize {
if (@hasDecl(@This(), "SYS_rmdir")) {
@ -887,6 +895,18 @@ pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_inf
return last_r;
}
pub fn io_uring_setup(entries: u32, p: *io_uring_params) usize {
return syscall2(SYS_io_uring_setup, entries, @ptrToInt(p));
}
pub fn io_uring_enter(fd: i32, to_submit: u32, min_complete: u32, flags: u32, sig: ?*sigset_t) usize {
return syscall6(SYS_io_uring_enter, @bitCast(usize, isize(fd)), to_submit, min_complete, flags, @ptrToInt(sig), NSIG / 8);
}
pub fn io_uring_register(fd: i32, opcode: u32, arg: ?*const c_void, nr_args: u32) usize {
return syscall4(SYS_io_uring_register, @bitCast(usize, isize(fd)), opcode, @ptrToInt(arg), nr_args);
}
test "" {
if (is_the_target) {
_ = @import("linux/test.zig");

View File

@ -39,7 +39,7 @@ test "timer" {
expect(err == 0);
const events_one: linux.epoll_event = undefined;
var events = []linux.epoll_event{events_one} ** 8;
var events = [_]linux.epoll_event{events_one} ** 8;
// TODO implicit cast from *[N]T to [*]T
err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);

View File

@ -145,7 +145,7 @@ pub const FindFirstFileError = error{
};
pub fn FindFirstFile(dir_path: []const u8, find_file_data: *WIN32_FIND_DATAW) FindFirstFileError!HANDLE {
const dir_path_w = try sliceToPrefixedSuffixedFileW(dir_path, []u16{ '\\', '*', 0 });
const dir_path_w = try sliceToPrefixedSuffixedFileW(dir_path, [_]u16{ '\\', '*', 0 });
const handle = kernel32.FindFirstFileW(&dir_path_w, find_file_data);
if (handle == INVALID_HANDLE_VALUE) {
@ -632,6 +632,7 @@ pub fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) G
pub const CreateProcessError = error{
FileNotFound,
AccessDenied,
InvalidName,
Unexpected,
};
@ -663,6 +664,7 @@ pub fn CreateProcessW(
switch (kernel32.GetLastError()) {
ERROR.FILE_NOT_FOUND => return error.FileNotFound,
ERROR.PATH_NOT_FOUND => return error.FileNotFound,
ERROR.ACCESS_DENIED => return error.AccessDenied,
ERROR.INVALID_PARAMETER => unreachable,
ERROR.INVALID_NAME => return error.InvalidName,
else => |err| return unexpectedError(err),
@ -725,7 +727,7 @@ pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {
}
pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 {
return sliceToPrefixedSuffixedFileW(s, []u16{0});
return sliceToPrefixedSuffixedFileW(s, [_]u16{0});
}
pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len]u16 {
@ -745,7 +747,7 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
}
}
const start_index = if (mem.startsWith(u8, s, "\\\\") or !std.fs.path.isAbsolute(s)) 0 else blk: {
const prefix = []u16{ '\\', '\\', '?', '\\' };
const prefix = [_]u16{ '\\', '\\', '?', '\\' };
mem.copy(u16, result[0..], prefix);
break :blk prefix.len;
};
@ -767,10 +769,7 @@ pub fn unexpectedError(err: DWORD) std.os.UnexpectedError {
// 614 is the length of the longest windows error desciption
var buf_u16: [614]u16 = undefined;
var buf_u8: [614]u8 = undefined;
var len = kernel32.FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
null, err, MAKELANGID(LANG.NEUTRAL, SUBLANG.DEFAULT),
buf_u16[0..].ptr, buf_u16.len / @sizeOf(TCHAR), null);
var len = kernel32.FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, null, err, MAKELANGID(LANG.NEUTRAL, SUBLANG.DEFAULT), buf_u16[0..].ptr, buf_u16.len / @sizeOf(TCHAR), null);
_ = std.unicode.utf16leToUtf8(&buf_u8, buf_u16[0..len]) catch unreachable;
std.debug.warn("error.Unexpected: GetLastError({}): {}\n", err, buf_u8[0..len]);
std.debug.dumpCurrentStackTrace(null);

View File

@ -351,7 +351,7 @@ test "PackedIntArray" {
test "PackedIntArray init" {
const PackedArray = PackedIntArray(u3, 8);
var packed_array = PackedArray.init([]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
var i = usize(0);
while (i < packed_array.len()) : (i += 1) testing.expect(packed_array.get(i) == i);
}
@ -487,7 +487,7 @@ test "PackedIntSlice accumulating bit offsets" {
// big endian values were not tested
test "PackedInt(Array/Slice) sliceCast" {
const PackedArray = PackedIntArray(u1, 16);
var packed_array = PackedArray.init([]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
var packed_array = PackedArray.init([_]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
const packed_slice_cast_2 = packed_array.sliceCast(u2);
const packed_slice_cast_4 = packed_slice_cast_2.sliceCast(u4);
var packed_slice_cast_9 = packed_array.slice(0, (packed_array.len() / 9) * 9).sliceCast(u9);
@ -528,7 +528,7 @@ test "PackedInt(Array/Slice) sliceCast" {
test "PackedInt(Array/Slice)Endian" {
{
const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8);
var packed_array_be = PackedArrayBe.init([]u4{
var packed_array_be = PackedArrayBe.init([_]u4{
0,
1,
2,
@ -563,7 +563,7 @@ test "PackedInt(Array/Slice)Endian" {
{
const PackedArrayBe = PackedIntArrayEndian(u11, .Big, 8);
var packed_array_be = PackedArrayBe.init([]u11{
var packed_array_be = PackedArrayBe.init([_]u11{
0,
1,
2,
@ -603,8 +603,7 @@ test "PackedInt(Array/Slice)Endian" {
}
//@NOTE: Need to manually update this list as more posix os's get
// added to DirectAllocator. Windows can be added too when DirectAllocator
// switches to VirtualAlloc.
// added to DirectAllocator.
//These tests prove we aren't accidentally accessing memory past
// the end of the array/slice by placing it at the end of a page
@ -613,7 +612,7 @@ test "PackedInt(Array/Slice)Endian" {
// don't account for the bounds.
test "PackedIntArray at end of available memory" {
switch (builtin.os) {
.linux, .macosx, .ios, .freebsd, .netbsd => {},
.linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
else => return,
}
const PackedArray = PackedIntArray(u3, 8);
@ -623,8 +622,7 @@ test "PackedIntArray at end of available memory" {
p: PackedArray,
};
var da = std.heap.DirectAllocator.init();
const allocator = &da.allocator;
const allocator = std.heap.direct_allocator;
var pad = try allocator.create(Padded);
defer allocator.destroy(pad);
@ -633,13 +631,12 @@ test "PackedIntArray at end of available memory" {
test "PackedIntSlice at end of available memory" {
switch (builtin.os) {
.linux, .macosx, .ios, .freebsd, .netbsd => {},
.linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
else => return,
}
const PackedSlice = PackedIntSlice(u11);
var da = std.heap.DirectAllocator.init();
const allocator = &da.allocator;
const allocator = std.heap.direct_allocator;
var page = try allocator.alloc(u8, std.mem.page_size);
defer allocator.free(page);

View File

@ -15,7 +15,7 @@ pub fn PriorityQueue(comptime T: type) type {
pub fn init(allocator: *Allocator, compareFn: fn (a: T, b: T) bool) Self {
return Self{
.items = []T{},
.items = [_]T{},
.len = 0,
.allocator = allocator,
.compareFn = compareFn,
@ -276,12 +276,12 @@ test "std.PriorityQueue: peek" {
test "std.PriorityQueue: sift up with odd indices" {
var queue = PQ.init(debug.global_allocator, lessThan);
defer queue.deinit();
const items = []u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
for (items) |e| {
try queue.add(e);
}
const sorted_items = []u32{ 1, 2, 5, 6, 7, 7, 11, 12, 13, 14, 15, 15, 16, 21, 22, 24, 24, 25 };
const sorted_items = [_]u32{ 1, 2, 5, 6, 7, 7, 11, 12, 13, 14, 15, 15, 16, 21, 22, 24, 24, 25 };
for (sorted_items) |e| {
expectEqual(e, queue.remove());
}
@ -290,22 +290,22 @@ test "std.PriorityQueue: sift up with odd indices" {
test "std.PriorityQueue: addSlice" {
var queue = PQ.init(debug.global_allocator, lessThan);
defer queue.deinit();
const items = []u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
try queue.addSlice(items[0..]);
const sorted_items = []u32{ 1, 2, 5, 6, 7, 7, 11, 12, 13, 14, 15, 15, 16, 21, 22, 24, 24, 25 };
const sorted_items = [_]u32{ 1, 2, 5, 6, 7, 7, 11, 12, 13, 14, 15, 15, 16, 21, 22, 24, 24, 25 };
for (sorted_items) |e| {
expectEqual(e, queue.remove());
}
}
test "std.PriorityQueue: fromOwnedSlice" {
const items = []u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
const heap_items = try std.mem.dupe(debug.global_allocator, u32, items[0..]);
var queue = PQ.fromOwnedSlice(debug.global_allocator, lessThan, heap_items[0..]);
defer queue.deinit();
const sorted_items = []u32{ 1, 2, 5, 6, 7, 7, 11, 12, 13, 14, 15, 15, 16, 21, 22, 24, 24, 25 };
const sorted_items = [_]u32{ 1, 2, 5, 6, 7, 7, 11, 12, 13, 14, 15, 15, 16, 21, 22, 24, 24, 25 };
for (sorted_items) |e| {
expectEqual(e, queue.remove());
}
@ -355,7 +355,7 @@ test "std.PriorityQueue: iterator" {
map.deinit();
}
const items = []u32{ 54, 12, 7, 23, 25, 13 };
const items = [_]u32{ 54, 12, 7, 23, 25, 13 };
for (items) |e| {
_ = try queue.add(e);
_ = try map.put(e, {});

View File

@ -388,7 +388,7 @@ pub fn args() ArgIterator {
}
/// Caller must call argsFree on result.
pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {
if (builtin.os == .wasi) {
var count: usize = undefined;
var buf_size: usize = undefined;
@ -474,14 +474,14 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
}
test "windows arg parsing" {
testWindowsCmdLine(c"a b\tc d", [][]const u8{ "a", "b", "c", "d" });
testWindowsCmdLine(c"\"abc\" d e", [][]const u8{ "abc", "d", "e" });
testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8{ "a\\\\\\b", "de fg", "h" });
testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8{ "a\\\"b", "c", "d" });
testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8{ "a\\\\b c", "d", "e" });
testWindowsCmdLine(c"a b\tc \"d f", [][]const u8{ "a", "b", "c", "\"d", "f" });
testWindowsCmdLine(c"a b\tc d", [_][]const u8{ "a", "b", "c", "d" });
testWindowsCmdLine(c"\"abc\" d e", [_][]const u8{ "abc", "d", "e" });
testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [_][]const u8{ "a\\\\\\b", "de fg", "h" });
testWindowsCmdLine(c"a\\\\\\\"b c d", [_][]const u8{ "a\\\"b", "c", "d" });
testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [_][]const u8{ "a\\\\b c", "d", "e" });
testWindowsCmdLine(c"a b\tc \"d f", [_][]const u8{ "a", "b", "c", "\"d", "f" });
testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [][]const u8{
testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [_][]const u8{
".\\..\\zig-cache\\build",
"bin\\zig.exe",
".\\..",

View File

@ -18,6 +18,7 @@ const std = @import("std.zig");
const builtin = @import("builtin");
const assert = std.debug.assert;
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
const mem = std.mem;
const math = std.math;
const ziggurat = @import("rand/ziggurat.zig");
@ -501,7 +502,7 @@ const SplitMix64 = struct {
test "splitmix64 sequence" {
var r = SplitMix64.init(0xaeecf86f7878dd75);
const seq = []const u64{
const seq = [_]u64{
0x5dbd39db0178eb44,
0xa9900fb66b397da3,
0x5c1a28b1aeebcf5c,
@ -594,7 +595,7 @@ test "pcg sequence" {
const s1: u64 = 0x84e9c579ef59bbf7;
r.seedTwo(s0, s1);
const seq = []const u32{
const seq = [_]u32{
2881561918,
3063928540,
1199791034,
@ -643,7 +644,7 @@ pub const Xoroshiro128 = struct {
var s0: u64 = 0;
var s1: u64 = 0;
const table = []const u64{
const table = [_]u64{
0xbeac0467eba5facb,
0xd86b048b86aa9922,
};
@ -703,7 +704,7 @@ test "xoroshiro sequence" {
r.s[0] = 0xaeecf86f7878dd75;
r.s[1] = 0x01cd153642e72622;
const seq1 = []const u64{
const seq1 = [_]u64{
0xb0ba0da5bb600397,
0x18a08afde614dccc,
0xa2635b956a31b929,
@ -718,7 +719,7 @@ test "xoroshiro sequence" {
r.jump();
const seq2 = []const u64{
const seq2 = [_]u64{
0x95344a13556d3e22,
0xb4fb32dafa4d00df,
0xb2011d9ccdcfe2dd,
@ -821,7 +822,7 @@ pub const Isaac64 = struct {
self.m[0] = init_s;
// prescrambled golden ratio constants
var a = []const u64{
var a = [_]u64{
0x647c4677a2884b7c,
0xb9f8b322c73ac862,
0x8c0ea5053d4712a0,
@ -911,7 +912,7 @@ test "isaac64 sequence" {
var r = Isaac64.init(0);
// from reference implementation
const seq = []const u64{
const seq = [_]u64{
0xf67dfba498e4937c,
0x84a5066a9204f380,
0xfee34bd5f5514dbb,
@ -935,6 +936,105 @@ test "isaac64 sequence" {
}
}
/// Sfc64 pseudo-random number generator from Practically Random.
/// Fastest engine of pracrand and smallest footprint.
/// See http://pracrand.sourceforge.net/
pub const Sfc64 = struct {
random: Random,
a: u64 = undefined,
b: u64 = undefined,
c: u64 = undefined,
counter: u64 = undefined,
const Rotation = 24;
const RightShift = 11;
const LeftShift = 3;
pub fn init(init_s: u64) Sfc64 {
var x = Sfc64{
.random = Random{ .fillFn = fill },
};
x.seed(init_s);
return x;
}
fn next(self: *Sfc64) u64 {
const tmp = self.a +% self.b +% self.counter;
self.counter += 1;
self.a = self.b ^ (self.b >> RightShift);
self.b = self.c +% (self.c << LeftShift);
self.c = math.rotl(u64, self.c, Rotation) +% tmp;
return tmp;
}
fn seed(self: *Sfc64, init_s: u64) void {
self.a = init_s;
self.b = init_s;
self.c = init_s;
self.counter = 1;
var i: u32 = 0;
while (i < 12) : (i += 1) {
_ = self.next();
}
}
fn fill(r: *Random, buf: []u8) void {
const self = @fieldParentPtr(Sfc64, "random", r);
var i: usize = 0;
const aligned_len = buf.len - (buf.len & 7);
// Complete 8 byte segments.
while (i < aligned_len) : (i += 8) {
var n = self.next();
comptime var j: usize = 0;
inline while (j < 8) : (j += 1) {
buf[i + j] = @truncate(u8, n);
n >>= 8;
}
}
// Remaining. (cuts the stream)
if (i != buf.len) {
var n = self.next();
while (i < buf.len) : (i += 1) {
buf[i] = @truncate(u8, n);
n >>= 8;
}
}
}
};
test "Sfc64 sequence" {
// Unfortunately there does not seem to be an official test sequence.
var r = Sfc64.init(0);
const seq = [_]u64{
0x3acfa029e3cc6041,
0xf5b6515bf2ee419c,
0x1259635894a29b61,
0xb6ae75395f8ebd6,
0x225622285ce302e2,
0x520d28611395cb21,
0xdb909c818901599d,
0x8ffd195365216f57,
0xe8c4ad5e258ac04a,
0x8f8ef2c89fdb63ca,
0xf9865b01d98d8e2f,
0x46555871a65d08ba,
0x66868677c6298fcd,
0x2ce15a7e6329f57d,
0xb2f1833ca91ca79,
0x4b0890ac9bf453ca,
};
for (seq) |s| {
expectEqual(s, r.next());
}
}
// Actual Random helper function tests, pcg engine is assumed correct.
test "Random float" {
var prng = DefaultPrng.init(0);
@ -954,8 +1054,8 @@ test "Random float" {
test "Random shuffle" {
var prng = DefaultPrng.init(0);
var seq = []const u8{ 0, 1, 2, 3, 4 };
var seen = []bool{false} ** 5;
var seq = [_]u8{ 0, 1, 2, 3, 4 };
var seen = [_]bool{false} ** 5;
var i: usize = 0;
while (i < 1000) : (i += 1) {
@ -991,7 +1091,7 @@ fn testRange(r: *Random, start: i8, end: i8) void {
}
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;
var values_buffer = [_]bool{false} ** 0x100;
const values = values_buffer[0..count];
var i: usize = 0;
while (i < count) {

View File

@ -80,9 +80,9 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
const prealloc_exp = blk: {
// we don't use the prealloc_exp constant when prealloc_item_count is 0.
assert(prealloc_item_count != 0);
assert(std.math.isPowerOfTwo(prealloc_item_count));
const value = std.math.log2_int(usize, prealloc_item_count);
assert((1 << value) == prealloc_item_count); // prealloc_item_count must be a power of 2
break :blk @typeOf(1)(value);
};
const ShelfIndex = std.math.Log2Int(usize);
@ -108,7 +108,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
.allocator = allocator,
.len = 0,
.prealloc_segment = undefined,
.dynamic_segments = [][*]T{},
.dynamic_segments = [_][*]T{},
};
}
@ -187,7 +187,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
const len = @intCast(ShelfIndex, self.dynamic_segments.len);
self.freeShelves(len, 0);
self.allocator.free(self.dynamic_segments);
self.dynamic_segments = [][*]T{};
self.dynamic_segments = [_][*]T{};
return;
}
@ -334,9 +334,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
}
test "std.SegmentedList" {
var da = std.heap.DirectAllocator.init();
defer da.deinit();
var a = &da.allocator;
var a = std.heap.direct_allocator;
try testSegmentedList(0, a);
try testSegmentedList(1, a);
@ -382,7 +380,7 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
testing.expect(list.pop().? == 100);
testing.expect(list.len == 99);
try list.pushMany([]i32{
try list.pushMany([_]i32{
1,
2,
3,
@ -393,7 +391,7 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
testing.expect(list.pop().? == 1);
testing.expect(list.len == 99);
try list.pushMany([]const i32{});
try list.pushMany([_]i32{});
testing.expect(list.len == 99);
var i: i32 = 99;

Some files were not shown because too many files have changed in this diff Show More