Skip to content

Instantly share code, notes, and snippets.

@agagniere
Last active December 2, 2023 17:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agagniere/41b26032b8051c507dcda85a28bbaddc to your computer and use it in GitHub Desktop.
Save agagniere/41b26032b8051c507dcda85a28bbaddc to your computer and use it in GitHub Desktop.
Reading an infinite stream line per line

We compare various ways of reading the first line of stdin. In our test the first \n is the 14th character.

File Notable function used Number of calls to read
single.c read 15
stdio.c fread 2
buffered.c read, memchr 2
single.zig read 14
until.zig readUntilDelimiter 14
stream.zig streamUntilDelimiter 14
buffered.zig bufferedReader 1
$ make run
cc     single.c   -o single
cc     stdio.c   -o stdio
cc     buffered.c   -o buffered
zig build-exe single.zig --name single.exe
zig build-exe until.zig --name until.exe
zig build-exe stream.zig --name stream.exe
zig build-exe buffered.zig --name buffered.exe
for bin in single stdio buffered single.exe until.exe stream.exe buffered.exe; do echo -n " - $bin: "; echo "Hello World !\nNooo\nKO" | strace -e read ./$bin 2>&1 >/dev/null | grep read | wc -l ; done
 - single: 15
 - stdio: 2
 - buffered: 2
 - single.exe: 14
 - until.exe: 14
 - stream.exe: 14
 - buffered.exe: 1
#include <string.h> // memchr
#include <unistd.h> // read, write
#define SIZE 4096
int main()
{
char buffer[SIZE];
char* end;
ssize_t count;
ssize_t to_write;
while ((count = read(0, buffer, SIZE)) > 0)
{
end = memchr(buffer, '\n', count);
to_write = end ? end - buffer : count;
write(1, buffer, to_write);
if (end)
break;
}
}
const std = @import("std");
pub fn main() !void {
var buffered_in = std.io.bufferedReader(std.io.getStdIn().reader());
try buffered_in.reader().streamUntilDelimiter(std.io.getStdOut().writer(), '\n', null);
}
bins = single stdio buffered single.exe until.exe stream.exe buffered.exe
all: $(bins)
run: $(bins)
for bin in $^; do echo -n " - $$bin: "; echo "Hello World !\nNooo\nKO" | strace -e read ./$$bin 2>&1 >/dev/null | grep read | wc -l ; done
clean:
$(RM) $(bins)
%.exe: %.zig
zig build-exe $< --name $@
int main()
{
char c;
while (read(0, &c, 1) > 0)
{
if (c == '\n')
break;
write(1, &c, 1);
}
}
const std = @import("std");
pub fn main() !void {
const stdin = std.io.getStdIn();
var buffer: [1]u8 = undefined;
while (stdin.read(&buffer) catch 0 > 0) {
if (buffer[0] == '\n')
break;
_ = std.io.getStdOut().write(&buffer) catch break;
}
}
#include <stdio.h>
int main()
{
char c;
while (fread(&c, 1, 1, stdin) > 0)
{
if (c == '\n')
break;
fwrite(&c, 1, 1, stdout);
}
fflush(stdout);
}
const std = @import("std");
pub fn main() !void {
const stdin = std.io.getStdIn();
try stdin.reader().streamUntilDelimiter(std.io.getStdOut().writer(), '\n', null);
}
const std = @import("std");
pub fn main() !void {
const stdin = std.io.getStdIn();
var buffer: [4096]u8 = undefined;
var read: []u8 = stdin.reader().readUntilDelimiter(&buffer, '\n') catch undefined;
_ = try std.io.getStdOut().write(read);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment