aboutsummaryrefslogtreecommitdiff
path: root/std/io.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-09-10 00:25:37 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-09-10 10:26:52 -0400
commit0489d06c249d16457d66523b5c407fc7ddeca45a (patch)
tree799b4abcf50830158975f8d408c7ce52ed401a59 /std/io.zig
parenta29ce78651c05029dbd72064752a099885edfd0c (diff)
downloadzig-0489d06c249d16457d66523b5c407fc7ddeca45a.tar.gz
zig-0489d06c249d16457d66523b5c407fc7ddeca45a.zip
make the std lib support event-based I/O
also add -fstack-report
Diffstat (limited to 'std/io.zig')
-rw-r--r--std/io.zig188
1 files changed, 14 insertions, 174 deletions
diff --git a/std/io.zig b/std/io.zig
index dcf2ec5f61..25106e24be 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -1,5 +1,6 @@
const std = @import("std.zig");
const builtin = @import("builtin");
+const root = @import("root");
const c = std.c;
const math = std.math;
@@ -15,6 +16,18 @@ const fmt = std.fmt;
const File = std.fs.File;
const testing = std.testing;
+pub const Mode = enum {
+ blocking,
+ evented,
+};
+pub const mode: Mode = if (@hasDecl(root, "io_mode"))
+ root.io_mode
+else if (@hasDecl(root, "event_loop"))
+ Mode.evented
+else
+ Mode.blocking;
+pub const is_async = mode != .blocking;
+
pub const GetStdIoError = os.windows.GetStdHandleError;
pub fn getStdOut() GetStdIoError!File {
@@ -44,180 +57,7 @@ pub fn getStdIn() GetStdIoError!File {
pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
pub const SliceSeekableInStream = @import("io/seekable_stream.zig").SliceSeekableInStream;
pub const COutStream = @import("io/c_out_stream.zig").COutStream;
-
-pub fn InStream(comptime ReadError: type) type {
- return struct {
- const Self = @This();
- pub const Error = ReadError;
-
- /// Return the number of bytes read. If the number read is smaller than buf.len, it
- /// means the stream reached the end. Reaching the end of a stream is not an error
- /// condition.
- readFn: fn (self: *Self, buffer: []u8) Error!usize,
-
- /// Replaces `buffer` contents by reading from the stream until it is finished.
- /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and
- /// the contents read from the stream are lost.
- pub fn readAllBuffer(self: *Self, buffer: *Buffer, max_size: usize) !void {
- try buffer.resize(0);
-
- var actual_buf_len: usize = 0;
- while (true) {
- const dest_slice = buffer.toSlice()[actual_buf_len..];
- const bytes_read = try self.readFull(dest_slice);
- actual_buf_len += bytes_read;
-
- if (bytes_read != dest_slice.len) {
- buffer.shrink(actual_buf_len);
- return;
- }
-
- const new_buf_size = math.min(max_size, actual_buf_len + mem.page_size);
- if (new_buf_size == actual_buf_len) return error.StreamTooLong;
- try buffer.resize(new_buf_size);
- }
- }
-
- /// Allocates enough memory to hold all the contents of the stream. If the allocated
- /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
- /// Caller owns returned memory.
- /// If this function returns an error, the contents from the stream read so far are lost.
- pub fn readAllAlloc(self: *Self, allocator: *mem.Allocator, max_size: usize) ![]u8 {
- var buf = Buffer.initNull(allocator);
- defer buf.deinit();
-
- try self.readAllBuffer(&buf, max_size);
- return buf.toOwnedSlice();
- }
-
- /// Replaces `buffer` contents by reading from the stream until `delimiter` is found.
- /// Does not include the delimiter in the result.
- /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents
- /// read from the stream so far are lost.
- pub fn readUntilDelimiterBuffer(self: *Self, buffer: *Buffer, delimiter: u8, max_size: usize) !void {
- try buffer.resize(0);
-
- while (true) {
- var byte: u8 = try self.readByte();
-
- if (byte == delimiter) {
- return;
- }
-
- if (buffer.len() == max_size) {
- return error.StreamTooLong;
- }
-
- try buffer.appendByte(byte);
- }
- }
-
- /// Allocates enough memory to read until `delimiter`. If the allocated
- /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
- /// Caller owns returned memory.
- /// If this function returns an error, the contents from the stream read so far are lost.
- pub fn readUntilDelimiterAlloc(self: *Self, allocator: *mem.Allocator, delimiter: u8, max_size: usize) ![]u8 {
- var buf = Buffer.initNull(allocator);
- defer buf.deinit();
-
- try self.readUntilDelimiterBuffer(&buf, delimiter, max_size);
- return buf.toOwnedSlice();
- }
-
- /// Returns the number of bytes read. It may be less than buffer.len.
- /// If the number of bytes read is 0, it means end of stream.
- /// End of stream is not an error condition.
- pub fn read(self: *Self, buffer: []u8) Error!usize {
- return self.readFn(self, buffer);
- }
-
- /// Returns the number of bytes read. If the number read is smaller than buf.len, it
- /// means the stream reached the end. Reaching the end of a stream is not an error
- /// condition.
- pub fn readFull(self: *Self, buffer: []u8) Error!usize {
- var index: usize = 0;
- while (index != buffer.len) {
- const amt = try self.read(buffer[index..]);
- if (amt == 0) return index;
- index += amt;
- }
- return index;
- }
-
- /// Same as `readFull` but end of stream returns `error.EndOfStream`.
- pub fn readNoEof(self: *Self, buf: []u8) !void {
- const amt_read = try self.readFull(buf);
- if (amt_read < buf.len) return error.EndOfStream;
- }
-
- /// Reads 1 byte from the stream or returns `error.EndOfStream`.
- pub fn readByte(self: *Self) !u8 {
- var result: [1]u8 = undefined;
- try self.readNoEof(result[0..]);
- return result[0];
- }
-
- /// Same as `readByte` except the returned byte is signed.
- pub fn readByteSigned(self: *Self) !i8 {
- return @bitCast(i8, try self.readByte());
- }
-
- /// Reads a native-endian integer
- pub fn readIntNative(self: *Self, comptime T: type) !T {
- 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: [(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: [(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: [(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: [(T.bit_count + 7) / 8]u8 = undefined;
- try self.readNoEof(bytes[0..]);
- return mem.readInt(T, &bytes, endian);
- }
-
- pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
- assert(size <= @sizeOf(ReturnType));
- var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined;
- const bytes = bytes_buf[0..size];
- try self.readNoEof(bytes);
- return mem.readVarInt(ReturnType, bytes, endian);
- }
-
- pub fn skipBytes(self: *Self, num_bytes: u64) !void {
- var i: u64 = 0;
- while (i < num_bytes) : (i += 1) {
- _ = try self.readByte();
- }
- }
-
- pub fn readStruct(self: *Self, comptime T: type) !T {
- // Only extern and packed structs have defined in-memory layout.
- comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto);
- var res: [1]T = undefined;
- try self.readNoEof(@sliceToBytes(res[0..]));
- return res[0];
- }
- };
-}
+pub const InStream = @import("io/in_stream.zig").InStream;
pub fn OutStream(comptime WriteError: type) type {
return struct {