diff --git a/examples/sha256sum_with_io_cp.v b/examples/sha256sum_with_io_cp.v new file mode 100644 index 0000000000..62e3d85814 --- /dev/null +++ b/examples/sha256sum_with_io_cp.v @@ -0,0 +1,28 @@ +// This example shows how to use io.cp, in combination with os.open and crypto.sha256, +// to read and hash files chunk by chunk, without loading them completely in memory (which may +// require too much RAM with big files). +// +// Usage: examples/sha256sum_with_io_cp [FILE]... +// +// Note: to compile the program, use: +// `v -prod -cflags "-march=native -mtune=native" examples/sha256sum_with_io_cp.v` +// After that, to compare it with say `sha256sum`, you can run: +// `v repeat -R 5 "sha256sum v" "examples/sha256sum_with_io_cp v` +import os +import io +import crypto.sha256 + +fn hash_file(path string) !string { + mut file := os.open(path)! + mut digest := sha256.new() + io.cp(mut file, mut digest, buffer_size: 256 * 1024)! + file.close() + return digest.sum([]).hex() +} + +fn main() { + for fpath in os.args#[1..] { + h := hash_file(fpath)! + println('${h} ${fpath}') + } +} diff --git a/vlib/io/io.v b/vlib/io/io.v index 8982b03867..46b13cffdd 100644 --- a/vlib/io/io.v +++ b/vlib/io/io.v @@ -1,18 +1,26 @@ module io -const buf_max_len = 1024 +// CopySettings provides additional options to io.cp +@[params] +pub struct CopySettings { +pub mut: + buffer_size int = 64 * 1024 // The buffer size used during the copying. A larger buffer is more performant, but uses more RAM. +} // cp copies from `src` to `dst` by allocating // a maximum of 1024 bytes buffer for reading // until either EOF is reached on `src` or an error occurs. // An error is returned if an error is encountered during write. -pub fn cp(mut src Reader, mut dst Writer) ! { - mut buf := []u8{len: buf_max_len} - for { - len := src.read(mut buf) or { break } - dst.write(buf[..len]) or { return err } +@[manualfree] +pub fn cp(mut src Reader, mut dst Writer, params CopySettings) ! { + mut buf := []u8{len: params.buffer_size} + defer { + unsafe { + buf.free() + } } - unsafe { - buf.free() + for { + bytes := src.read(mut buf) or { break } + dst.write(buf[..bytes]) or { return err } } }