mirror of
https://github.com/ziglang/zig.git
synced 2026-01-25 00:35:20 +00:00
Merge branch 'master' into translate-c-userland
This commit is contained in:
commit
c423697c78
@ -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")
|
||||
|
||||
@ -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
|
||||
```
|
||||
|
||||
|
||||
36
build.zig
36
build.zig
@ -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),
|
||||
});
|
||||
|
||||
@ -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",
|
||||
});
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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("'");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
}};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
96
src/ir.cpp
96
src/ir.cpp
@ -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;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
29
src/main.cpp
29
src/main.cpp
@ -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));
|
||||
|
||||
56
src/os.cpp
56
src/os.cpp
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ enum TokenId {
|
||||
TokenIdBitXorEq,
|
||||
TokenIdBracketStarBracket,
|
||||
TokenIdBracketStarCBracket,
|
||||
TokenIdBracketUnderscoreBracket,
|
||||
TokenIdCharLiteral,
|
||||
TokenIdCmpEq,
|
||||
TokenIdCmpGreaterOrEq,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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" {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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| {
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
168
std/crypto/gimli.zig
Normal 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);
|
||||
}
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
465
std/fmt.zig
465
std/fmt.zig
@ -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 {
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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 },
|
||||
|
||||
@ -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, ""));
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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"),
|
||||
}
|
||||
|
||||
124
std/fs/path.zig
124
std/fs/path.zig
@ -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" {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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,
|
||||
|
||||
41
std/heap.zig
41
std/heap.zig
@ -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);
|
||||
|
||||
20
std/io.zig
20
std/io.zig
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
32
std/math.zig
32
std/math.zig
@ -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;
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
127
std/mem.zig
127
std/mem.zig
@ -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,
|
||||
|
||||
@ -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"),
|
||||
|
||||
@ -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)));
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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, {});
|
||||
|
||||
@ -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",
|
||||
".\\..",
|
||||
|
||||
120
std/rand.zig
120
std/rand.zig
@ -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) {
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user