From b25e002092edf81de6b74ef7879f1f4affd8bf32 Mon Sep 17 00:00:00 2001 From: messypy Date: Mon, 27 Jul 2026 23:13:30 +0900 Subject: [PATCH] Make log decoding build on non-Windows CI --- internal/app/codepage_nonwindows.go | 7 +++++ internal/app/codepage_windows.go | 37 +++++++++++++++++++++++ internal/app/vrc_log.go | 46 ++++++++--------------------- 3 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 internal/app/codepage_nonwindows.go create mode 100644 internal/app/codepage_windows.go diff --git a/internal/app/codepage_nonwindows.go b/internal/app/codepage_nonwindows.go new file mode 100644 index 0000000..675dfe8 --- /dev/null +++ b/internal/app/codepage_nonwindows.go @@ -0,0 +1,7 @@ +//go:build !windows + +package app + +func decodeWithCodePage(_ []byte, _ uint32) string { + return "" +} diff --git a/internal/app/codepage_windows.go b/internal/app/codepage_windows.go new file mode 100644 index 0000000..9ecdb30 --- /dev/null +++ b/internal/app/codepage_windows.go @@ -0,0 +1,37 @@ +//go:build windows + +package app + +import ( + "syscall" + "unsafe" +) + +func decodeWithCodePage(b []byte, codePage uint32) string { + if len(b) == 0 { + return "" + } + kernel32 := syscall.NewLazyDLL("kernel32.dll") + multiByteToWideChar := kernel32.NewProc("MultiByteToWideChar") + n, _, _ := multiByteToWideChar.Call( + uintptr(codePage), + 0, + uintptr(unsafe.Pointer(&b[0])), + uintptr(len(b)), + 0, + 0, + ) + if n == 0 { + return "" + } + buf := make([]uint16, n) + multiByteToWideChar.Call( + uintptr(codePage), + 0, + uintptr(unsafe.Pointer(&b[0])), + uintptr(len(b)), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(len(buf)), + ) + return utf16ToString(buf) +} diff --git a/internal/app/vrc_log.go b/internal/app/vrc_log.go index 9cb7132..e68bc5a 100644 --- a/internal/app/vrc_log.go +++ b/internal/app/vrc_log.go @@ -9,9 +9,8 @@ import ( "path/filepath" "regexp" "strings" - "syscall" "time" - "unsafe" + "unicode/utf16" ) var ( @@ -315,14 +314,14 @@ func decodeVRChatLog(b []byte) string { for i := 2; i+1 < len(b); i += 2 { u16 = append(u16, uint16(b[i])|uint16(b[i+1])<<8) } - return strings.TrimPrefix(fixMojibake(syscall.UTF16ToString(u16)), "\ufeff") + return strings.TrimPrefix(fixMojibake(utf16ToString(u16)), "\ufeff") } if b[0] == 0xfe && b[1] == 0xff { u16 := make([]uint16, 0, (len(b)-2)/2) for i := 2; i+1 < len(b); i += 2 { u16 = append(u16, uint16(b[i+1])|uint16(b[i])<<8) } - return strings.TrimPrefix(fixMojibake(syscall.UTF16ToString(u16)), "\ufeff") + return strings.TrimPrefix(fixMojibake(utf16ToString(u16)), "\ufeff") } } lines := bytes.Split(b, []byte{'\n'}) @@ -377,6 +376,16 @@ func tryRepairShiftJISMojibake(s string) string { return "" } +func utf16ToString(u16 []uint16) string { + for i, r := range u16 { + if r == 0 { + u16 = u16[:i] + break + } + } + return string(utf16.Decode(u16)) +} + func scoreReadable(s string) int { if s == "" { return -1 @@ -401,35 +410,6 @@ func scoreReadable(s string) int { return score } -func decodeWithCodePage(b []byte, codePage uint32) string { - if len(b) == 0 { - return "" - } - kernel32 := syscall.NewLazyDLL("kernel32.dll") - multiByteToWideChar := kernel32.NewProc("MultiByteToWideChar") - n, _, _ := multiByteToWideChar.Call( - uintptr(codePage), - 0, - uintptr(unsafe.Pointer(&b[0])), - uintptr(len(b)), - 0, - 0, - ) - if n == 0 { - return "" - } - buf := make([]uint16, n) - multiByteToWideChar.Call( - uintptr(codePage), - 0, - uintptr(unsafe.Pointer(&b[0])), - uintptr(len(b)), - uintptr(unsafe.Pointer(&buf[0])), - uintptr(len(buf)), - ) - return syscall.UTF16ToString(buf) -} - func updateWorldState(state *vrcLogState, line string) (bool, string) { worldID := "" instanceID := ""