seq.go

  1package parser
  2
  3import "math"
  4
  5// Shift and masks for sequence parameters and intermediates.
  6const (
  7	PrefixShift    = 8
  8	IntermedShift  = 16
  9	FinalMask      = 0xff
 10	HasMoreFlag    = math.MinInt32
 11	ParamMask      = ^HasMoreFlag
 12	MissingParam   = ParamMask
 13	MissingCommand = MissingParam
 14	MaxParam       = math.MaxUint16 // the maximum value a parameter can have
 15)
 16
 17const (
 18	// MaxParamsSize is the maximum number of parameters a sequence can have.
 19	MaxParamsSize = 32
 20
 21	// DefaultParamValue is the default value used for missing parameters.
 22	DefaultParamValue = 0
 23)
 24
 25// Prefix returns the prefix byte of the sequence.
 26// This is always gonna be one of the following '<' '=' '>' '?' and in the
 27// range of 0x3C-0x3F.
 28// Zero is returned if the sequence does not have a prefix.
 29func Prefix(cmd int) int {
 30	return (cmd >> PrefixShift) & FinalMask
 31}
 32
 33// Intermediate returns the intermediate byte of the sequence.
 34// An intermediate byte is in the range of 0x20-0x2F. This includes these
 35// characters from ' ', '!', '"', '#', '$', '%', '&', ”', '(', ')', '*', '+',
 36// ',', '-', '.', '/'.
 37// Zero is returned if the sequence does not have an intermediate byte.
 38func Intermediate(cmd int) int {
 39	return (cmd >> IntermedShift) & FinalMask
 40}
 41
 42// Command returns the command byte of the CSI sequence.
 43func Command(cmd int) int {
 44	return cmd & FinalMask
 45}
 46
 47// Param returns the parameter at the given index.
 48// It returns -1 if the parameter does not exist.
 49func Param(params []int, i int) int {
 50	if len(params) == 0 || i < 0 || i >= len(params) {
 51		return -1
 52	}
 53
 54	p := params[i] & ParamMask
 55	if p == MissingParam {
 56		return -1
 57	}
 58
 59	return p
 60}
 61
 62// HasMore returns true if the parameter has more sub-parameters.
 63func HasMore(params []int, i int) bool {
 64	if len(params) == 0 || i >= len(params) {
 65		return false
 66	}
 67
 68	return params[i]&HasMoreFlag != 0
 69}
 70
 71// Subparams returns the sub-parameters of the given parameter.
 72// It returns nil if the parameter does not exist.
 73func Subparams(params []int, i int) []int {
 74	if len(params) == 0 || i < 0 || i >= len(params) {
 75		return nil
 76	}
 77
 78	// Count the number of parameters before the given parameter index.
 79	var count int
 80	var j int
 81	for j = range params {
 82		if count == i {
 83			break
 84		}
 85		if !HasMore(params, j) {
 86			count++
 87		}
 88	}
 89
 90	if count > i || j >= len(params) {
 91		return nil
 92	}
 93
 94	var subs []int
 95	for ; j < len(params); j++ {
 96		if !HasMore(params, j) {
 97			break
 98		}
 99		p := Param(params, j)
100		if p == -1 {
101			p = DefaultParamValue
102		}
103		subs = append(subs, p)
104	}
105
106	p := Param(params, j)
107	if p == -1 {
108		p = DefaultParamValue
109	}
110
111	return append(subs, p)
112}
113
114// Len returns the number of parameters in the sequence.
115// This will return the number of parameters in the sequence, excluding any
116// sub-parameters.
117func Len(params []int) int {
118	var n int
119	for i := range params {
120		if !HasMore(params, i) {
121			n++
122		}
123	}
124	return n
125}
126
127// Range iterates over the parameters of the sequence and calls the given
128// function for each parameter.
129// The function should return false to stop the iteration.
130func Range(params []int, fn func(i int, param int, hasMore bool) bool) {
131	for i := range params {
132		if !fn(i, Param(params, i), HasMore(params, i)) {
133			break
134		}
135	}
136}