mirror of
https://github.com/vlang/v.git
synced 2025-09-08 23:07:19 -04:00
149 lines
4.5 KiB
V
149 lines
4.5 KiB
V
module os
|
|
|
|
// write_le writes an unsigned number value to the file.
|
|
// It assumes that the value should be stored in a *little endian order*.
|
|
// If the machine is a big endian one, it will first convert the big endian value to a little endian one.
|
|
// It is safe to use as a cross platform way to write data, for which you have to use a predefined order (defined in a file format spec).
|
|
pub fn (mut f File) write_le[T](data T) ! {
|
|
mut serialized := data
|
|
$if big_endian {
|
|
serialized = swap_bytes(serialized)
|
|
}
|
|
C.errno = 0 // needed for tcc
|
|
check_fwrite(C.fwrite(voidptr(&serialized), sizeof(T), 1, f.cfile))!
|
|
}
|
|
|
|
// write_be writes an unsigned number value to the file.
|
|
// It assumes that the value should be stored in a *big endian order*.
|
|
// If the machine is a little endian one, it will first convert the little endian value to a big endian one.
|
|
// It is safe to use as a cross platform way to write data, for which you have to use a predefined order (defined in a file format spec).
|
|
pub fn (mut f File) write_be[T](data T) ! {
|
|
mut serialized := data
|
|
$if little_endian {
|
|
serialized = swap_bytes(serialized)
|
|
}
|
|
C.errno = 0 // needed for tcc
|
|
check_fwrite(C.fwrite(voidptr(&serialized), sizeof(T), 1, f.cfile))!
|
|
}
|
|
|
|
// read_le reads an unsigned number value from the file.
|
|
// It assumes that the value was stored in a *little endian order*.
|
|
// If the machine is a big endian one, it will convert the value to a big endian one.
|
|
// It is intended to use as a cross platform way to read data, for which the order is known (from the file format spec).
|
|
pub fn (mut f File) read_le[T]() !T {
|
|
mut serialized := T(0)
|
|
C.errno = 0 // needed for tcc
|
|
check_fread(C.fread(voidptr(&serialized), sizeof(T), 1, f.cfile))!
|
|
$if big_endian {
|
|
return swap_bytes(serialized)
|
|
}
|
|
return serialized
|
|
}
|
|
|
|
// read_be reads an unsigned number value from the file.
|
|
// It assumes that the value was stored in a *big endian order*.
|
|
// If the machine is a little endian one, it will convert the value to a little endian one.
|
|
// It is intended to use as a cross platform way to read data, for which the order is known (from the file format spec).
|
|
pub fn (mut f File) read_be[T]() !T {
|
|
mut serialized := T(0)
|
|
C.errno = 0 // needed for tcc
|
|
check_fread(C.fread(voidptr(&serialized), sizeof(T), 1, f.cfile))!
|
|
$if little_endian {
|
|
return swap_bytes(serialized)
|
|
}
|
|
return serialized
|
|
}
|
|
|
|
// write_u8 writes a single byte value to the file `f`.
|
|
// Note: if possible, use some of the other APIs, that write larger chunks of data, before using write_u8/1.
|
|
pub fn (mut f File) write_u8(b u8) ! {
|
|
C.errno = 0 // needed for tcc
|
|
check_fwrite(C.fwrite(voidptr(&b), 1, 1, f.cfile))!
|
|
}
|
|
|
|
// read_u8 reads a single byte value from the file `f`.
|
|
// Note: if possible, use some of the other APIs, that read larger chunks of data, before using read_u8/1.
|
|
pub fn (mut f File) read_u8() !u8 {
|
|
mut res := u8(0)
|
|
C.errno = 0 // needed for tcc
|
|
check_fread(C.fread(voidptr(&res), 1, 1, f.cfile))!
|
|
return res
|
|
}
|
|
|
|
// private helpers
|
|
|
|
@[inline]
|
|
fn swap_bytes_u16(x u16) u16 {
|
|
// vfmt off
|
|
return ((x >> 8) & 0x00FF) |
|
|
((x << 8) & 0xFF00)
|
|
// vfmt on
|
|
}
|
|
|
|
@[inline]
|
|
fn swap_bytes_u32(x u32) u32 {
|
|
// vfmt off
|
|
return ((x >> 24) & 0x0000_00FF) |
|
|
((x >> 8) & 0x0000_FF00) |
|
|
((x << 8) & 0x00FF_0000) |
|
|
((x << 24) & 0xFF00_0000)
|
|
// vfmt on
|
|
}
|
|
|
|
@[inline]
|
|
fn swap_bytes_u64(x u64) u64 {
|
|
// vfmt off
|
|
return ((x >> 56) & 0x00000000_000000FF) |
|
|
((x >> 40) & 0x00000000_0000FF00) |
|
|
((x >> 24) & 0x00000000_00FF0000) |
|
|
((x >> 8) & 0x00000000_FF000000) |
|
|
((x << 8) & 0x000000FF_00000000) |
|
|
((x << 24) & 0x0000FF00_00000000) |
|
|
((x << 40) & 0x00FF0000_00000000) |
|
|
((x << 56) & 0xFF000000_00000000)
|
|
// vfmt on
|
|
}
|
|
|
|
fn swap_bytes[T](input T) T {
|
|
$if T is u8 {
|
|
return input
|
|
} $else $if T is i8 {
|
|
return input
|
|
} $else $if T is byte {
|
|
return input
|
|
} $else $if T is u16 {
|
|
return swap_bytes_u16(input)
|
|
} $else $if T is u32 {
|
|
return swap_bytes_u32(input)
|
|
} $else $if T is u64 {
|
|
return swap_bytes_u64(input)
|
|
} $else $if T is i16 {
|
|
return i16(swap_bytes_u16(u16(input)))
|
|
} $else $if T is i32 {
|
|
return i32(swap_bytes_u32(u32(input)))
|
|
} $else $if T is int {
|
|
return i32(swap_bytes_u32(u32(input)))
|
|
} $else $if T is i64 {
|
|
return i64(swap_bytes_u64(u64(input)))
|
|
} $else {
|
|
panic('type is not supported: ' + typeof[T]().str())
|
|
}
|
|
}
|
|
|
|
fn check_cf(x usize, label string) ! {
|
|
if C.errno != 0 {
|
|
return error(posix_get_error_msg(C.errno))
|
|
}
|
|
if x == 0 {
|
|
return error(label)
|
|
}
|
|
}
|
|
|
|
fn check_fwrite(x usize) ! {
|
|
check_cf(x, 'fwrite')!
|
|
}
|
|
|
|
fn check_fread(x usize) ! {
|
|
check_cf(x, 'fread')!
|
|
}
|