1use libc::{fopen, fread, fclose, fseek, ftell};
26use libc::{SEEK_SET, SEEK_CUR, SEEK_END};
27use libc::FILE;
28use libc::stat;
29use std::mem::zeroed;
30use libc::fstat;
31use libc::fileno;
32use libc::{c_void, c_char, c_long};
33use std::ffi::CString;
34
35#[doc(hidden)]
36pub fn get_ffi(file: &FmodFile) -> *mut FILE {
37 file.fd
38}
39
40#[doc(hidden)]
41pub fn from_ffi(fd: *mut FILE) -> FmodFile {
42 FmodFile {
43 fd: fd,
44 }
45}
46
47#[derive(Debug, PartialOrd, PartialEq)]
48pub enum SeekStyle {
49 SeekSet,
51 SeekEnd,
53 SeekCur,
55}
56
57pub struct FmodFile {
63 fd: *mut FILE,
64}
65
66impl FmodFile {
67 pub fn open(file_name: &str) -> Result<FmodFile, ::RStatus> {
68 let tmp_file_name = match CString::new(file_name) {
69 Ok(s) => s,
70 Err(e) => return Err(::RStatus::Other(format!("invalid file name: {}", e))),
71 };
72 unsafe {
73 let tmp = fopen(tmp_file_name.as_ptr() as *const c_char,
74 "rb".as_ptr() as *const c_char);
75
76 if tmp.is_null() {
77 Err(::RStatus::Other(format!("fopen call failed")))
78 } else {
79 Ok(FmodFile{fd: tmp})
80 }
81 }
82 }
83
84 pub fn read(&self, buffer: &mut [u8]) -> usize {
85 unsafe {
86 if self.fd.is_null() {
87 0usize
88 } else {
89 fread(buffer.as_mut_ptr() as *mut c_void, buffer.len() as usize, 1usize,
90 self.fd) as usize
91 }
92 }
93 }
94
95 pub fn seek(&self, pos: i64, style: self::SeekStyle) -> usize {
96 unsafe {
97 if self.fd.is_null() {
98 0usize
99 } else {
100 fseek(self.fd, pos as c_long, match style {
101 self::SeekStyle::SeekSet => SEEK_SET,
102 self::SeekStyle::SeekEnd => SEEK_END,
103 self::SeekStyle::SeekCur => SEEK_CUR
104 }) as usize
105 }
106 }
107 }
108
109 pub fn get_file_size(&self) -> i64 {
110 unsafe {
111 if self.fd.is_null() {
112 0i64
113 } else {
114 let mut tmp : stat = zeroed::<stat>();
115 let id = fileno(self.fd);
116 match fstat(id, &mut tmp) {
117 0 => tmp.st_size,
118 _ => 0i64
119 }
120 }
121 }
122 }
123
124 pub fn tell(&self) -> i64 {
125 unsafe {
126 if self.fd.is_null() {
127 0i64
128 } else {
129 ftell(self.fd) as i64
130 }
131 }
132 }
133
134 pub fn close(&mut self) {
135 unsafe {
136 if !self.fd.is_null() {
137 fclose(self.fd);
138 self.fd = ::std::ptr::null_mut();
139 }
140 }
141 }
142}