str: add a function for truncating a vector of u16 at NUL.
Many of the functions interacting with Windows APIs allocate a vector of 0's and do not retrieve a length directly from the API call, and so need to be sure to remove the unmodified junk at the end of the vector.
This commit is contained in:
parent
4f841ee150
commit
c9b4538bab
@ -571,7 +571,8 @@ pub fn readdir(p: &CString) -> IoResult<~[Path]> {
|
||||
else {
|
||||
let fp_vec = vec::from_buf(
|
||||
fp_buf, wcslen(fp_buf) as uint);
|
||||
let fp_str = str::from_utf16(fp_vec)
|
||||
let fp_trimmed = str::truncate_utf16_at_nul(fp_vec);
|
||||
let fp_str = str::from_utf16(fp_trimmed)
|
||||
.expect("rust_list_dir_wfd_fp_buf returned invalid UTF-16");
|
||||
paths.push(Path::new(fp_str));
|
||||
}
|
||||
|
@ -88,7 +88,8 @@ pub fn getcwd() -> Path {
|
||||
fail!();
|
||||
}
|
||||
}
|
||||
Path::new(str::from_utf16(buf).expect("GetCurrentDirectoryW returned invalid UTF-16"))
|
||||
Path::new(str::from_utf16(str::truncate_utf16_at_nul(buf))
|
||||
.expect("GetCurrentDirectoryW returned invalid UTF-16"))
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@ -744,7 +745,8 @@ pub fn last_os_error() -> ~str {
|
||||
fail!("[{}] FormatMessage failure", errno());
|
||||
}
|
||||
|
||||
str::from_utf16(buf).expect("FormatMessageW returned invalid UTF-16")
|
||||
str::from_utf16(str::truncate_utf16_at_nul(buf))
|
||||
.expect("FormatMessageW returned invalid UTF-16")
|
||||
}
|
||||
}
|
||||
|
||||
@ -833,7 +835,9 @@ fn real_args() -> ~[~str] {
|
||||
while *ptr.offset(len as int) != 0 { len += 1; }
|
||||
|
||||
// Push it onto the list.
|
||||
let opt_s = vec::raw::buf_as_slice(ptr, len, str::from_utf16);
|
||||
let opt_s = vec::raw::buf_as_slice(ptr, len, |buf| {
|
||||
str::from_utf16(str::truncate_utf16_at_nul(buf))
|
||||
});
|
||||
args.push(opt_s.expect("CommandLineToArgvW returned invalid UTF-16"));
|
||||
}
|
||||
}
|
||||
|
@ -920,6 +920,32 @@ pub fn utf16_items<'a>(v: &'a [u16]) -> UTF16Items<'a> {
|
||||
UTF16Items { iter : v.iter() }
|
||||
}
|
||||
|
||||
/// Return a slice of `v` ending at (and not including) the first NUL
|
||||
/// (0).
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::str;
|
||||
///
|
||||
/// // "abcd"
|
||||
/// let mut v = ['a' as u16, 'b' as u16, 'c' as u16, 'd' as u16];
|
||||
/// // no NULs so no change
|
||||
/// assert_eq!(str::truncate_utf16_at_nul(v), v.as_slice());
|
||||
///
|
||||
/// // "ab\0d"
|
||||
/// v[2] = 0;
|
||||
/// assert_eq!(str::truncate_utf16_at_nul(v),
|
||||
/// &['a' as u16, 'b' as u16]);
|
||||
/// ```
|
||||
pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
|
||||
match v.iter().position(|c| *c == 0) {
|
||||
// don't include the 0
|
||||
Some(i) => v.slice_to(i),
|
||||
None => v
|
||||
}
|
||||
}
|
||||
|
||||
/// Decode a UTF-16 encoded vector `v` into a string, returning `None`
|
||||
/// if `v` contains any invalid data.
|
||||
///
|
||||
@ -3875,6 +3901,24 @@ mod tests {
|
||||
assert_eq!(from_utf16_lossy([0xD800, 0xd801, 0xdc8b, 0xD800]), ~"\uFFFD𐒋\uFFFD");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_truncate_utf16_at_nul() {
|
||||
let v = [];
|
||||
assert_eq!(truncate_utf16_at_nul(v), &[]);
|
||||
|
||||
let v = [0, 2, 3];
|
||||
assert_eq!(truncate_utf16_at_nul(v), &[]);
|
||||
|
||||
let v = [1, 0, 3];
|
||||
assert_eq!(truncate_utf16_at_nul(v), &[1]);
|
||||
|
||||
let v = [1, 2, 0];
|
||||
assert_eq!(truncate_utf16_at_nul(v), &[1, 2]);
|
||||
|
||||
let v = [1, 2, 3];
|
||||
assert_eq!(truncate_utf16_at_nul(v), &[1, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_char_at() {
|
||||
let s = ~"ศไทย中华Việt Nam";
|
||||
|
Loading…
x
Reference in New Issue
Block a user