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}