2
0
Эх сурвалжийг харах

Factor out buffered utf helper.

Jeroen van Rijn 2 сар өмнө
parent
commit
eef07431ef

+ 7 - 30
core/os/env_windows.odin

@@ -35,50 +35,27 @@ lookup_env_alloc :: proc(key: string, allocator := context.allocator) -> (value:
 @(require_results)
 lookup_env_buffer :: proc(buf: []u8, key: string) -> (value: string, err: Error) {
 	key_buf: [513]u16
-	n1 := win32.MultiByteToWideChar(win32.CP_UTF8, win32.MB_ERR_INVALID_CHARS, raw_data(key), i32(len(key)), nil, 0)
-	if n1 == 0 {
-		return "", nil
-	}
-
-	n1 = win32.MultiByteToWideChar(win32.CP_UTF8, win32.MB_ERR_INVALID_CHARS, raw_data(key), i32(len(key)), raw_data(key_buf[:]), n1)
-	if n1 == 0 {
-		return "", nil
+	wkey := win32.utf8_to_wstring(key_buf[:], key)
+	if wkey == nil {
+		return "", .Buffer_Full
 	}
 
-	n2 := win32.GetEnvironmentVariableW(raw_data(key_buf[:]), nil, 0)
+	n2 := win32.GetEnvironmentVariableW(wkey, nil, 0)
 	if n2 == 0 && get_last_error() == ERROR_ENVVAR_NOT_FOUND {
 		return "", .Env_Var_Not_Found
 	}
 
 	val_buf: [513]u16
-	n2 = win32.GetEnvironmentVariableW(raw_data(key_buf[:]), raw_data(val_buf[:]), u32(len(val_buf[:])))
+	n2 = win32.GetEnvironmentVariableW(wkey, raw_data(val_buf[:]), u32(len(val_buf[:])))
 	if n2 == 0 && get_last_error() == ERROR_ENVVAR_NOT_FOUND {
 		return "", .Env_Var_Not_Found
 	} else if int(n2) > len(buf) {
 		return "", .Buffer_Full
 	}
 
-	n3 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(val_buf[:]), -1, nil, 0, nil, nil)
-	if n3 == 0 {
-		return
-	} else if int(n3) > len(buf) {
-		return "", .Buffer_Full
-	}
-
-	n4 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(val_buf[:]), -1, raw_data(buf), n3, nil, nil)
-	if n4 == 0 {
-		return
-	} else if int(n4) > len(buf) {
-		return "", .Buffer_Full
-	}
+	value = win32.utf16_to_utf8(buf, val_buf[:n2])
 
-	for i in 0..<n3 {
-		if buf[i] == 0 {
-			n3 = i
-			break
-		}
-	}
-	return string(buf[:n3]), nil
+	return value, nil
 }
 lookup_env :: proc{lookup_env_alloc, lookup_env_buffer}
 

+ 68 - 4
core/sys/windows/util.odin

@@ -75,7 +75,7 @@ LANGIDFROMLCID :: #force_inline proc "contextless" (lcid: LCID) -> LANGID {
 	return LANGID(lcid)
 }
 
-utf8_to_utf16 :: proc(s: string, allocator := context.temp_allocator) -> []u16 {
+utf8_to_utf16_alloc :: proc(s: string, allocator := context.temp_allocator) -> []u16 {
 	if len(s) < 1 {
 		return nil
 	}
@@ -101,14 +101,42 @@ utf8_to_utf16 :: proc(s: string, allocator := context.temp_allocator) -> []u16 {
 	}
 	return text[:n]
 }
-utf8_to_wstring :: proc(s: string, allocator := context.temp_allocator) -> wstring {
+
+utf8_to_utf16_buf :: proc(buf: []u16, s: string) -> []u16 {
+	n1 := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), nil, 0)
+	if n1 == 0 {
+		return nil
+	} else if int(n1) > len(buf) {
+		return nil
+	}
+
+	n1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), raw_data(buf[:]), n1)
+	if n1 == 0 {
+		return nil
+	} else if int(n1) > len(buf) {
+		return nil
+	}
+	return buf[:n1]
+}
+utf8_to_utf16 :: proc{utf8_to_utf16_alloc, utf8_to_utf16_buf}
+
+utf8_to_wstring_alloc :: proc(s: string, allocator := context.temp_allocator) -> wstring {
 	if res := utf8_to_utf16(s, allocator); len(res) > 0 {
 		return raw_data(res)
 	}
 	return nil
 }
 
-wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) {
+utf8_to_wstring_buf :: proc(buf: []u16, s: string) -> wstring {
+	if res := utf8_to_utf16(buf, s); len(res) > 0 {
+		return raw_data(res)
+	}
+	return nil
+}
+
+utf8_to_wstring :: proc{utf8_to_wstring_alloc, utf8_to_wstring_buf}
+
+wstring_to_utf8_alloc :: proc(s: wstring, N: int, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) {
 	context.allocator = allocator
 
 	if N == 0 {
@@ -142,13 +170,49 @@ wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator)
 	return string(text[:n]), nil
 }
 
-utf16_to_utf8 :: proc(s: []u16, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) {
+wstring_to_utf8_buf :: proc(buf: []u8, s: wstring) -> (res: string) {
+	n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, -1, nil, 0, nil, nil)
+	if n == 0 {
+		return
+	} else if int(n) > len(buf) {
+		return
+	}
+
+	n2 := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, -1, raw_data(buf), n, nil, nil)
+	if n2 == 0 {
+		return
+	} else if int(n2) > len(buf) {
+		return
+	}
+
+	for i in 0..<n2 {
+		if buf[i] == 0 {
+			n2 = i
+			break
+		}
+	}
+	return string(buf[:n2])
+}
+
+wstring_to_utf8 :: proc{wstring_to_utf8_alloc, wstring_to_utf8_buf}
+
+utf16_to_utf8_alloc :: proc(s: []u16, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) {
 	if len(s) == 0 {
 		return "", nil
 	}
 	return wstring_to_utf8(raw_data(s), len(s), allocator)
 }
 
+utf16_to_utf8_buf :: proc(buf: []u8, s: []u16) -> (res: string) {
+	if len(s) == 0 {
+		return
+	}
+	return wstring_to_utf8(buf, raw_data(s))
+}
+
+utf16_to_utf8 :: proc{utf16_to_utf8_alloc, utf16_to_utf8_buf}
+
+
 // AdvAPI32, NetAPI32 and UserENV helpers.
 
 allowed_username :: proc(username: string) -> bool {