From ce92bf8da0b5cdf093f64c8d6134e86b730307ec Mon Sep 17 00:00:00 2001 From: Bartimus <465079+bartimus-primed@users.noreply.github.com> Date: Sat, 6 Mar 2021 13:44:53 -0500 Subject: [PATCH] os.File: add .read_struct_at and .write_struct_at (#9114) --- vlib/os/file.c.v | 42 ++++++++++++++++++++++++++++++++++++++++++ vlib/os/file_test.v | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/vlib/os/file.c.v b/vlib/os/file.c.v index 2f88ca0c22..fe08b48788 100644 --- a/vlib/os/file.c.v +++ b/vlib/os/file.c.v @@ -337,6 +337,27 @@ pub fn (mut f File) read_struct(mut t T) ? { } } +// read_struct_at reads a single struct of type `T` at position specified in file +pub fn (mut f File) read_struct_at(mut t T, pos int) ? { + if !f.is_opened { + return none + } + tsize := int(sizeof(*t)) + if tsize == 0 { + return none + } + C.errno = 0 + C.fseek(f.cfile, pos, C.SEEK_SET) + nbytes := int(C.fread(t, 1, tsize, f.cfile)) + C.fseek(f.cfile, 0, C.SEEK_END) + if C.errno != 0 { + return error(posix_get_error_msg(C.errno)) + } + if nbytes != tsize { + return error_with_code('incomplete struct read', nbytes) + } +} + // write_struct writes a single struct of type `T` pub fn (mut f File) write_struct(t &T) ? { if !f.is_opened { @@ -355,3 +376,24 @@ pub fn (mut f File) write_struct(t &T) ? { return error_with_code('incomplete struct write', nbytes) } } + +// write_struct_at writes a single struct of type `T` at position specified in file +pub fn (mut f File) write_struct_at(t &T, pos int) ? { + if !f.is_opened { + return error('file is not opened') + } + tsize := int(sizeof(*t)) + if tsize == 0 { + return error('struct size is 0') + } + C.errno = 0 + C.fseek(f.cfile, pos, C.SEEK_SET) + nbytes := int(C.fwrite(t, 1, tsize, f.cfile)) + C.fseek(f.cfile, 0, C.SEEK_END) + if C.errno != 0 { + return error(posix_get_error_msg(C.errno)) + } + if nbytes != tsize { + return error_with_code('incomplete struct write', nbytes) + } +} diff --git a/vlib/os/file_test.v b/vlib/os/file_test.v index 47ec3b79c7..6fdd837437 100644 --- a/vlib/os/file_test.v +++ b/vlib/os/file_test.v @@ -6,6 +6,18 @@ struct Point { z f64 } +struct Extended_Point { + a f64 + b f64 + c f64 + d f64 + e f64 + f f64 + g f64 + h f64 + i f64 +} + const unit_point = Point{1.0, 1.0, 1.0} const tfolder = os.join_path(os.temp_dir(), 'os_file_test') @@ -14,6 +26,8 @@ const tfile = os.join_path(tfolder, 'test_file') const another_point = Point{0.25, 2.25, 6.25} +const extended_point = Extended_Point{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0} + fn testsuite_begin() { os.rmdir_all(tfolder) or { } assert !os.is_dir(tfolder) @@ -54,3 +68,29 @@ fn test_read_struct() { assert p == another_point } + +fn test_read_struct_at() { + mut f := os.open_file(tfile, 'w') or { panic(err) } + f.write([byte(1), 2, 3]) or { panic(err) } + f.write_struct(another_point) or { panic(err) } + f.close() + f = os.open_file(tfile, 'r') or { panic(err) } + mut p := Point{} + f.read_struct_at(mut p, 3) or { panic(err) } + f.close() + + assert p == another_point +} + +fn test_write_struct_at() { + mut f := os.open_file(tfile, 'w') or { panic(err) } + f.write_struct(extended_point) or { panic(err) } + f.write_struct_at(another_point, 3) or { panic(err) } + f.close() + f = os.open_file(tfile, 'r') or { panic(err) } + mut p := Point{} + f.read_struct_at(mut p, 3) or { panic(err) } + f.close() + + assert p == another_point +}