-
Notifications
You must be signed in to change notification settings - Fork 0
/
lex.go
93 lines (83 loc) · 2.06 KB
/
lex.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cacheobject
// This file deals with lexical matters of HTTP
func isSeparator(c byte) bool {
switch c {
case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
return true
}
return false
}
func isCtl(c byte) bool { return (0 <= c && c <= 31) || c == 127 }
func isChar(c byte) bool { return 0 <= c && c <= 127 }
func isAnyText(c byte) bool { return !isCtl(c) }
func isQdText(c byte) bool { return isAnyText(c) && c != '"' }
func isToken(c byte) bool { return isChar(c) && !isCtl(c) && !isSeparator(c) }
// Valid escaped sequences are not specified in RFC 2616, so for now, we assume
// that they coincide with the common sense ones used by GO. Malformed
// characters should probably not be treated as errors by a robust (forgiving)
// parser, so we replace them with the '?' character.
func httpUnquotePair(b byte) byte {
// skip the first byte, which should always be '\'
switch b {
case 'a':
return '\a'
case 'b':
return '\b'
case 'f':
return '\f'
case 'n':
return '\n'
case 'r':
return '\r'
case 't':
return '\t'
case 'v':
return '\v'
case '\\':
return '\\'
case '\'':
return '\''
case '"':
return '"'
}
return '?'
}
// raw must begin with a valid quoted string. Only the first quoted string is
// parsed and is unquoted in result. eaten is the number of bytes parsed, or -1
// upon failure.
func httpUnquote(raw string) (eaten int, result string) {
buf := make([]byte, len(raw))
if raw[0] != '"' {
return -1, ""
}
eaten = 1
j := 0 // # of bytes written in buf
for i := 1; i < len(raw); i++ {
switch b := raw[i]; b {
case '"':
eaten++
buf = buf[0:j]
return i + 1, string(buf)
case '\\':
if len(raw) < i+2 {
return -1, ""
}
buf[j] = httpUnquotePair(raw[i+1])
eaten += 2
j++
i++
default:
if isQdText(b) {
buf[j] = b
} else {
buf[j] = '?'
}
eaten++
j++
}
}
return -1, ""
}