use libc::{fopen, fread, fclose, fseek, ftell};
use libc::{SEEK_SET, SEEK_CUR, SEEK_END};
use libc::FILE;
use libc::stat;
use std::mem::zeroed;
use libc::fstat;
use libc::fileno;
use libc::{c_void, c_char};
use std::ffi::CString;
pub fn get_ffi(file: &FmodFile) -> *mut FILE {
file.fd
}
pub fn from_ffi(fd: *mut FILE) -> FmodFile {
FmodFile {
fd: fd
}
}
#[derive(Debug, PartialOrd, PartialEq)]
pub enum SeekStyle {
SeekSet,
SeekEnd,
SeekCur
}
pub struct FmodFile {
fd: *mut FILE
}
impl FmodFile {
pub fn open(file_name: &str) -> Option<FmodFile> {
let tmp_file_name = CString::new(file_name).unwrap();
unsafe {
let tmp = fopen(tmp_file_name.as_ptr() as *const c_char, "rb".as_ptr() as *const c_char);
if tmp.is_null() {
None
} else {
Some(FmodFile{fd: tmp})
}
}
}
pub fn read(&self, buffer: &mut [u8]) -> usize {
unsafe {
if self.fd.is_null() {
0usize
} else {
fread(buffer.as_mut_ptr() as *mut c_void, buffer.len() as usize, 1usize, self.fd) as usize
}
}
}
pub fn seek(&self, pos: i64, style: self::SeekStyle) -> usize {
unsafe {
if self.fd.is_null() {
0usize
} else {
fseek(self.fd, pos, match style {
self::SeekStyle::SeekSet => SEEK_SET,
self::SeekStyle::SeekEnd => SEEK_END,
self::SeekStyle::SeekCur => SEEK_CUR
}) as usize
}
}
}
pub fn get_file_size(&self) -> i64 {
unsafe {
if self.fd.is_null() {
0i64
} else {
let mut tmp : stat = zeroed::<stat>();
let id = fileno(self.fd);
match fstat(id, &mut tmp) {
0 => tmp.st_size,
_ => 0i64
}
}
}
}
pub fn tell(&self) -> i64 {
unsafe {
if self.fd.is_null() {
0i64
} else {
ftell(self.fd)
}
}
}
pub fn close(&mut self) {
unsafe {
if !self.fd.is_null() {
fclose(self.fd);
self.fd = ::std::ptr::null_mut();
}
}
}
}