All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			See #478
		
			
				
	
	
		
			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}
 | |
| }
 |