Reduce memory allocation and remove channels
Signed-off-by: Sachin Joshi <sachin_jayant_joshi@hotmail.com>
This commit is contained in:
parent
7fc3c0ba26
commit
9cc42dea7c
1 changed files with 31 additions and 39 deletions
|
@ -83,6 +83,7 @@ const (
|
|||
|
||||
ANSI_MAX_CMD_LENGTH = 256
|
||||
|
||||
MAX_INPUT_EVENTS = 128
|
||||
MAX_INPUT_BUFFER = 1024
|
||||
DEFAULT_WIDTH = 80
|
||||
DEFAULT_HEIGHT = 24
|
||||
|
@ -195,15 +196,18 @@ type (
|
|||
type WindowsTerminal struct {
|
||||
outMutex sync.Mutex
|
||||
inMutex sync.Mutex
|
||||
inputBuffer chan byte
|
||||
inputBuffer []byte
|
||||
inputSize int
|
||||
inputEvents []INPUT_RECORD
|
||||
screenBufferInfo *CONSOLE_SCREEN_BUFFER_INFO
|
||||
inputEscapeSequence []byte
|
||||
}
|
||||
|
||||
func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
|
||||
handler := &WindowsTerminal{
|
||||
inputBuffer: make(chan byte, MAX_INPUT_BUFFER),
|
||||
inputBuffer: make([]byte, MAX_INPUT_BUFFER),
|
||||
inputEscapeSequence: []byte(KEY_ESC_CSI),
|
||||
inputEvents: make([]INPUT_RECORD, MAX_INPUT_EVENTS),
|
||||
}
|
||||
|
||||
// Save current screen buffer info
|
||||
|
@ -218,6 +222,8 @@ func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
|
|||
|
||||
// Set the window size
|
||||
SetWindowSize(uintptr(handle), DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_HEIGHT)
|
||||
buffer = make([]CHAR_INFO, screenBufferInfo.MaximumWindowSize.X*screenBufferInfo.MaximumWindowSize.Y)
|
||||
|
||||
if IsTerminal(os.Stdout.Fd()) {
|
||||
stdOut = &terminalWriter{
|
||||
wrappedWriter: os.Stdout,
|
||||
|
@ -427,6 +433,8 @@ func getNumberOfChars(fromCoord COORD, toCoord COORD, screenSize COORD) uint32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
var buffer []CHAR_INFO
|
||||
|
||||
func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (bool, uint32, error) {
|
||||
var writeRegion SMALL_RECT
|
||||
writeRegion.Top = fromCoord.Y
|
||||
|
@ -439,14 +447,13 @@ func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoor
|
|||
height := toCoord.Y - fromCoord.Y + 1
|
||||
size := width * height
|
||||
if size > 0 {
|
||||
buffer := make([]CHAR_INFO, size)
|
||||
for i := 0; i < len(buffer); i++ {
|
||||
for i := 0; i < int(size); i++ {
|
||||
buffer[i].UnicodeChar = WCHAR(fillChar)
|
||||
buffer[i].Attributes = attributes
|
||||
}
|
||||
|
||||
// Write to buffer
|
||||
r, err := writeConsoleOutput(fileDesc, buffer, windowSize, COORD{X: 0, Y: 0}, &writeRegion)
|
||||
r, err := writeConsoleOutput(fileDesc, buffer[:size], windowSize, COORD{X: 0, Y: 0}, &writeRegion)
|
||||
if !r {
|
||||
if err != nil {
|
||||
return false, 0, err
|
||||
|
@ -914,6 +921,9 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
|
|||
|
||||
// WriteChars writes the bytes to given writer.
|
||||
func (term *WindowsTerminal) WriteChars(fd uintptr, w io.Writer, p []byte) (n int, err error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
return w.Write(p)
|
||||
}
|
||||
|
||||
|
@ -1049,24 +1059,19 @@ func mapKeystokeToTerminalString(keyEvent *KEY_EVENT_RECORD, escapeSequence []by
|
|||
|
||||
// getAvailableInputEvents polls the console for availble events
|
||||
// The function does not return until at least one input record has been read.
|
||||
func getAvailableInputEvents(fd uintptr) (inputEvents []INPUT_RECORD, err error) {
|
||||
func getAvailableInputEvents(fd uintptr, inputEvents []INPUT_RECORD) (n int, err error) {
|
||||
handle := syscall.Handle(fd)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
return 0, err
|
||||
}
|
||||
for {
|
||||
// Read number of console events available
|
||||
tempBuffer := make([]INPUT_RECORD, MAX_INPUT_BUFFER)
|
||||
nr, err := readConsoleInputKey(uintptr(handle), tempBuffer)
|
||||
nr, err := readConsoleInputKey(uintptr(handle), inputEvents)
|
||||
if nr == 0 {
|
||||
return nil, err
|
||||
return 0, err
|
||||
}
|
||||
if 0 < nr {
|
||||
retValue := make([]INPUT_RECORD, nr)
|
||||
for i := 0; i < nr; i++ {
|
||||
retValue[i] = tempBuffer[i]
|
||||
}
|
||||
return retValue, nil
|
||||
return nr, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1086,32 +1091,19 @@ func getTranslatedKeyCodes(inputEvents []INPUT_RECORD, escapeSequence []byte) st
|
|||
}
|
||||
|
||||
// ReadChars reads the characters from the given reader
|
||||
func (term *WindowsTerminal) ReadChars(fd uintptr, w io.Reader, p []byte) (n int, err error) {
|
||||
n = 0
|
||||
for n < len(p) {
|
||||
select {
|
||||
case b := <-term.inputBuffer:
|
||||
p[n] = b
|
||||
n++
|
||||
default:
|
||||
// Read at least one byte read
|
||||
if n > 0 {
|
||||
return n, nil
|
||||
}
|
||||
inputEvents, _ := getAvailableInputEvents(fd)
|
||||
if inputEvents != nil {
|
||||
if len(inputEvents) == 0 && nil != err {
|
||||
return n, err
|
||||
}
|
||||
if len(inputEvents) != 0 {
|
||||
keyCodes := getTranslatedKeyCodes(inputEvents, term.inputEscapeSequence)
|
||||
for _, b := range []byte(keyCodes) {
|
||||
term.inputBuffer <- b
|
||||
}
|
||||
}
|
||||
}
|
||||
func (term *WindowsTerminal) ReadChars(fd uintptr, r io.Reader, p []byte) (n int, err error) {
|
||||
for term.inputSize == 0 {
|
||||
nr, err := getAvailableInputEvents(fd, term.inputEvents)
|
||||
if nr == 0 && nil != err {
|
||||
return n, err
|
||||
}
|
||||
if nr > 0 {
|
||||
keyCodes := getTranslatedKeyCodes(term.inputEvents[:nr], term.inputEscapeSequence)
|
||||
term.inputSize = copy(term.inputBuffer, keyCodes)
|
||||
}
|
||||
}
|
||||
n = copy(p, term.inputBuffer[:term.inputSize])
|
||||
term.inputSize -= n
|
||||
return n, nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue