cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.28.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/parser/read.go

185lines · modecode

1package parser
2
3import (
4 "bufio"
5 "errors"
6 "io"
7 "strings"
8)
9
10type skipMode int
11
12const (
13 skipNone skipMode = iota
14 skipNextLine
15 skipBegin
16 skipEnd
17 skipCurrentLine
18 skipFile
19)
20
21func removeRedundantSpaces(line string) string {
22 return strings.Join(strings.Fields(line), " ")
23}
24
25func emptyLine(line string) (emptied string) {
26 preComment := strings.TrimSuffix(line, "\n")
27 var comment string
28 if commentStart := strings.IndexRune(line, '#'); commentStart >= 0 {
29 comment = preComment[commentStart:]
30 preComment = preComment[:commentStart]
31 }
32
33 emptied = strings.Repeat(" ", len(preComment)) + comment
34
35 if strings.HasSuffix(line, "\n") {
36 emptied += "\n"
37 }
38
39 return
40}
41
42func hasComment(line, comment string) bool {
43 sc := bufio.NewScanner(strings.NewReader(line))
44 for sc.Scan() {
45 elems := strings.Split(sc.Text(), "#")
46 lastComment := elems[len(elems)-1]
47 parts := strings.SplitN(removeRedundantSpaces(lastComment), " ", 2)
48 if len(parts) < 2 {
49 continue
50 }
51 if parts[0] == "pint" && parts[1] == comment {
52 return true
53 }
54 }
55 return false
56}
57
58func parseSkipComment(line string) (skipMode, bool) {
59 switch {
60 case hasComment(line, "ignore/file"):
61 return skipFile, true
62 case hasComment(line, "ignore/line"):
63 return skipCurrentLine, true
64 case hasComment(line, "ignore/next-line"):
65 return skipNextLine, true
66 case hasComment(line, "ignore/begin"):
67 return skipBegin, true
68 case hasComment(line, "ignore/end"):
69 return skipEnd, true
70 default:
71 return skipNone, false
72 }
73}
74
75func ReadContent(r io.Reader) (out []byte, err error) {
76 reader := bufio.NewReader(r)
77 var line string
78 var found bool
79 var skip skipMode
80
81 var skipNext bool
82 var autoReset bool
83 var skipAll bool
84 var inBegin bool
85 for {
86 line, err = reader.ReadString('\n')
87 if err != nil && !errors.Is(err, io.EOF) {
88 break
89 }
90
91 if skipAll {
92 out = append(out, []byte(emptyLine(line))...)
93 } else {
94 skip, found = parseSkipComment(line)
95 switch {
96 case found:
97 switch skip {
98 case skipNone:
99 // no-op
100 case skipFile:
101 out = append(out, []byte(emptyLine(line))...)
102 skipNext = true
103 autoReset = false
104 skipAll = true
105 case skipCurrentLine:
106 out = append(out, []byte(emptyLine(line))...)
107 if !inBegin {
108 skipNext = false
109 autoReset = true
110 }
111 case skipNextLine:
112 out = append(out, []byte(line)...)
113 skipNext = true
114 autoReset = true
115 case skipBegin:
116 out = append(out, []byte(line)...)
117 skipNext = true
118 autoReset = false
119 inBegin = true
120 case skipEnd:
121 out = append(out, []byte(line)...)
122 skipNext = false
123 autoReset = true
124 inBegin = false
125 }
126 case skipNext:
127 out = append(out, []byte(emptyLine(line))...)
128 if autoReset {
129 skipNext = false
130 }
131 default:
132 out = append(out, []byte(line)...)
133 }
134 }
135
136 if err != nil {
137 break
138 }
139 }
140
141 if !errors.Is(err, io.EOF) {
142 return nil, err
143 }
144
145 return out, nil
146}
147
148type Comment struct {
149 Key string
150 Value string
151}
152
153func (c Comment) String() string {
154 return c.Key + " " + c.Value
155}
156
157func GetComment(line string, comment ...string) (s Comment, ok bool) {
158 sc := bufio.NewScanner(strings.NewReader(line))
159 for sc.Scan() {
160 elems := strings.Split(sc.Text(), "#")
161 lastComment := elems[len(elems)-1]
162 parts := strings.Split(removeRedundantSpaces(lastComment), " ")
163 if len(parts) < 2 {
164 continue
165 }
166 keys := make([]string, 0, len(parts))
167 values := make([]string, 0, len(parts))
168 if parts[0] == "pint" && len(parts) >= len(comment)+1 {
169 for i, c := range comment {
170 if parts[i+1] != c {
171 goto NEXT
172 }
173 keys = append(keys, parts[i+1])
174 }
175 for i := len(comment) + 1; i < len(parts); i++ {
176 values = append(values, parts[i])
177 }
178 ok = true
179 s.Key = strings.Join(keys, " ")
180 s.Value = strings.Join(values, " ")
181 }
182 NEXT:
183 }
184 return
185}
186