github.com/jspc/eggos@v0.5.1-0.20221028160421-556c75c878a5/drivers/cga/ansi.go (about)

     1  package cga
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  )
     7  
     8  const (
     9  	stateBegin = iota
    10  	stateESC
    11  	stateLeft
    12  	stateParam
    13  	stateDone
    14  )
    15  
    16  const (
    17  	_ESC = 0x1b
    18  )
    19  
    20  var (
    21  	errInvalidChar = errors.New("invalid char")
    22  	errNormalChar  = errors.New("normal char")
    23  	errCSIDone     = errors.New("done")
    24  )
    25  
    26  type ansiParser struct {
    27  	state int
    28  
    29  	action   byte
    30  	parambuf []byte
    31  	params   []string
    32  }
    33  
    34  func (p *ansiParser) step(ch byte) error {
    35  	switch p.state {
    36  	case stateBegin:
    37  		if ch != _ESC {
    38  			return errNormalChar
    39  		}
    40  		p.state = stateESC
    41  	case stateESC:
    42  		if ch != '[' {
    43  			return errInvalidChar
    44  		}
    45  		p.state = stateLeft
    46  	case stateLeft:
    47  		switch {
    48  		case ch >= 0x30 && ch <= 0x3f:
    49  			p.state = stateParam
    50  			p.parambuf = append(p.parambuf, ch)
    51  		case ch >= 0x40 && ch <= 0x7f:
    52  			p.action = ch
    53  			p.state = stateDone
    54  		default:
    55  			return errInvalidChar
    56  		}
    57  	case stateParam:
    58  		switch {
    59  		case ch >= 0x30 && ch <= 0x3f:
    60  			p.parambuf = append(p.parambuf, ch)
    61  		case ch >= 0x40 && ch <= 0x7f:
    62  			p.action = ch
    63  			p.state = stateDone
    64  		default:
    65  			return errInvalidChar
    66  		}
    67  	}
    68  	if p.state == stateDone {
    69  		p.decodePram()
    70  		return errCSIDone
    71  	}
    72  	return nil
    73  }
    74  
    75  func (p *ansiParser) decodePram() {
    76  	if len(p.parambuf) == 0 {
    77  		return
    78  	}
    79  	params := bytes.Split(p.parambuf, []byte(";"))
    80  	for _, param := range params {
    81  		p.params = append(p.params, string(param))
    82  	}
    83  }
    84  
    85  func (p *ansiParser) Action() byte {
    86  	return p.action
    87  }
    88  
    89  func (p *ansiParser) Params() []string {
    90  	return p.params
    91  }
    92  
    93  func (p *ansiParser) Reset() {
    94  	p.state = stateBegin
    95  	p.action = 0
    96  	p.parambuf = p.parambuf[:0]
    97  	p.params = p.params[:0]
    98  }