Ejemplo n.º 1
0
        // 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);
                }
            }
        }
Ejemplo n.º 2
0
        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);
        }