first commit
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package imap
|
||||
|
||||
import "strings"
|
||||
|
||||
// tokenize splits an IMAP command line into space-separated tokens, treating
|
||||
// "quoted strings" and (parenthesized lists) as single tokens (lists keep
|
||||
// their outer parens so command handlers can recognize and further split
|
||||
// them). Literal syntax ({n}\r\n<bytes>) is not handled here — see session.go's
|
||||
// readCommand, which handles literals as a pre-pass before tokenizing since
|
||||
// they require reading raw bytes off the connection, not just string scanning.
|
||||
func tokenize(line string) []string {
|
||||
var tokens []string
|
||||
i, n := 0, len(line)
|
||||
|
||||
for i < n {
|
||||
for i < n && (line[i] == ' ' || line[i] == '\t') {
|
||||
i++
|
||||
}
|
||||
if i >= n {
|
||||
break
|
||||
}
|
||||
|
||||
switch line[i] {
|
||||
case '"':
|
||||
j := i + 1
|
||||
var sb strings.Builder
|
||||
for j < n && line[j] != '"' {
|
||||
if line[j] == '\\' && j+1 < n {
|
||||
j++
|
||||
}
|
||||
sb.WriteByte(line[j])
|
||||
j++
|
||||
}
|
||||
tokens = append(tokens, sb.String())
|
||||
i = j + 1
|
||||
|
||||
case '(':
|
||||
depth := 1
|
||||
j := i + 1
|
||||
for j < n && depth > 0 {
|
||||
switch line[j] {
|
||||
case '(':
|
||||
depth++
|
||||
case ')':
|
||||
depth--
|
||||
}
|
||||
j++
|
||||
}
|
||||
tokens = append(tokens, line[i:j])
|
||||
i = j
|
||||
|
||||
default:
|
||||
j := i
|
||||
for j < n && line[j] != ' ' && line[j] != '\t' {
|
||||
j++
|
||||
}
|
||||
tokens = append(tokens, line[i:j])
|
||||
i = j
|
||||
}
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
// splitList takes a token like "(FLAGS UID)" and returns its inner
|
||||
// space-separated items — used by FETCH/STORE argument parsing.
|
||||
func splitList(token string) []string {
|
||||
inner := strings.TrimPrefix(token, "(")
|
||||
inner = strings.TrimSuffix(inner, ")")
|
||||
if inner == "" {
|
||||
return nil
|
||||
}
|
||||
return tokenize(inner)
|
||||
}
|
||||
|
||||
func isList(token string) bool {
|
||||
return strings.HasPrefix(token, "(") && strings.HasSuffix(token, ")")
|
||||
}
|
||||
Reference in New Issue
Block a user