Fix up CString interop

Working with `*const c_char` now works as follows:

* Call `c_str_to_bytes(*const char)` helper function to get a slice
  of data w/o the null terminator. (`&'a [u8]`)

* Use that slice of data to construct a standard `String` using the
  checked, unchecked, or lossy UTF-8 conversion methods.

---

CString now only exists to go the other way (from String -> CString).
It simply adds the invariants that the string contains no interior NULL
bytes and has a null-terminator.
This commit is contained in:
Robert Straw
2015-01-07 14:35:35 -06:00
parent a9302202cb
commit bce52276af
11 changed files with 83 additions and 90 deletions
+11 -11
View File
@@ -1,7 +1,7 @@
//! Audio Functions
use std::ptr;
use std::mem;
use std::ffi::CString;
use std::ffi::{c_str_to_bytes, CString};
use std::borrow::ToOwned;
use std::num::FromPrimitive;
use libc;
@@ -50,8 +50,8 @@ pub fn get_num_audio_drivers() -> int {
pub fn get_audio_driver(index: int) -> String {
unsafe {
let buf = ll::SDL_GetAudioDriver(index as c_int);
CString::new(buf, false).as_str().unwrap().to_owned()
let driver = ll::SDL_GetAudioDriver(index as c_int);
String::from_utf8_lossy(c_str_to_bytes(&driver)).to_string()
}
}
@@ -61,15 +61,15 @@ pub fn get_num_audio_devices(iscapture: int) -> int {
pub fn get_audio_device_name(index: int, iscapture: int) -> String {
unsafe {
let buf = ll::SDL_GetAudioDeviceName(index as c_int, iscapture as c_int);
CString::new(buf, false).as_str().unwrap().to_owned()
let dev_name = ll::SDL_GetAudioDeviceName(index as c_int, iscapture as c_int);
String::from_utf8_lossy(c_str_to_bytes(&dev_name)).to_string()
}
}
pub fn audio_init(name: &str) -> SdlResult<()> {
let ret = name.with_c_str(|buf| {
unsafe { ll::SDL_AudioInit(buf) }
});
let buf = CString::from_slice(name.as_bytes()).as_ptr();
let ret = unsafe { ll::SDL_AudioInit(buf) };
if ret == 0 {
Ok(())
} else {
@@ -83,8 +83,8 @@ pub fn audio_quit() {
pub fn get_current_audio_driver() -> String {
unsafe {
let buf = ll::SDL_GetCurrentAudioDriver();
CString::new(buf, false).as_str().unwrap().to_owned()
let driver = ll::SDL_GetCurrentAudioDriver();
String::from_utf8_lossy(c_str_to_bytes(&driver)).to_string()
}
}
@@ -245,7 +245,7 @@ impl<T: AudioFormatNum<T>, CB: AudioCallback<T>> AudioSpecDesired<T, CB> {
unsafe {
let device_cstr: Option<CString> = match device {
None => None,
Some(d) => Some(d.to_c_str())
Some(d) => Some(CString::from_slice(d.as_bytes()))
};
let device_cstr_ptr: *const c_char = match device_cstr {
None => null(),
+5 -7
View File
@@ -1,5 +1,4 @@
use std::ffi::CString;
use std::ffi::{c_str_to_bytes, CString};
use SdlResult;
use get_error;
@@ -7,9 +6,8 @@ pub use sys::clipboard as ll;
pub fn set_clipboard_text(text: &String) -> SdlResult<()> {
unsafe {
let result = text.with_c_str(|buff| {
ll::SDL_SetClipboardText(buff)
});
let buff = CString::from_slice(text.as_slice().as_bytes());
let result = ll::SDL_SetClipboardText(buff.as_ptr());
if result == 0 {
Err(get_error())
@@ -21,8 +19,8 @@ pub fn set_clipboard_text(text: &String) -> SdlResult<()> {
pub fn get_clipboard_text() -> SdlResult<String> {
let result = unsafe {
let cstr = ll::SDL_GetClipboardText() as *const u8;
String::from_raw_buf(cstr)
let buf = ll::SDL_GetClipboardText();
String::from_utf8_lossy(c_str_to_bytes(&buf)).to_string()
};
if result.len() == 0 {
+3 -1
View File
@@ -2,6 +2,7 @@
Event Handling
*/
use std::ffi::{c_str_to_bytes};
use std::mem;
use libc::{c_int, c_void, uint32_t};
use std::num::FromPrimitive;
@@ -592,7 +593,8 @@ impl Event {
EventType::DropFile => {
let ref event = *raw.drop();
let text = String::from_raw_buf(event.file as *const u8);
let buf = c_str_to_bytes(&event.file);
let text = String::from_utf8_lossy(buf).to_string();
ll::SDL_free(event.file as *const c_void);
Event::DropFile(event.timestamp as uint, text)
+7 -9
View File
@@ -1,4 +1,4 @@
use std::ffi::CString;
use std::ffi::{c_str_to_bytes, CString};
use SdlResult;
use get_error;
@@ -6,8 +6,8 @@ pub use sys::filesystem as ll;
pub fn get_base_path() -> SdlResult<String> {
let result = unsafe {
let cstr = ll::SDL_GetBasePath();
String::from_raw_buf(cstr as *const u8)
let buf = ll::SDL_GetBasePath();
String::from_utf8_lossy(c_str_to_bytes(&buf)).to_string()
};
if result.len() == 0 {
@@ -19,12 +19,10 @@ pub fn get_base_path() -> SdlResult<String> {
pub fn get_pref_path(org: &str, app: &str) -> SdlResult<String> {
let result = unsafe {
let cstr =
org.with_c_str(|org_cstr| {
app.with_c_str(|app_cstr| {
ll::SDL_GetPrefPath(org_cstr, app_cstr)
})});
String::from_raw_buf(cstr as *const u8)
let org_cstr = CString::from_slice(org.as_bytes()).as_ptr();
let app_cstr = CString::from_slice(app.as_bytes()).as_ptr();
let buf = ll::SDL_GetPrefPath(org_cstr, app_cstr);
String::from_utf8_lossy(c_str_to_bytes(&buf)).to_string()
};
if result.len() == 0 {
+10 -12
View File
@@ -1,5 +1,5 @@
use std::collections::HashMap;
use std::ffi::CString;
use std::ffi::{c_str_to_bytes, CString};
use std::num::FromPrimitive;
use std::ptr;
@@ -80,32 +80,30 @@ pub fn get_scancode_from_key(key: KeyCode) -> ScanCode {
pub fn get_scancode_name(scancode: ScanCode) -> String {
unsafe {
let scancode_name = ll::SDL_GetScancodeName(scancode as u32);
String::from_raw_buf(scancode_name as *const u8)
String::from_utf8_lossy(c_str_to_bytes(&scancode_name)).to_string()
}
}
pub fn get_scancode_from_name(name: &str) -> ScanCode {
unsafe {
name.with_c_str(|name| {
FromPrimitive::from_int(ll::SDL_GetScancodeFromName(name) as int)
.unwrap_or(ScanCode::Unknown)
})
}
let name = CString::from_slice(name.as_bytes()).as_ptr();
FromPrimitive::from_int(ll::SDL_GetScancodeFromName(name) as int)
.unwrap_or(ScanCode::Unknown)
}
}
pub fn get_key_name(key: KeyCode) -> String {
unsafe {
let key_name = ll::SDL_GetKeyName(key as i32);
String::from_raw_buf(key_name as *const u8)
String::from_utf8_lossy(c_str_to_bytes(&key_name)).to_string()
}
}
pub fn get_key_from_name(name: &str) -> KeyCode {
unsafe {
name.with_c_str(|name| {
FromPrimitive::from_int(ll::SDL_GetKeyFromName(name) as int)
.unwrap_or(KeyCode::Unknown)
})
let name = CString::from_slice(name.as_bytes()).as_ptr();
FromPrimitive::from_int(ll::SDL_GetKeyFromName(name) as int)
.unwrap_or(KeyCode::Unknown)
}
}
+6 -5
View File
@@ -17,11 +17,12 @@ bitflags! {
pub fn show_simple_message_box(flags: MessageBoxFlag, title: &str, message: &str, window: Option<&Window>) -> SdlResult<()> {
let result = unsafe {
title.with_c_str(|title_cstr| {
message.with_c_str(|message_cstr| {
ll::SDL_ShowSimpleMessageBox(flags.bits(), title_cstr, message_cstr, window.map_or(ptr::null(), |win| win.raw()))
})
})
let title_cstr = CString::from_slice(title.as_bytes()).as_ptr();
let message_cstr = CString::from_slice(message.as_bytes()).as_ptr();
ll::SDL_ShowSimpleMessageBox(flags.bits(),
title_cstr,
message_cstr,
window.map_or(ptr::null(), |win| win.raw()))
} == 0;
if result {
+3 -1
View File
@@ -8,8 +8,10 @@ use SdlResult;
use std::ptr;
use libc;
use libc::{c_int, uint32_t, c_float, c_double, c_void, size_t};
use ::c_vec::CVec;
use rect::Point;
use rect::Rect;
use std::ffi::c_str_to_bytes;
use std::num::FromPrimitive;
use std::vec::Vec;
use std::borrow::ToOwned;
@@ -72,7 +74,7 @@ impl RendererInfo {
}).collect();
RendererInfo {
name: String::from_raw_buf(info.name as *const _),
name: String::from_utf8_lossy(c_str_to_bytes(&info.name)).to_string(),
flags: actual_flags,
texture_formats: texture_formats,
max_texture_width: info.max_texture_width as int,
+3 -1
View File
@@ -20,7 +20,9 @@ impl_owned_accessors!(RWops, close_on_drop);
impl RWops {
pub fn from_file(path: &Path, mode: &str) -> SdlResult<RWops> {
let raw = unsafe {
ll::SDL_RWFromFile(CString::from_slice(path), CString::from_slice(mode))
let path_c = CString::from_slice(path.as_vec()).as_ptr();
let mode_c = CString::from_slice(mode.as_bytes()).as_ptr();
ll::SDL_RWFromFile(path_c, mode_c)
};
if raw.is_null() { Err(get_error()) }
else { Ok(RWops{raw: raw, close_on_drop: true}) }
+5 -7
View File
@@ -1,5 +1,4 @@
use std::borrow::ToOwned;
use std::ffi::CString;
use std::ffi::{c_str_to_bytes, CString};
use sys::sdl as ll;
@@ -57,15 +56,14 @@ pub fn was_inited(flags: InitFlag) -> InitFlag {
pub fn get_error() -> String {
unsafe {
let cstr = CString::new(ll::SDL_GetError(), false);
cstr.as_str().unwrap().to_owned()
let err = ll::SDL_GetError();
String::from_utf8_lossy(c_str_to_bytes(&err)).to_string()
}
}
pub fn set_error(err: &str) {
err.with_c_str(|buf| {
unsafe { ll::SDL_SetError(buf); }
})
let buf = CString::from_slice(err.as_bytes()).as_ptr();
unsafe { ll::SDL_SetError(buf); }
}
pub fn set_error_from_code(err: Error) {
+3 -4
View File
@@ -2,9 +2,8 @@
Querying SDL Version
*/
use std::ffi::CString;
use std::ffi::c_str_to_bytes;
use std::fmt;
use std::borrow::ToOwned;
pub use sys::version as ll;
@@ -47,8 +46,8 @@ pub fn get_version() -> Version {
/// Get the code revision of SDL that is linked against your program.
pub fn get_revision() -> String {
unsafe {
let ret = ll::SDL_GetRevision();
CString::new(ret, false).as_str().unwrap().to_owned()
let rev = ll::SDL_GetRevision();
String::from_utf8_lossy(c_str_to_bytes(&rev)).to_string()
}
}
+27 -32
View File
@@ -1,5 +1,5 @@
use libc::{c_int, c_float, uint32_t};
use std::ffi::CString;
use std::ffi::{c_str_to_bytes, CString};
use std::ptr;
use std::vec::Vec;
@@ -190,16 +190,15 @@ impl Drop for Window {
impl Window {
pub fn new(title: &str, x: WindowPos, y: WindowPos, width: int, height: int, window_flags: WindowFlags) -> SdlResult<Window> {
unsafe {
let raw = title.with_c_str(|buff| {
ll::SDL_CreateWindow(
let buff = CString::from_slice(title.as_bytes()).as_ptr();
let raw = ll::SDL_CreateWindow(
buff,
unwrap_windowpos(x),
unwrap_windowpos(y),
width as c_int,
height as c_int,
window_flags.bits()
)
});
);
if raw == ptr::null() {
Err(get_error())
@@ -272,15 +271,14 @@ impl Window {
}
pub fn set_title(&self, title: &str) {
title.with_c_str(|buff| {
unsafe { ll::SDL_SetWindowTitle(self.raw, buff) }
})
let buff = CString::from_slice(title.as_bytes()).as_ptr();
unsafe { ll::SDL_SetWindowTitle(self.raw, buff) }
}
pub fn get_title(&self) -> String {
unsafe {
let cstr = ll::SDL_GetWindowTitle(self.raw);
String::from_raw_buf(cstr as *const _)
let buf = ll::SDL_GetWindowTitle(self.raw);
String::from_utf8_lossy(c_str_to_bytes(&buf)).to_string()
}
}
@@ -467,15 +465,14 @@ pub fn get_num_video_drivers() -> SdlResult<int> {
pub fn get_video_driver(id: int) -> String {
unsafe {
let cstr = ll::SDL_GetVideoDriver(id as c_int);
String::from_raw_buf(cstr as *const _)
let buf = ll::SDL_GetVideoDriver(id as c_int);
String::from_utf8_lossy(c_str_to_bytes(&buf)).to_string()
}
}
pub fn video_init(name: &str) -> bool {
name.with_c_str(|buf| {
unsafe { ll::SDL_VideoInit(buf) == 0 }
})
let buf = CString::from_slice(name.as_bytes()).as_ptr();
unsafe { ll::SDL_VideoInit(buf) == 0 }
}
pub fn video_quit() {
@@ -484,8 +481,8 @@ pub fn video_quit() {
pub fn get_current_video_driver() -> String {
unsafe {
let cstr = ll::SDL_GetCurrentVideoDriver();
String::from_raw_buf(cstr as *const _)
let video = ll::SDL_GetCurrentVideoDriver();
String::from_utf8_lossy(c_str_to_bytes(&video)).to_string()
}
}
@@ -500,8 +497,8 @@ pub fn get_num_video_displays() -> SdlResult<int> {
pub fn get_display_name(display_index: int) -> String {
unsafe {
let cstr = ll::SDL_GetDisplayName(display_index as c_int);
String::from_raw_buf(cstr as *const _)
let display = ll::SDL_GetDisplayName(display_index as c_int);
String::from_utf8_lossy(c_str_to_bytes(&display)).to_string()
}
}
@@ -585,13 +582,13 @@ pub fn disable_screen_saver() {
pub fn gl_load_library(path: &str) -> SdlResult<()> {
unsafe {
path.with_c_str(|path| {
if ll::SDL_GL_LoadLibrary(path) == 0 {
Ok(())
} else {
Err(get_error())
}
})
let path = CString::from_slice(path.as_bytes()).as_ptr();
if ll::SDL_GL_LoadLibrary(path) == 0 {
Ok(())
} else {
Err(get_error())
}
}
}
@@ -601,16 +598,14 @@ pub fn gl_unload_library() {
pub fn gl_get_proc_address(procname: &str) -> Option<extern "system" fn()> {
unsafe {
procname.with_c_str(|procname| {
ll::SDL_GL_GetProcAddress(procname)
})
let procname = CString::from_slice(procname.as_bytes()).as_ptr();
ll::SDL_GL_GetProcAddress(procname)
}
}
pub fn gl_extension_supported(extension: &str) -> bool {
extension.with_c_str(|buff| {
unsafe { ll::SDL_GL_ExtensionSupported(buff) == 1 }
})
let buff = CString::from_slice(extension.as_bytes()).as_ptr();
unsafe { ll::SDL_GL_ExtensionSupported(buff) == 1 }
}
pub fn gl_set_attribute(attr: GLAttr, value: int) -> bool {