Add RWops struct implementation

This commit is contained in:
Andelf
2014-04-07 22:48:35 +08:00
parent b7727bd654
commit f2fea4c822
2 changed files with 136 additions and 11 deletions
+131 -6
View File
@@ -1,22 +1,147 @@
use std::io;
use std::io::IoResult;
use get_error;
use libc::{c_void, c_int};
#[allow(non_camel_case_types)]
pub mod ll {
use libc::{c_uchar, uint8_t, uint32_t, c_schar};
use libc::{c_uchar, uint32_t, c_schar, FILE, c_void};
use libc::{c_int, int64_t, size_t};
struct SDL_RWops_Anon {
data: [c_uchar, ..24],
}
pub type SDL_bool = c_int;
pub static RW_SEEK_SET: c_int = 0;
pub static RW_SEEK_CUR: c_int = 1;
pub static RW_SEEK_END: c_int = 2;
pub struct SDL_RWops {
pub size: *uint8_t,
pub seek: *uint8_t,
pub read: *uint8_t,
pub write: *uint8_t,
pub close: *uint8_t,
pub size: extern "C" fn(context: *SDL_RWops) -> int64_t,
pub seek: extern "C" fn(context: *SDL_RWops, offset: int64_t, whence: c_int) -> int64_t,
pub read: extern "C" fn(context: *SDL_RWops, ptr: *c_void,
size: size_t, maxnum: size_t) -> size_t,
pub write: extern "C" fn(context: *SDL_RWops, ptr: *c_void,
size: size_t, maxnum: size_t) -> size_t,
pub close: extern "C" fn(context: *SDL_RWops) -> c_int,
pub _type: uint32_t,
hidden: SDL_RWops_Anon
}
extern "C" {
pub fn SDL_RWFromFile(file: *c_schar, mode: *c_schar) -> *SDL_RWops;
pub fn SDL_RWFromFP(fp: *FILE, autoclose: SDL_bool) -> *SDL_RWops;
pub fn SDL_RWFromMem(mem: *c_void, size: c_int) -> *SDL_RWops;
pub fn SDL_RWFromConstMem(mem: *c_void, size: c_int) -> *SDL_RWops;
pub fn SDL_AllocRW() -> *SDL_RWops;
pub fn SDL_FreeRW(area: *SDL_RWops);
}
}
#[deriving(Eq)] #[allow(raw_pointer_deriving)]
pub struct RWops {
pub raw: *ll::SDL_RWops,
pub owned: bool
}
/// A structure that provides an abstract interface to stream I/O.
impl RWops {
pub fn from_file(path: &Path, mode: &str) -> Result<~RWops, ~str> {
let raw = unsafe {
ll::SDL_RWFromFile(path.to_c_str().unwrap(), mode.to_c_str().unwrap())
};
if raw.is_null() { Err(get_error()) }
else { Ok(~RWops{raw: raw, owned: true}) }
}
pub fn from_bytes(buf: &[u8]) -> Result<~RWops, ~str> {
let raw = unsafe {
ll::SDL_RWFromConstMem(buf.as_ptr() as *c_void, buf.len() as c_int)
};
if raw.is_null() { Err(get_error()) }
else { Ok(~RWops{raw: raw, owned: true}) }
}
}
impl Drop for RWops {
fn drop(&mut self) {
// TODO: handle close error
unsafe {
ll::SDL_FreeRW(self.raw);
}
}
}
impl Reader for RWops {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
let out_len = buf.len() as u64;
// FIXME: it's better to use as_mut_ptr().
// number of objects read, or 0 at error or end of file.
let ret = unsafe {
((*self.raw).read)(self.raw, buf.as_ptr() as *c_void, 1, out_len)
};
if ret == 0 {
Err(io::standard_error(io::EndOfFile))
} else {
Ok(ret as uint)
}
}
}
impl Writer for RWops {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
let in_len = buf.len() as u64;
let ret = unsafe {
((*self.raw).write)(self.raw, buf.as_ptr() as *c_void, 1, in_len)
};
if ret == 0 {
Err(io::standard_error(io::EndOfFile))
} else if ret != in_len {
// FIXME: what error should we return here?
Err(io::standard_error(io::EndOfFile))
} else {
Ok(())
}
}
}
impl Seek for RWops {
fn tell(&self) -> IoResult<u64> {
let ret = unsafe {
((*self.raw).seek)(self.raw, 0, ll::RW_SEEK_CUR)
};
if ret == -1 {
Err(io::IoError::last_error())
} else {
Ok(ret as u64)
}
}
fn seek(&mut self, pos: i64, style: io::SeekStyle) -> IoResult<()> {
// whence code is different from SeekStyle
let whence = match style {
io::SeekSet => ll::RW_SEEK_SET,
io::SeekEnd => ll::RW_SEEK_END,
io::SeekCur => ll::RW_SEEK_CUR
};
let ret = unsafe {
((*self.raw).seek)(self.raw, pos, whence)
};
if ret == -1 {
Err(io::IoError::last_error())
} else {
Ok(())
}
}
}
impl Container for RWops {
fn len(&self) -> uint {
unsafe {
((*self.raw).size)(self.raw) as uint
}
}
}
+5 -5
View File
@@ -166,7 +166,7 @@ impl Surface {
pub fn from_bmp(path: &Path) -> Result<~Surface, ~str> {
let raw = unsafe {
ll::SDL_LoadBMP_RW(rwops::ll::SDL_RWFromFile(path.to_c_str().unwrap(), "rb".to_c_str().unwrap()), 1)
ll::SDL_LoadBMP_RW(rwops::RWops::from_file(path, "rb").unwrap().raw, 0)
};
if raw.is_null() { Err(get_error()) }
@@ -174,9 +174,9 @@ impl Surface {
}
pub fn save_bmp(&self, path: &Path) -> bool {
unsafe {
ll::SDL_SaveBMP_RW(self.raw, rwops::ll::SDL_RWFromFile(path.to_c_str().unwrap(), "wb".to_c_str().unwrap()), 1) == 0
}
unsafe {
ll::SDL_SaveBMP_RW(self.raw, rwops::RWops::from_file(path, "rb").unwrap().raw, 0) == 0
}
}
pub fn set_palette(&self, palette: &pixels::Palette) -> bool {
@@ -221,7 +221,7 @@ impl Surface {
Err(get_error())
}
}
pub fn set_color_mod(&self, color: pixels::Color) -> bool {
let (r, g, b) = match color {
pixels::RGB(r, g, b) => (r, g, b),