abra/vendor/github.com/mattn/go-localereader/localereader_windows.go
decentral1se 30d3dbc796
All checks were successful
continuous-integration/drone/push Build is passing
feat: improved deploy progress reporting
See #478
2025-03-23 10:04:06 +01:00

86 lines
1.7 KiB
Go

// +build windows
package localereader
import (
"io"
"syscall"
"unicode/utf8"
"unsafe"
"golang.org/x/text/transform"
)
const (
CP_ACP = 0
MB_ERR_INVALID_CHARS = 8
)
var (
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar")
procIsDBCSLeadByte = modkernel32.NewProc("IsDBCSLeadByte")
)
type codepageDecoder struct {
transform.NopResetter
cp int
}
func (codepageDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
loop:
for ; nSrc < len(src); nSrc += size {
switch c0 := src[nSrc]; {
case c0 < utf8.RuneSelf:
r, size = rune(c0), 1
default:
br, _, _ := procIsDBCSLeadByte.Call(uintptr(src[nSrc]))
if br == 0 {
r = rune(src[nSrc])
size = 1
break
}
if nSrc >= len(src)-1 {
r = rune(src[nSrc])
size = 1
break
}
n, _, _ := procMultiByteToWideChar.Call(CP_ACP, 0, uintptr(unsafe.Pointer(&src[nSrc])), uintptr(2), uintptr(0), 0)
if n <= 0 {
err = syscall.GetLastError()
break
}
var us [1]uint16
rc, _, _ := procMultiByteToWideChar.Call(CP_ACP, 0, uintptr(unsafe.Pointer(&src[nSrc])), uintptr(2), uintptr(unsafe.Pointer(&us[0])), 1)
if rc == 0 {
size = 1
break
}
r = rune(us[0])
size = 2
}
if nDst+utf8.RuneLen(r) > len(dst) {
err = transform.ErrShortDst
break loop
}
nDst += utf8.EncodeRune(dst[nDst:], r)
}
return nDst, nSrc, err
}
func newReader(r io.Reader) io.Reader {
return transform.NewReader(r, NewAcpDecoder())
}
func NewCodePageDecoder(cp int) transform.Transformer {
return &codepageDecoder{cp: cp}
}
func NewAcpDecoder() transform.Transformer {
return &codepageDecoder{cp: CP_ACP}
}