forked from toolshed/abra
		
	
		
			
				
	
	
		
			86 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			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}
 | 
						|
}
 |