os: implement File.seek/2 and File.tell/0
parent
054bd67490
commit
d7dcb47db3
|
@ -16,6 +16,7 @@ struct FileInfo {
|
||||||
fn C.fseeko(&C.FILE, u64, int) int
|
fn C.fseeko(&C.FILE, u64, int) int
|
||||||
|
|
||||||
fn C._fseeki64(&C.FILE, u64, int) int
|
fn C._fseeki64(&C.FILE, u64, int) int
|
||||||
|
fn C._ftelli64(&C.FILE) i64
|
||||||
|
|
||||||
fn C.getc(&C.FILE) int
|
fn C.getc(&C.FILE) int
|
||||||
|
|
||||||
|
@ -727,3 +728,60 @@ pub fn (mut f File) write_raw_at<T>(t &T, pos u64) ? {
|
||||||
return error_with_code('incomplete struct write', nbytes)
|
return error_with_code('incomplete struct write', nbytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum SeekMode {
|
||||||
|
start
|
||||||
|
current
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
// seek moves the file cursor (if any) associated with a file
|
||||||
|
// to a new location, offset `pos` bytes from the origin. The origin
|
||||||
|
// is dependent on the `mode` and can be:
|
||||||
|
// .start -> the origin is the start of the file
|
||||||
|
// .current -> the current position/cursor in the file
|
||||||
|
// .end -> the end of the file
|
||||||
|
// If the file is not seek-able, or an error occures, the error will
|
||||||
|
// be returned to the caller.
|
||||||
|
// A successful call to the fseek() function clears the end-of-file
|
||||||
|
// indicator for the file.
|
||||||
|
pub fn (mut f File) seek(pos i64, mode SeekMode) ? {
|
||||||
|
if !f.is_opened {
|
||||||
|
return error_file_not_opened()
|
||||||
|
}
|
||||||
|
whence := int(mode)
|
||||||
|
mut res := 0
|
||||||
|
$if x64 {
|
||||||
|
$if windows {
|
||||||
|
res = C._fseeki64(f.cfile, pos, whence)
|
||||||
|
} $else {
|
||||||
|
res = C.fseeko(f.cfile, pos, whence)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$if x32 {
|
||||||
|
res = C.fseek(f.cfile, pos, whence)
|
||||||
|
}
|
||||||
|
if res == -1 {
|
||||||
|
return error(posix_get_error_msg(C.errno))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell will return the current offset of the file cursor measured from
|
||||||
|
// the start of the file, in bytes. It is complementary to seek, i.e.
|
||||||
|
// you can use the return value as the `pos` parameter to .seek( pos, .start ),
|
||||||
|
// so that your next read will happen from the same place.
|
||||||
|
pub fn (f &File) tell() ?i64 {
|
||||||
|
if !f.is_opened {
|
||||||
|
return error_file_not_opened()
|
||||||
|
}
|
||||||
|
mut pos := i64(0)
|
||||||
|
$if windows && x64 {
|
||||||
|
pos = C._ftelli64(f.cfile)
|
||||||
|
} $else {
|
||||||
|
pos = C.ftell(f.cfile)
|
||||||
|
}
|
||||||
|
if pos == -1 {
|
||||||
|
return error(posix_get_error_msg(C.errno))
|
||||||
|
}
|
||||||
|
return pos
|
||||||
|
}
|
||||||
|
|
|
@ -331,3 +331,31 @@ fn test_read_raw_at_negative_pos() ? {
|
||||||
f.read_raw_at<Point>(-234) or { assert err.msg == 'Invalid argument' }
|
f.read_raw_at<Point>(-234) or { assert err.msg == 'Invalid argument' }
|
||||||
f.close()
|
f.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_seek() ? {
|
||||||
|
mut f := os.open_file(tfile, 'w') ?
|
||||||
|
f.write_raw(another_point) ?
|
||||||
|
f.write_raw(another_byte) ?
|
||||||
|
f.write_raw(another_color) ?
|
||||||
|
f.write_raw(another_permission) ?
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
// println('> ${sizeof(Point)} ${sizeof(byte)} ${sizeof(Color)} ${sizeof(Permissions)}')
|
||||||
|
f = os.open_file(tfile, 'r') ?
|
||||||
|
defer {
|
||||||
|
f.close()
|
||||||
|
}
|
||||||
|
f.seek(i64(sizeof(Point)), .start) ?
|
||||||
|
assert f.tell() ? == sizeof(Point)
|
||||||
|
b := f.read_raw<byte>() ?
|
||||||
|
|
||||||
|
f.seek(i64(sizeof(Color)), .current) ?
|
||||||
|
x := f.read_raw<Permissions>() ?
|
||||||
|
|
||||||
|
f.seek(-i64(sizeof(Permissions) + sizeof(Color)), .end) ?
|
||||||
|
assert f.tell() ? == sizeof(Point) + sizeof(byte)
|
||||||
|
cc := f.read_raw<Color>() ?
|
||||||
|
assert b == another_byte
|
||||||
|
assert x == another_permission
|
||||||
|
assert cc == another_color
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ fn C.readlink(pathname &char, buf &char, bufsiz size_t) int
|
||||||
|
|
||||||
fn C.getline(voidptr, voidptr, voidptr) int
|
fn C.getline(voidptr, voidptr, voidptr) int
|
||||||
|
|
||||||
fn C.ftell(fp voidptr) int
|
fn C.ftell(fp voidptr) i64
|
||||||
|
|
||||||
fn C.sigaction(int, voidptr, int) int
|
fn C.sigaction(int, voidptr, int) int
|
||||||
|
|
||||||
|
@ -83,12 +83,12 @@ pub fn read_bytes(path string) ?[]byte {
|
||||||
return error('ftell failed')
|
return error('ftell failed')
|
||||||
}
|
}
|
||||||
C.rewind(fp)
|
C.rewind(fp)
|
||||||
mut res := []byte{len: fsize}
|
mut res := []byte{len: int(fsize)}
|
||||||
nr_read_elements := int(C.fread(res.data, fsize, 1, fp))
|
nr_read_elements := int(C.fread(res.data, fsize, 1, fp))
|
||||||
if nr_read_elements == 0 && fsize > 0 {
|
if nr_read_elements == 0 && fsize > 0 {
|
||||||
return error('fread failed')
|
return error('fread failed')
|
||||||
}
|
}
|
||||||
res.trim(nr_read_elements * fsize)
|
res.trim(nr_read_elements * int(fsize))
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ pub fn read_file(path string) ?string {
|
||||||
// C.fseek(fp, 0, SEEK_SET) // same as `C.rewind(fp)` below
|
// C.fseek(fp, 0, SEEK_SET) // same as `C.rewind(fp)` below
|
||||||
C.rewind(fp)
|
C.rewind(fp)
|
||||||
unsafe {
|
unsafe {
|
||||||
mut str := malloc_noscan(fsize + 1)
|
mut str := malloc_noscan(int(fsize) + 1)
|
||||||
nelements := int(C.fread(str, 1, fsize, fp))
|
nelements := int(C.fread(str, 1, fsize, fp))
|
||||||
is_eof := int(C.feof(fp))
|
is_eof := int(C.feof(fp))
|
||||||
is_error := int(C.ferror(fp))
|
is_error := int(C.ferror(fp))
|
||||||
|
@ -586,7 +586,7 @@ pub fn read_file_array<T>(path string) []T {
|
||||||
C.rewind(fp)
|
C.rewind(fp)
|
||||||
// read the actual data from the file
|
// read the actual data from the file
|
||||||
len := fsize / tsize
|
len := fsize / tsize
|
||||||
buf := unsafe { malloc_noscan(fsize) }
|
buf := unsafe { malloc_noscan(int(fsize)) }
|
||||||
nread := C.fread(buf, tsize, len, fp)
|
nread := C.fread(buf, tsize, len, fp)
|
||||||
C.fclose(fp)
|
C.fclose(fp)
|
||||||
return unsafe {
|
return unsafe {
|
||||||
|
@ -594,7 +594,7 @@ pub fn read_file_array<T>(path string) []T {
|
||||||
element_size: tsize
|
element_size: tsize
|
||||||
data: buf
|
data: buf
|
||||||
len: int(nread)
|
len: int(nread)
|
||||||
cap: len
|
cap: int(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,10 +304,7 @@ pub fn is_dir(path string) bool {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
pub fn (mut f File) fseek(pos, mode int) {
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// mkdir creates a new directory with the specified path.
|
// mkdir creates a new directory with the specified path.
|
||||||
pub fn mkdir(path string) ?bool {
|
pub fn mkdir(path string) ?bool {
|
||||||
if path == '.' {
|
if path == '.' {
|
||||||
|
|
Loading…
Reference in New Issue