aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/build.zig7
-rw-r--r--lib/std/build/emit_raw.zig4
-rw-r--r--lib/std/builtin.zig36
-rw-r--r--lib/std/fs.zig9
-rw-r--r--lib/std/fs/file.zig29
-rw-r--r--lib/std/math.zig5
-rw-r--r--lib/std/math/ceil.zig43
-rw-r--r--lib/std/math/floor.zig43
-rw-r--r--lib/std/math/round.zig50
-rw-r--r--lib/std/math/trunc.zig37
-rw-r--r--lib/std/meta.zig12
-rw-r--r--lib/std/unicode.zig41
12 files changed, 292 insertions, 24 deletions
diff --git a/lib/std/build.zig b/lib/std/build.zig
index d98ef71a59..a4d922f2ad 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -2558,3 +2558,10 @@ pub const InstalledFile = struct {
dir: InstallDir,
path: []const u8,
};
+
+test "" {
+ // The only purpose of this test is to get all these untested functions
+ // to be referenced to avoid regression so it is okay to skip some targets.
+ if (comptime std.Target.current.cpu.arch.ptrBitWidth() == 64)
+ std.meta.refAllDecls(@This());
+}
diff --git a/lib/std/build/emit_raw.zig b/lib/std/build/emit_raw.zig
index 8fd27d6cfc..746b0ac91b 100644
--- a/lib/std/build/emit_raw.zig
+++ b/lib/std/build/emit_raw.zig
@@ -215,3 +215,7 @@ pub const InstallRawStep = struct {
try emitRaw(builder.allocator, full_src_path, full_dest_path);
}
};
+
+test "" {
+ std.meta.refAllDecls(InstallRawStep);
+}
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index af8033ae91..0c7e534bed 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -131,6 +131,15 @@ pub const CallingConvention = enum {
AAPCSVFP,
};
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const SourceLocation = struct {
+ file: [:0]const u8,
+ fn_name: [:0]const u8,
+ line: u32,
+ column: u32,
+};
+
pub const TypeId = @TagType(TypeInfo);
/// This data structure is used by the Zig language code generation and
@@ -157,7 +166,7 @@ pub const TypeInfo = union(enum) {
Fn: Fn,
BoundFn: Fn,
Opaque: void,
- Frame: void,
+ Frame: Frame,
AnyFrame: AnyFrame,
Vector: Vector,
EnumLiteral: void,
@@ -235,8 +244,8 @@ pub const TypeInfo = union(enum) {
/// therefore must be kept in sync with the compiler implementation.
pub const Struct = struct {
layout: ContainerLayout,
- fields: []StructField,
- decls: []Declaration,
+ fields: []const StructField,
+ decls: []const Declaration,
};
/// This data structure is used by the Zig language code generation and
@@ -256,12 +265,13 @@ pub const TypeInfo = union(enum) {
/// therefore must be kept in sync with the compiler implementation.
pub const Error = struct {
name: []const u8,
+ /// This field is ignored when using @Type().
value: comptime_int,
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
- pub const ErrorSet = ?[]Error;
+ pub const ErrorSet = ?[]const Error;
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
@@ -275,8 +285,8 @@ pub const TypeInfo = union(enum) {
pub const Enum = struct {
layout: ContainerLayout,
tag_type: type,
- fields: []EnumField,
- decls: []Declaration,
+ fields: []const EnumField,
+ decls: []const Declaration,
is_exhaustive: bool,
};
@@ -293,8 +303,8 @@ pub const TypeInfo = union(enum) {
pub const Union = struct {
layout: ContainerLayout,
tag_type: ?type,
- fields: []UnionField,
- decls: []Declaration,
+ fields: []const UnionField,
+ decls: []const Declaration,
};
/// This data structure is used by the Zig language code generation and
@@ -312,7 +322,13 @@ pub const TypeInfo = union(enum) {
is_generic: bool,
is_var_args: bool,
return_type: ?type,
- args: []FnArg,
+ args: []const FnArg,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Frame = struct {
+ function: var,
};
/// This data structure is used by the Zig language code generation and
@@ -352,7 +368,7 @@ pub const TypeInfo = union(enum) {
is_export: bool,
lib_name: ?[]const u8,
return_type: type,
- arg_names: [][]const u8,
+ arg_names: []const []const u8,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 262aa4872d..3ff4819ac5 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -1229,14 +1229,9 @@ pub const Dir = struct {
var file = try self.openFile(file_path, .{});
defer file.close();
- const size = math.cast(usize, try file.getEndPos()) catch math.maxInt(usize);
- if (size > max_bytes) return error.FileTooBig;
+ const stat_size = try file.getEndPos();
- const buf = try allocator.allocWithOptions(u8, size, alignment, optional_sentinel);
- errdefer allocator.free(buf);
-
- try file.inStream().readNoEof(buf);
- return buf;
+ return file.readAllAllocOptions(allocator, stat_size, max_bytes, alignment, optional_sentinel);
}
pub const DeleteTreeError = error{
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index d950a1cfa4..0a3c1b5ab7 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -209,7 +209,7 @@ pub const File = struct {
/// TODO: integrate with async I/O
pub fn mode(self: File) ModeError!Mode {
if (builtin.os.tag == .windows) {
- return {};
+ return 0;
}
return (try self.stat()).mode;
}
@@ -306,6 +306,33 @@ pub const File = struct {
try os.futimens(self.handle, &times);
}
+ /// On success, caller owns returned buffer.
+ /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
+ pub fn readAllAlloc(self: File, allocator: *mem.Allocator, stat_size: u64, max_bytes: usize) ![]u8 {
+ return self.readAllAllocOptions(allocator, stat_size, max_bytes, @alignOf(u8), null);
+ }
+
+ /// On success, caller owns returned buffer.
+ /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
+ /// Allows specifying alignment and a sentinel value.
+ pub fn readAllAllocOptions(
+ self: File,
+ allocator: *mem.Allocator,
+ stat_size: u64,
+ max_bytes: usize,
+ comptime alignment: u29,
+ comptime optional_sentinel: ?u8,
+ ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {
+ const size = math.cast(usize, stat_size) catch math.maxInt(usize);
+ if (size > max_bytes) return error.FileTooBig;
+
+ const buf = try allocator.allocWithOptions(u8, size, alignment, optional_sentinel);
+ errdefer allocator.free(buf);
+
+ try self.inStream().readNoEof(buf);
+ return buf;
+ }
+
pub const ReadError = os.ReadError;
pub const PReadError = os.PReadError;
diff --git a/lib/std/math.zig b/lib/std/math.zig
index 5cf6d40d8a..799c42846b 100644
--- a/lib/std/math.zig
+++ b/lib/std/math.zig
@@ -122,6 +122,11 @@ pub fn forceEval(value: var) void {
const p = @ptrCast(*volatile f64, &x);
p.* = x;
},
+ f128 => {
+ var x: f128 = undefined;
+ const p = @ptrCast(*volatile f128, &x);
+ p.* = x;
+ },
else => {
@compileError("forceEval not implemented for " ++ @typeName(T));
},
diff --git a/lib/std/math/ceil.zig b/lib/std/math/ceil.zig
index b94e13a176..e3b5679318 100644
--- a/lib/std/math/ceil.zig
+++ b/lib/std/math/ceil.zig
@@ -20,6 +20,7 @@ pub fn ceil(x: var) @TypeOf(x) {
return switch (T) {
f32 => ceil32(x),
f64 => ceil64(x),
+ f128 => ceil128(x),
else => @compileError("ceil not implemented for " ++ @typeName(T)),
};
}
@@ -86,9 +87,37 @@ fn ceil64(x: f64) f64 {
}
}
+fn ceil128(x: f128) f128 {
+ const u = @bitCast(u128, x);
+ const e = (u >> 112) & 0x7FFF;
+ var y: f128 = undefined;
+
+ if (e >= 0x3FFF + 112 or x == 0) return x;
+
+ if (u >> 127 != 0) {
+ y = x - math.f128_toint + math.f128_toint - x;
+ } else {
+ y = x + math.f128_toint - math.f128_toint - x;
+ }
+
+ if (e <= 0x3FFF - 1) {
+ math.forceEval(y);
+ if (u >> 127 != 0) {
+ return -0.0;
+ } else {
+ return 1.0;
+ }
+ } else if (y < 0) {
+ return x + y + 1;
+ } else {
+ return x + y;
+ }
+}
+
test "math.ceil" {
expect(ceil(@as(f32, 0.0)) == ceil32(0.0));
expect(ceil(@as(f64, 0.0)) == ceil64(0.0));
+ expect(ceil(@as(f128, 0.0)) == ceil128(0.0));
}
test "math.ceil32" {
@@ -103,6 +132,12 @@ test "math.ceil64" {
expect(ceil64(0.2) == 1.0);
}
+test "math.ceil128" {
+ expect(ceil128(1.3) == 2.0);
+ expect(ceil128(-1.3) == -1.0);
+ expect(ceil128(0.2) == 1.0);
+}
+
test "math.ceil32.special" {
expect(ceil32(0.0) == 0.0);
expect(ceil32(-0.0) == -0.0);
@@ -118,3 +153,11 @@ test "math.ceil64.special" {
expect(math.isNegativeInf(ceil64(-math.inf(f64))));
expect(math.isNan(ceil64(math.nan(f64))));
}
+
+test "math.ceil128.special" {
+ expect(ceil128(0.0) == 0.0);
+ expect(ceil128(-0.0) == -0.0);
+ expect(math.isPositiveInf(ceil128(math.inf(f128))));
+ expect(math.isNegativeInf(ceil128(-math.inf(f128))));
+ expect(math.isNan(ceil128(math.nan(f128))));
+}
diff --git a/lib/std/math/floor.zig b/lib/std/math/floor.zig
index 1eda362e69..565e2911a9 100644
--- a/lib/std/math/floor.zig
+++ b/lib/std/math/floor.zig
@@ -21,6 +21,7 @@ pub fn floor(x: var) @TypeOf(x) {
f16 => floor16(x),
f32 => floor32(x),
f64 => floor64(x),
+ f128 => floor128(x),
else => @compileError("floor not implemented for " ++ @typeName(T)),
};
}
@@ -122,10 +123,38 @@ fn floor64(x: f64) f64 {
}
}
+fn floor128(x: f128) f128 {
+ const u = @bitCast(u128, x);
+ const e = (u >> 112) & 0x7FFF;
+ var y: f128 = undefined;
+
+ if (e >= 0x3FFF + 112 or x == 0) return x;
+
+ if (u >> 127 != 0) {
+ y = x - math.f128_toint + math.f128_toint - x;
+ } else {
+ y = x + math.f128_toint - math.f128_toint - x;
+ }
+
+ if (e <= 0x3FFF - 1) {
+ math.forceEval(y);
+ if (u >> 127 != 0) {
+ return -1.0;
+ } else {
+ return 0.0;
+ }
+ } else if (y > 0) {
+ return x + y - 1;
+ } else {
+ return x + y;
+ }
+}
+
test "math.floor" {
expect(floor(@as(f16, 1.3)) == floor16(1.3));
expect(floor(@as(f32, 1.3)) == floor32(1.3));
expect(floor(@as(f64, 1.3)) == floor64(1.3));
+ expect(floor(@as(f128, 1.3)) == floor128(1.3));
}
test "math.floor16" {
@@ -146,6 +175,12 @@ test "math.floor64" {
expect(floor64(0.2) == 0.0);
}
+test "math.floor128" {
+ expect(floor128(1.3) == 1.0);
+ expect(floor128(-1.3) == -2.0);
+ expect(floor128(0.2) == 0.0);
+}
+
test "math.floor16.special" {
expect(floor16(0.0) == 0.0);
expect(floor16(-0.0) == -0.0);
@@ -169,3 +204,11 @@ test "math.floor64.special" {
expect(math.isNegativeInf(floor64(-math.inf(f64))));
expect(math.isNan(floor64(math.nan(f64))));
}
+
+test "math.floor128.special" {
+ expect(floor128(0.0) == 0.0);
+ expect(floor128(-0.0) == -0.0);
+ expect(math.isPositiveInf(floor128(math.inf(f128))));
+ expect(math.isNegativeInf(floor128(-math.inf(f128))));
+ expect(math.isNan(floor128(math.nan(f128))));
+}
diff --git a/lib/std/math/round.zig b/lib/std/math/round.zig
index dceb3ed770..052c0f7670 100644
--- a/lib/std/math/round.zig
+++ b/lib/std/math/round.zig
@@ -20,6 +20,7 @@ pub fn round(x: var) @TypeOf(x) {
return switch (T) {
f32 => round32(x),
f64 => round64(x),
+ f128 => round128(x),
else => @compileError("round not implemented for " ++ @typeName(T)),
};
}
@@ -90,9 +91,43 @@ fn round64(x_: f64) f64 {
}
}
+fn round128(x_: f128) f128 {
+ var x = x_;
+ const u = @bitCast(u128, x);
+ const e = (u >> 112) & 0x7FFF;
+ var y: f128 = undefined;
+
+ if (e >= 0x3FFF + 112) {
+ return x;
+ }
+ if (u >> 127 != 0) {
+ x = -x;
+ }
+ if (e < 0x3FFF - 1) {
+ math.forceEval(x + math.f64_toint);
+ return 0 * @bitCast(f128, u);
+ }
+
+ y = x + math.f128_toint - math.f128_toint - x;
+ if (y > 0.5) {
+ y = y + x - 1;
+ } else if (y <= -0.5) {
+ y = y + x + 1;
+ } else {
+ y = y + x;
+ }
+
+ if (u >> 127 != 0) {
+ return -y;
+ } else {
+ return y;
+ }
+}
+
test "math.round" {
expect(round(@as(f32, 1.3)) == round32(1.3));
expect(round(@as(f64, 1.3)) == round64(1.3));
+ expect(round(@as(f128, 1.3)) == round128(1.3));
}
test "math.round32" {
@@ -109,6 +144,13 @@ test "math.round64" {
expect(round64(1.8) == 2.0);
}
+test "math.round128" {
+ expect(round128(1.3) == 1.0);
+ expect(round128(-1.3) == -1.0);
+ expect(round128(0.2) == 0.0);
+ expect(round128(1.8) == 2.0);
+}
+
test "math.round32.special" {
expect(round32(0.0) == 0.0);
expect(round32(-0.0) == -0.0);
@@ -124,3 +166,11 @@ test "math.round64.special" {
expect(math.isNegativeInf(round64(-math.inf(f64))));
expect(math.isNan(round64(math.nan(f64))));
}
+
+test "math.round128.special" {
+ expect(round128(0.0) == 0.0);
+ expect(round128(-0.0) == -0.0);
+ expect(math.isPositiveInf(round128(math.inf(f128))));
+ expect(math.isNegativeInf(round128(-math.inf(f128))));
+ expect(math.isNan(round128(math.nan(f128))));
+}
diff --git a/lib/std/math/trunc.zig b/lib/std/math/trunc.zig
index b70f0c6be3..cdd2fa3c6b 100644
--- a/lib/std/math/trunc.zig
+++ b/lib/std/math/trunc.zig
@@ -20,6 +20,7 @@ pub fn trunc(x: var) @TypeOf(x) {
return switch (T) {
f32 => trunc32(x),
f64 => trunc64(x),
+ f128 => trunc128(x),
else => @compileError("trunc not implemented for " ++ @typeName(T)),
};
}
@@ -66,9 +67,31 @@ fn trunc64(x: f64) f64 {
}
}
+fn trunc128(x: f128) f128 {
+ const u = @bitCast(u128, x);
+ var e = @intCast(i32, ((u >> 112) & 0x7FFF)) - 0x3FFF + 16;
+ var m: u128 = undefined;
+
+ if (e >= 112 + 16) {
+ return x;
+ }
+ if (e < 16) {
+ e = 1;
+ }
+
+ m = @as(u128, maxInt(u128)) >> @intCast(u7, e);
+ if (u & m == 0) {
+ return x;
+ } else {
+ math.forceEval(x + 0x1p120);
+ return @bitCast(f128, u & ~m);
+ }
+}
+
test "math.trunc" {
expect(trunc(@as(f32, 1.3)) == trunc32(1.3));
expect(trunc(@as(f64, 1.3)) == trunc64(1.3));
+ expect(trunc(@as(f128, 1.3)) == trunc128(1.3));
}
test "math.trunc32" {
@@ -83,6 +106,12 @@ test "math.trunc64" {
expect(trunc64(0.2) == 0.0);
}
+test "math.trunc128" {
+ expect(trunc128(1.3) == 1.0);
+ expect(trunc128(-1.3) == -1.0);
+ expect(trunc128(0.2) == 0.0);
+}
+
test "math.trunc32.special" {
expect(trunc32(0.0) == 0.0); // 0x3F800000
expect(trunc32(-0.0) == -0.0);
@@ -98,3 +127,11 @@ test "math.trunc64.special" {
expect(math.isNegativeInf(trunc64(-math.inf(f64))));
expect(math.isNan(trunc64(math.nan(f64))));
}
+
+test "math.trunc128.special" {
+ expect(trunc128(0.0) == 0.0);
+ expect(trunc128(-0.0) == -0.0);
+ expect(math.isPositiveInf(trunc128(math.inf(f128))));
+ expect(math.isNegativeInf(trunc128(-math.inf(f128))));
+ expect(math.isNan(trunc128(math.nan(f128))));
+}
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 75f507da74..f93f035429 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -250,7 +250,7 @@ test "std.meta.containerLayout" {
testing.expect(containerLayout(U3) == .Extern);
}
-pub fn declarations(comptime T: type) []TypeInfo.Declaration {
+pub fn declarations(comptime T: type) []const TypeInfo.Declaration {
return switch (@typeInfo(T)) {
.Struct => |info| info.decls,
.Enum => |info| info.decls,
@@ -274,7 +274,7 @@ test "std.meta.declarations" {
fn a() void {}
};
- const decls = comptime [_][]TypeInfo.Declaration{
+ const decls = comptime [_][]const TypeInfo.Declaration{
declarations(E1),
declarations(S1),
declarations(U1),
@@ -323,10 +323,10 @@ test "std.meta.declarationInfo" {
}
pub fn fields(comptime T: type) switch (@typeInfo(T)) {
- .Struct => []TypeInfo.StructField,
- .Union => []TypeInfo.UnionField,
- .ErrorSet => []TypeInfo.Error,
- .Enum => []TypeInfo.EnumField,
+ .Struct => []const TypeInfo.StructField,
+ .Union => []const TypeInfo.UnionField,
+ .ErrorSet => []const TypeInfo.Error,
+ .Enum => []const TypeInfo.EnumField,
else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
} {
return switch (@typeInfo(T)) {
diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig
index df2e16a4bf..2c88d2ba0c 100644
--- a/lib/std/unicode.zig
+++ b/lib/std/unicode.zig
@@ -235,6 +235,22 @@ pub const Utf8Iterator = struct {
else => unreachable,
}
}
+
+ /// Look ahead at the next n codepoints without advancing the iterator.
+ /// If fewer than n codepoints are available, then return the remainder of the string.
+ pub fn peek(it: *Utf8Iterator, n: usize) []const u8 {
+ const original_i = it.i;
+ defer it.i = original_i;
+
+ var end_ix = original_i;
+ var found: usize = 0;
+ while (found < n) : (found += 1) {
+ const next_codepoint = it.nextCodepointSlice() orelse return it.bytes[original_i..];
+ end_ix += next_codepoint.len;
+ }
+
+ return it.bytes[original_i..end_ix];
+ }
};
pub const Utf16LeIterator = struct {
@@ -451,6 +467,31 @@ fn testMiscInvalidUtf8() void {
testValid("\xee\x80\x80", 0xe000);
}
+test "utf8 iterator peeking" {
+ comptime testUtf8Peeking();
+ testUtf8Peeking();
+}
+
+fn testUtf8Peeking() void {
+ const s = Utf8View.initComptime("noël");
+ var it = s.iterator();
+
+ testing.expect(std.mem.eql(u8, "n", it.nextCodepointSlice().?));
+
+ testing.expect(std.mem.eql(u8, "o", it.peek(1)));
+ testing.expect(std.mem.eql(u8, "oë", it.peek(2)));
+ testing.expect(std.mem.eql(u8, "oël", it.peek(3)));
+ testing.expect(std.mem.eql(u8, "oël", it.peek(4)));
+ testing.expect(std.mem.eql(u8, "oël", it.peek(10)));
+
+ testing.expect(std.mem.eql(u8, "o", it.nextCodepointSlice().?));
+ testing.expect(std.mem.eql(u8, "ë", it.nextCodepointSlice().?));
+ testing.expect(std.mem.eql(u8, "l", it.nextCodepointSlice().?));
+ testing.expect(it.nextCodepointSlice() == null);
+
+ testing.expect(std.mem.eql(u8, &[_]u8{}, it.peek(1)));
+}
+
fn testError(bytes: []const u8, expected_err: anyerror) void {
testing.expectError(expected_err, testDecode(bytes));
}