cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.18.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/parser/read.go

180lines · 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 if hasComment(line, "ignore/file") {
60 return skipFile, true
61 } else if hasComment(line, "ignore/line") {
62 return skipCurrentLine, true
63 } else if hasComment(line, "ignore/next-line") {
64 return skipNextLine, true
65 } else if hasComment(line, "ignore/begin") {
66 return skipBegin, true
67 } else if hasComment(line, "ignore/end") {
68 return skipEnd, true
69 }
70 return skipNone, false
71}
72
73func ReadContent(r io.Reader) (out []byte, err error) {
74 reader := bufio.NewReader(r)
75 var line string
76 var found bool
77 var skip skipMode
78
79 var skipNext bool
80 var autoReset bool
81 var skipAll bool
82 var inBegin bool
83 for {
84 line, err = reader.ReadString('\n')
85 if err != nil && !errors.Is(err, io.EOF) {
86 break
87 }
88
89 if skipAll {
90 out = append(out, []byte(emptyLine(line))...)
91 } else {
92 skip, found = parseSkipComment(line)
93 if found {
94 switch skip {
95 case skipFile:
96 out = append(out, []byte(emptyLine(line))...)
97 skipNext = true
98 autoReset = false
99 skipAll = true
100 case skipCurrentLine:
101 out = append(out, []byte(emptyLine(line))...)
102 if !inBegin {
103 skipNext = false
104 autoReset = true
105 }
106 case skipNextLine:
107 out = append(out, []byte(line)...)
108 skipNext = true
109 autoReset = true
110 case skipBegin:
111 out = append(out, []byte(line)...)
112 skipNext = true
113 autoReset = false
114 inBegin = true
115 case skipEnd:
116 out = append(out, []byte(line)...)
117 skipNext = false
118 autoReset = true
119 inBegin = false
120 }
121 } else if skipNext {
122 out = append(out, []byte(emptyLine(line))...)
123 if autoReset {
124 skipNext = false
125 }
126 } else {
127 out = append(out, []byte(line)...)
128 }
129 }
130
131 if err != nil {
132 break
133 }
134 }
135
136 if !errors.Is(err, io.EOF) {
137 return nil, err
138 }
139
140 return out, nil
141}
142
143type Comment struct {
144 Key string
145 Value string
146}
147
148func (c Comment) String() string {
149 return c.Key + " " + c.Value
150}
151
152func GetComment(line string, comment ...string) (s Comment, ok bool) {
153 sc := bufio.NewScanner(strings.NewReader(line))
154 for sc.Scan() {
155 elems := strings.Split(sc.Text(), "#")
156 lastComment := elems[len(elems)-1]
157 parts := strings.Split(removeRedundantSpaces(lastComment), " ")
158 if len(parts) < 2 {
159 continue
160 }
161 keys := make([]string, 0, len(parts))
162 values := make([]string, 0, len(parts))
163 if parts[0] == "pint" && len(parts) >= len(comment)+1 {
164 for i, c := range comment {
165 if parts[i+1] != c {
166 goto NEXT
167 }
168 keys = append(keys, parts[i+1])
169 }
170 for i := len(comment) + 1; i < len(parts); i++ {
171 values = append(values, parts[i])
172 }
173 ok = true
174 s.Key = strings.Join(keys, " ")
175 s.Value = strings.Join(values, " ")
176 }
177 NEXT:
178 }
179 return
180}
181