// Returns the length of a range list. E.g. "1-2, 3-4, 5-6" adds 3 ranges to 'rangeCollection'. Note that empty // list segments are allowed, e.g. ",1-2, , 3-4,,". internal static int GetRangeItemListLength( StringSegment input, int startIndex, ICollection <RangeItemHeaderValue> rangeCollection) { Contract.Requires(rangeCollection != null); Contract.Requires(startIndex >= 0); Contract.Ensures((Contract.Result <int>() == 0) || (rangeCollection.Count > 0), "If we can parse the string, then we expect to have at least one range item."); if ((StringSegment.IsNullOrEmpty(input)) || (startIndex >= input.Length)) { return(0); } // Empty segments are allowed, so skip all delimiter-only segments (e.g. ", ,"). var separatorFound = false; var current = HeaderUtilities.GetNextNonEmptyOrWhitespaceIndex(input, startIndex, true, out separatorFound); // It's OK if we didn't find leading separator characters. Ignore 'separatorFound'. if (current == input.Length) { return(0); } RangeItemHeaderValue range = null; while (true) { var rangeLength = GetRangeItemLength(input, current, out range); if (rangeLength == 0) { return(0); } rangeCollection.Add(range); current = current + rangeLength; current = HeaderUtilities.GetNextNonEmptyOrWhitespaceIndex(input, current, true, out separatorFound); // If the string is not consumed, we must have a delimiter, otherwise the string is not a valid // range list. if ((current < input.Length) && !separatorFound) { return(0); } if (current == input.Length) { return(current - startIndex); } } }
public sealed override bool TryParseValue(StringSegment value, ref int index, out T parsedValue) { parsedValue = default(T); // If multiple values are supported (i.e. list of values), then accept an empty string: The header may // be added multiple times to the request/response message. E.g. // Accept: text/xml; q=1 // Accept: // Accept: text/plain; q=0.2 if (StringSegment.IsNullOrEmpty(value) || (index == value.Length)) { return(SupportsMultipleValues); } var current = HeaderUtilities.GetNextNonEmptyOrWhitespaceIndex(value, index, SupportsMultipleValues, out var separatorFound); if (separatorFound && !SupportsMultipleValues) { return(false); // leading separators not allowed if we don't support multiple values. } if (current == value.Length) { if (SupportsMultipleValues) { index = current; } return(SupportsMultipleValues); } var length = GetParsedValueLength(value, current, out var result); if (length == 0) { return(false); } current += length; current = HeaderUtilities.GetNextNonEmptyOrWhitespaceIndex(value, current, SupportsMultipleValues, out separatorFound); // If we support multiple values and we've not reached the end of the string, then we must have a separator. if ((separatorFound && !SupportsMultipleValues) || (!separatorFound && (current < value.Length))) { return(false); } index = current; parsedValue = result; return(true); }