From e9571850daded0f46ae3b9b8e0834b6be2e5219b Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 6 Mar 2012 16:00:29 -0800 Subject: [PATCH] UTF-16-ify the win32 env routines. --- src/libcore/libc.rs | 7 ++++--- src/libcore/os.rs | 40 +++++++++++++++++++++++++++++++++++----- src/libcore/str.rs | 10 +++++----- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index fceb1f9f086..09af26336e0 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -1100,10 +1100,11 @@ mod funcs { #[abi = "stdcall"] native mod kernel32 { - fn GetEnvironmentVariableA(n: LPCSTR, - v: LPSTR, + fn GetEnvironmentVariableW(n: LPCWSTR, + v: LPWSTR, nsize: DWORD) -> DWORD; - fn SetEnvironmentVariableA(n: LPCSTR, v: LPCSTR) -> BOOL; + fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR) -> BOOL; + fn GetModuleFileNameA(hModule: HMODULE, lpFilename: LPSTR, nSize: DWORD) -> DWORD; diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 3cb0f7afe7c..ad18993c762 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -50,7 +50,17 @@ fn as_c_charp(s: str, f: fn(*c_char) -> T) -> T { str::as_buf(s) {|b| f(b as *c_char) } } -// FIXME: UTF-16-ify this and revive win32 Unicode variant. +fn as_utf16_p(s: str, f: fn(*u16) -> T) -> T { + let t = str::to_utf16(s); + // "null terminate" + t += [0u16]; + vec::as_buf(t, f) +} + + +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] fn getenv(n: str) -> option unsafe { let s = as_c_charp(n, libc::getenv); ret if unsafe::reinterpret_cast(s) == 0 { @@ -61,6 +71,27 @@ fn getenv(n: str) -> option unsafe { }; } +#[cfg(target_os = "win32")] +fn getenv(n: str) -> option unsafe { + import libc::types::os::arch::extra::*; + import libc::funcs::extra::kernel32; + as_utf16_p(n) {|u| + let bufsize = 1023u; + let buf = vec::to_mut(vec::init_elt(bufsize, 0u16)); + vec::as_mut_buf(buf) {|b| + let k = kernel32::GetEnvironmentVariableW(u, b, + bufsize as DWORD); + if k != (0 as DWORD) { + let sub = vec::slice(buf, 0u, k as uint); + option::some::(str::from_utf16(sub)) + } else { + option::none:: + } + } + } +} + + #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] @@ -78,13 +109,12 @@ fn setenv(n: str, v: str) { #[cfg(target_os = "win32")] -// FIXME: UTF-16-ify this and switch to the W version. fn setenv(n: str, v: str) { // FIXME: remove imports when export globs work properly. import libc::funcs::extra::kernel32; - as_c_charp(n) {|nbuf| - as_c_charp(v) {|vbuf| - kernel32::SetEnvironmentVariableA(nbuf, vbuf); + as_utf16_p(n) {|nbuf| + as_utf16_p(v) {|vbuf| + kernel32::SetEnvironmentVariableW(nbuf, vbuf); } } } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 5be3cb64037..5760cc8b066 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1047,7 +1047,7 @@ Function: is_utf8 Determines if a vector of bytes contains valid UTF-8 */ -fn is_utf8(v: [u8]) -> bool { +fn is_utf8(v: [const u8]) -> bool { let i = 0u; let total = vec::len::(v); while i < total { @@ -1065,7 +1065,7 @@ fn is_utf8(v: [u8]) -> bool { } -fn is_utf16(v: [u16]) -> bool { +fn is_utf16(v: [const u16]) -> bool { let len = v.len(); let i = 0u; while (i < len) { @@ -1108,10 +1108,10 @@ fn to_utf16(s: str) -> [u16] { ret u; } -fn utf16_chars(v: [u16], f: fn(char)) { +fn utf16_chars(v: [const u16], f: fn(char)) { let len = v.len(); let i = 0u; - while (i < len) { + while (i < len && v[i] != 0u16) { let u = v[i]; if u <= 0xD7FF_u16 || u >= 0xE000_u16 { @@ -1133,7 +1133,7 @@ fn utf16_chars(v: [u16], f: fn(char)) { } -fn from_utf16(v: [u16]) -> str { +fn from_utf16(v: [const u16]) -> str { let buf = ""; reserve(buf, v.len()); utf16_chars(v) {|ch| push_char(buf, ch); }