func quotedCommaSplit()

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
}