in transport/http/headerlist.go [31:119]
func quotedCommaSplit(v string) (parts []string, err error) {
v = strings.TrimSpace(v)
expectMore := true
for i := 0; i < len(v); i++ {
if unicode.IsSpace(rune(v[i])) {
continue
}
expectMore = false
// leading space in part is ignored.
// Start of value must be non-space, or quote.
//
// - If quote, enter quoted mode, find next non-escaped quote to
// terminate the value.
// - Otherwise, find next comma to terminate value.
remaining := v[i:]
var value string
var valueLen int
if remaining[0] == '"' {
//------------------------------
// Quoted value
//------------------------------
var j int
var skipQuote bool
for j += 1; j < len(remaining); j++ {
if remaining[j] == '\\' || (remaining[j] != '\\' && skipQuote) {
skipQuote = !skipQuote
continue
}
if remaining[j] == '"' {
break
}
}
if j == len(remaining) || j == 1 {
return nil, fmt.Errorf("value %v missing closing double quote",
remaining)
}
valueLen = j + 1
tail := remaining[valueLen:]
var k int
for ; k < len(tail); k++ {
if !unicode.IsSpace(rune(tail[k])) && tail[k] != ',' {
return nil, fmt.Errorf("value %v has non-space trailing characters",
remaining)
}
if tail[k] == ',' {
expectMore = true
break
}
}
value = remaining[:valueLen]
value, err = strconv.Unquote(value)
if err != nil {
return nil, fmt.Errorf("failed to unquote value %v, %w", value, err)
}
// Pad valueLen to include trailing space(s) so `i` is updated correctly.
valueLen += k
} else {
//------------------------------
// Unquoted value
//------------------------------
// Index of the next comma is the length of the value, or end of string.
valueLen = strings.Index(remaining, ",")
if valueLen != -1 {
expectMore = true
} else {
valueLen = len(remaining)
}
value = strings.TrimSpace(remaining[:valueLen])
}
i += valueLen
parts = append(parts, value)
}
if expectMore {
parts = append(parts, "")
}
return parts, nil
}