///|
#external
priv type CFile
///|
#borrow(ptr)
extern "c" fn is_null(ptr : CFile) -> Int = "moonbit_is_null"
///|
#borrow(path, mode)
extern "c" fn fopen_ffi(path : Bytes, mode : Bytes) -> CFile = "moonbit_fopen_ffi"
///|
#borrow(ptr, stream)
extern "c" fn fread_ffi(
ptr : Bytes,
size : Int,
count : Int,
stream : CFile,
) -> Int = "moonbit_fread_ffi"
///|
#borrow(ptr, stream)
extern "c" fn fwrite_ffi(
ptr : Bytes,
size : Int,
count : Int,
stream : CFile,
) -> Int = "moonbit_fwrite_ffi"
///|
#borrow(stream)
extern "c" fn fseek_ffi(stream : CFile, offset : Int, whence : Int) -> Int = "moonbit_fseek_ffi"
///|
#borrow(stream)
extern "c" fn ftell_ffi(stream : CFile) -> Int = "moonbit_ftell_ffi"
///|
#borrow(stream)
extern "c" fn fclose_ffi(stream : CFile) -> Int = "moonbit_fclose_ffi"
///|
extern "c" fn make_bytes_raw(length : Int) -> Bytes = "moonbit_make_bytes_raw"
///|
fn c_string(value : String) -> Bytes {
let encoded = @utf8.encode(value)
let result = FixedArray::make(encoded.length() + 1, b'\x00')
for i in 0.. Bytes? {
let file = fopen_ffi(c_string(path), c_string("rb"))
if is_null(file) != 0 {
return None
}
ignore(fseek_ffi(file, 0, 2))
let length = ftell_ffi(file)
ignore(fseek_ffi(file, 0, 0))
if length < 0 {
ignore(fclose_ffi(file))
return None
}
let buffer = make_bytes_raw(length)
let count = fread_ffi(buffer, 1, length, file)
ignore(fclose_ffi(file))
Some(buffer.view(start=0, end=count).to_owned())
}
///|
fn read_file(path : String) -> String? {
read_binary(path).map(content => @utf8.decode_lossy(content))
}
///|
fn write_binary(path : String, content : Bytes) -> Bool {
let file = fopen_ffi(c_string(path), c_string("wb"))
if is_null(file) != 0 {
return false
}
let count = fwrite_ffi(content, 1, content.length(), file)
let closed = fclose_ffi(file)
count == content.length() && closed == 0
}