Skip to content

Commit

Permalink
Add as_c_str method on strings
Browse files Browse the repository at this point in the history
  • Loading branch information
bstrie committed May 31, 2013
1 parent 91a7073 commit c77d58f
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/libstd/prelude.rs
Expand Up @@ -45,7 +45,7 @@ pub use path::PosixPath;
pub use path::WindowsPath;
pub use ptr::Ptr;
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
pub use str::{StrSlice, OwnedStr};
pub use str::{StrSlice, OwnedStr, StrUtil};
pub use from_str::{FromStr};
pub use to_bytes::IterBytes;
pub use to_str::{ToStr, ToStrConsume};
Expand Down
61 changes: 39 additions & 22 deletions src/libstd/str.rs
Expand Up @@ -2165,33 +2165,50 @@ pub fn as_bytes_slice<'a>(s: &'a str) -> &'a [u8] {
}

/**
* Work with the byte buffer of a string as a null-terminated C string.
*
* Allows for unsafe manipulation of strings, which is useful for foreign
* interop. This is similar to `str::as_buf`, but guarantees null-termination.
* If the given slice is not already null-terminated, this function will
* allocate a temporary, copy the slice, null terminate it, and pass
* that instead.
*
* # Example
*
* ~~~ {.rust}
* let s = str::as_c_str("PATH", { |path| libc::getenv(path) });
* ~~~
* A dummy trait to hold all the utility methods that we implement on strings.
*/
#[inline]
pub fn as_c_str<T>(s: &str, f: &fn(*libc::c_char) -> T) -> T {
do as_buf(s) |buf, len| {
// NB: len includes the trailing null.
assert!(len > 0);
if unsafe { *(ptr::offset(buf,len-1)) != 0 } {
as_c_str(to_owned(s), f)
} else {
f(buf as *libc::c_char)
pub trait StrUtil {
/**
* Work with the byte buffer of a string as a null-terminated C string.
*
* Allows for unsafe manipulation of strings, which is useful for foreign
* interop. This is similar to `str::as_buf`, but guarantees null-termination.
* If the given slice is not already null-terminated, this function will
* allocate a temporary, copy the slice, null terminate it, and pass
* that instead.
*
* # Example
*
* ~~~ {.rust}
* let s = "PATH".as_c_str(|path| libc::getenv(path));
* ~~~
*/
fn as_c_str<T>(self, f: &fn(*libc::c_char) -> T) -> T;
}

impl<'self> StrUtil for &'self str {
#[inline]
fn as_c_str<T>(self, f: &fn(*libc::c_char) -> T) -> T {
do as_buf(self) |buf, len| {
// NB: len includes the trailing null.
assert!(len > 0);
if unsafe { *(ptr::offset(buf,len-1)) != 0 } {
to_owned(self).as_c_str(f)
} else {
f(buf as *libc::c_char)
}
}
}
}

/**
* Deprecated. Use the `as_c_str` method on strings instead.
*/
#[inline(always)]
pub fn as_c_str<T>(s: &str, f: &fn(*libc::c_char) -> T) -> T {
s.as_c_str(f)
}

/**
* Work with the byte buffer and length of a slice.
*
Expand Down

5 comments on commit c77d58f

@bors
Copy link
Contributor

@bors bors commented on c77d58f Jun 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from Aatch
at bstrie@c77d58f

@bors
Copy link
Contributor

@bors bors commented on c77d58f Jun 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging bstrie/rust/ascstr = c77d58f into auto

@bors
Copy link
Contributor

@bors bors commented on c77d58f Jun 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bstrie/rust/ascstr = c77d58f merged ok, testing candidate = b570536

@bors
Copy link
Contributor

@bors bors commented on c77d58f Jun 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on c77d58f Jun 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding incoming to auto = b570536

Please sign in to comment.