From 75a0062d88fdfe3dd08b19613b5d5c8b0a434437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Tue, 22 Jul 2014 17:55:12 +0200 Subject: [PATCH] Add `string::raw::from_buf` --- src/libcollections/str.rs | 18 ++--------- src/libcollections/string.rs | 48 ++++++++++++++++++++++-------- src/librustc/middle/trans/type_.rs | 7 +++-- src/librustuv/lib.rs | 6 ++-- src/libstd/os.rs | 3 +- 5 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index db859bbf5bf..f013557f9a5 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -555,9 +555,6 @@ impl<'a> fmt::Show for MaybeOwned<'a> { /// Unsafe operations pub mod raw { - use core::mem; - use core::raw::Slice; - use core::ptr::RawPtr; use string; use string::String; use vec::Vec; @@ -573,19 +570,10 @@ pub mod raw { string::raw::from_buf_len(buf, len) } - /// Deprecated. Use `CString::as_str().unwrap().to_string()` - #[deprecated = "Use CString::as_str().unwrap().to_string()"] + /// Deprecated. Use `string::raw::from_buf` + #[deprecated = "Use string::raw::from_buf"] pub unsafe fn from_c_str(c_string: *const i8) -> String { - let mut buf = String::new(); - let mut len = 0; - while *c_string.offset(len) != 0 { - len += 1; - } - buf.push_bytes(mem::transmute(Slice { - data: c_string, - len: len as uint, - })); - buf + string::raw::from_buf(c_string as *const u8) } /// Deprecated. Replaced by `string::raw::from_utf8` diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index aeb323a9caf..282193d08aa 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -61,7 +61,7 @@ impl String { #[inline] #[deprecated = "Replaced by string::raw::from_parts"] pub unsafe fn from_raw_parts(length: uint, capacity: uint, ptr: *mut u8) -> String { - raw::from_parts(length, capacity, ptr) + raw::from_parts(ptr, length, capacity) } #[allow(missing_doc)] @@ -571,6 +571,7 @@ impl Add for String { pub mod raw { use core::mem; + use core::ptr::RawPtr; use core::raw::Slice; use super::String; @@ -582,21 +583,13 @@ pub mod raw { /// * We call `Vec::from_raw_parts` to get a `Vec` /// * We assume that the `Vec` contains valid UTF-8 #[inline] - pub unsafe fn from_parts(length: uint, capacity: uint, ptr: *mut u8) -> String { + pub unsafe fn from_parts(buf: *mut u8, length: uint, capacity: uint) -> String { String { - vec: Vec::from_raw_parts(length, capacity, ptr), + vec: Vec::from_raw_parts(length, capacity, buf), } } - /// Converts a vector of bytes to a new `String` without checking if - /// it contains valid UTF-8. This is unsafe because it assumes that - /// the utf-8-ness of the vector has already been validated. - #[inline] - pub unsafe fn from_utf8(bytes: Vec) -> String { - String { vec: bytes } - } - - /// Create a Rust string from a *u8 buffer of the given length + /// Create `String` from a *u8 buffer of the given length /// /// This function is unsafe because of two reasons: /// * A raw pointer is dereferenced and transmuted to `&[u8]` @@ -609,6 +602,27 @@ pub mod raw { }); self::from_utf8(slice.to_vec()) } + + /// Create a `String` from a null-terminated *u8 buffer + /// + /// This function is unsafe because we dereference memory until we find the NUL character, + /// which is not guaranteed to be present. Additionaly, the slice is not checked to see + /// whether it contains valid UTF-8 + pub unsafe fn from_buf(buf: *const u8) -> String { + let mut len = 0; + while *buf.offset(len) != 0 { + len += 1; + } + self::from_buf_len(buf, len as uint) + } + + /// Converts a vector of bytes to a new `String` without checking if + /// it contains valid UTF-8. This is unsafe because it assumes that + /// the utf-8-ness of the vector has already been validated. + #[inline] + pub unsafe fn from_utf8(bytes: Vec) -> String { + String { vec: bytes } + } } #[cfg(test)] @@ -776,6 +790,16 @@ mod tests { } } + #[test] + fn test_from_buf() { + unsafe { + let a = vec![65, 65, 65, 65, 65, 65, 65, 0]; + let b = a.as_ptr(); + let c = super::raw::from_buf(b); + assert_eq!(c, String::from_str("AAAAAAA")); + } + } + #[test] fn test_push_bytes() { let mut s = String::from_str("ABC"); diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs index 3833d4cd0c8..e9d92e45f62 100644 --- a/src/librustc/middle/trans/type_.rs +++ b/src/librustc/middle/trans/type_.rs @@ -19,8 +19,9 @@ use middle::trans::context::CrateContext; use syntax::ast; use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel}; -use std::c_str::{CString, ToCStr}; +use std::c_str::ToCStr; use std::mem; +use std::string; use std::cell::RefCell; use std::collections::HashMap; @@ -333,7 +334,7 @@ impl TypeNames { pub fn type_to_string(&self, ty: Type) -> String { unsafe { let s = llvm::LLVMTypeToString(ty.to_ref()); - let ret = CString::new(s, false).as_str().unwrap().to_string(); + let ret = string::raw::from_buf(s as *const u8); free(s as *mut c_void); ret } @@ -347,7 +348,7 @@ impl TypeNames { pub fn val_to_string(&self, val: ValueRef) -> String { unsafe { let s = llvm::LLVMValueToString(val); - let ret = CString::new(s, false).as_str().unwrap().to_string(); + let ret = string::raw::from_buf(s as *const u8); free(s as *mut c_void); ret } diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs index dc43a68e64d..4d23397cd38 100644 --- a/src/librustuv/lib.rs +++ b/src/librustuv/lib.rs @@ -55,10 +55,10 @@ extern crate libc; extern crate alloc; use libc::{c_int, c_void}; -use std::c_str::CString; use std::fmt; use std::mem; use std::ptr; +use std::string; use std::rt::local::Local; use std::rt::rtio; use std::rt::rtio::{IoResult, IoError}; @@ -363,7 +363,7 @@ impl UvError { let inner = match self { &UvError(a) => a }; let name_str = uvll::uv_err_name(inner); assert!(name_str.is_not_null()); - CString::new(name_str, false).as_str().unwrap().to_string() + string::raw::from_buf(name_str as *const u8) } } @@ -372,7 +372,7 @@ impl UvError { let inner = match self { &UvError(a) => a }; let desc_str = uvll::uv_strerror(inner); assert!(desc_str.is_not_null()); - CString::new(desc_str, false).as_str().unwrap().to_string() + string::raw::from_buf(desc_str as *const u8) } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index d2a2d9ff64b..ebcb60253f5 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -49,7 +49,6 @@ use slice::{Vector, ImmutableVector, MutableVector, ImmutableEqVector}; use str::{Str, StrSlice, StrAllocating}; use string::String; use sync::atomics::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; -use to_string::ToString; use vec::Vec; #[cfg(unix)] @@ -998,7 +997,7 @@ pub fn error_string(errnum: uint) -> String { fail!("strerror_r failure"); } - ::c_str::CString::new(p as *const c_char, false).as_str().unwrap().to_string() + ::string::raw::from_buf(p as *const u8) } }