diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-09-10 00:25:37 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-09-10 10:26:52 -0400 |
| commit | 0489d06c249d16457d66523b5c407fc7ddeca45a (patch) | |
| tree | 799b4abcf50830158975f8d408c7ce52ed401a59 /std/io.zig | |
| parent | a29ce78651c05029dbd72064752a099885edfd0c (diff) | |
| download | zig-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.zig | 188 |
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 { |
