internal static int GetEntityTagLength(string input, int startIndex, out EntityTagHeaderValue parsedValue) { Contract.Requires(startIndex >= 0); parsedValue = null; if (string.IsNullOrEmpty(input) || (startIndex >= input.Length)) { return(0); } // Caller must remove leading whitespace. If not, we'll return 0. bool isWeak = false; int current = startIndex; char firstChar = input[startIndex]; if (firstChar == '*') { // We have '*' value, indicating "any" ETag. parsedValue = Any; current++; } else { // The RFC defines 'W/' as prefix, but we'll be flexible and also accept lower-case 'w'. if ((firstChar == 'W') || (firstChar == 'w')) { current++; // We need at least 3 more chars: the '/' character followed by two quotes. if ((current + 2 >= input.Length) || (input[current] != '/')) { return(0); } isWeak = true; current++; // we have a weak-entity tag. current = current + HttpRuleParser.GetWhitespaceLength(input, current); } int tagStartIndex = current; int tagLength = 0; if (HttpRuleParser.GetQuotedStringLength(input, current, out tagLength) != HttpParseResult.Parsed) { return(0); } parsedValue = new EntityTagHeaderValue(); if (tagLength == input.Length) { // Most of the time we'll have strong ETags without leading/trailing whitespace. Debug.Assert(startIndex == 0); Debug.Assert(!isWeak); parsedValue._tag = input; parsedValue._isWeak = false; } else { parsedValue._tag = input.Substring(tagStartIndex, tagLength); parsedValue._isWeak = isWeak; } current = current + tagLength; } current = current + HttpRuleParser.GetWhitespaceLength(input, current); return(current - startIndex); }