PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/WCFWebApi/src/System.Net.Http/System/Net/Http/Headers/EntityTagHeaderValue.cs

#
C# | 200 lines | 162 code | 29 blank | 9 comment | 32 complexity | 7a4a5b48675b9b3fd8eac8cec271bf2f MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0
  1. using System.Diagnostics.Contracts;
  2. namespace System.Net.Http.Headers
  3. {
  4. public class EntityTagHeaderValue : ICloneable
  5. {
  6. private static EntityTagHeaderValue any;
  7. private string tag;
  8. private bool isWeak;
  9. public string Tag
  10. {
  11. get { return tag; }
  12. }
  13. public bool IsWeak
  14. {
  15. get { return isWeak; }
  16. }
  17. public static EntityTagHeaderValue Any
  18. {
  19. get
  20. {
  21. if (any == null)
  22. {
  23. any = new EntityTagHeaderValue();
  24. any.tag = "*";
  25. any.isWeak = false;
  26. }
  27. return any;
  28. }
  29. }
  30. public EntityTagHeaderValue(string tag)
  31. : this(tag, false)
  32. {
  33. }
  34. public EntityTagHeaderValue(string tag, bool isWeak)
  35. {
  36. if (string.IsNullOrEmpty(tag))
  37. {
  38. throw new ArgumentException(SR.net_http_argument_empty_string, "tag");
  39. }
  40. int length = 0;
  41. if ((HttpRuleParser.GetQuotedStringLength(tag, 0, out length) != HttpParseResult.Parsed) ||
  42. (length != tag.Length))
  43. {
  44. // Note that we don't allow 'W/' prefixes for weak ETags in the 'tag' parameter. If the user wants to
  45. // add a weak ETag, he can set 'isWeak' to true.
  46. throw new FormatException(SR.net_http_headers_invalid_etag_name);
  47. }
  48. this.tag = tag;
  49. this.isWeak = isWeak;
  50. }
  51. private EntityTagHeaderValue(EntityTagHeaderValue source)
  52. {
  53. Contract.Requires(source != null);
  54. this.tag = source.tag;
  55. this.isWeak = source.isWeak;
  56. }
  57. private EntityTagHeaderValue()
  58. {
  59. }
  60. public override string ToString()
  61. {
  62. if (isWeak)
  63. {
  64. return "W/" + tag;
  65. }
  66. return tag;
  67. }
  68. public override bool Equals(object obj)
  69. {
  70. EntityTagHeaderValue other = obj as EntityTagHeaderValue;
  71. if (other == null)
  72. {
  73. return false;
  74. }
  75. // Since the tag is a quoted-string we treat it case-sensitive.
  76. return ((isWeak == other.isWeak) && (string.CompareOrdinal(tag, other.tag) == 0));
  77. }
  78. public override int GetHashCode()
  79. {
  80. // Since the tag is a quoted-string we treat it case-sensitive.
  81. return tag.GetHashCode() ^ isWeak.GetHashCode();
  82. }
  83. public static EntityTagHeaderValue Parse(string input)
  84. {
  85. int index = 0;
  86. return (EntityTagHeaderValue)GenericHeaderParser.SingleValueEntityTagParser.ParseValue(
  87. input, null, ref index);
  88. }
  89. public static bool TryParse(string input, out EntityTagHeaderValue parsedValue)
  90. {
  91. int index = 0;
  92. object output;
  93. parsedValue = null;
  94. if (GenericHeaderParser.SingleValueEntityTagParser.TryParseValue(input, null, ref index, out output))
  95. {
  96. parsedValue = (EntityTagHeaderValue)output;
  97. return true;
  98. }
  99. return false;
  100. }
  101. internal static int GetEntityTagLength(string input, int startIndex, out EntityTagHeaderValue parsedValue)
  102. {
  103. Contract.Requires(startIndex >= 0);
  104. parsedValue = null;
  105. if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
  106. {
  107. return 0;
  108. }
  109. // Caller must remove leading whitespaces. If not, we'll return 0.
  110. bool isWeak = false;
  111. int current = startIndex;
  112. char firstChar = input[startIndex];
  113. if (firstChar == '*')
  114. {
  115. // We have '*' value, indicating "any" ETag.
  116. parsedValue = Any;
  117. current++;
  118. }
  119. else
  120. {
  121. // The RFC defines 'W/' as prefix, but we'll be flexible and also accept lower-case 'w'.
  122. if ((firstChar == 'W') || (firstChar == 'w'))
  123. {
  124. current++;
  125. // We need at least 3 more chars: the '/' character followed by two quotes.
  126. if ((current + 2 >= input.Length) || (input[current] != '/'))
  127. {
  128. return 0;
  129. }
  130. isWeak = true;
  131. current++; // we have a weak-entity tag.
  132. current = current + HttpRuleParser.GetWhitespaceLength(input, current);
  133. }
  134. int tagStartIndex = current;
  135. int tagLength = 0;
  136. if (HttpRuleParser.GetQuotedStringLength(input, current, out tagLength) != HttpParseResult.Parsed)
  137. {
  138. return 0;
  139. }
  140. parsedValue = new EntityTagHeaderValue();
  141. if (tagLength == input.Length)
  142. {
  143. // Most of the time we'll have strong ETags without leading/trailing whitespaces.
  144. Contract.Assert(startIndex == 0);
  145. Contract.Assert(!isWeak);
  146. parsedValue.tag = input;
  147. parsedValue.isWeak = false;
  148. }
  149. else
  150. {
  151. parsedValue.tag = input.Substring(tagStartIndex, tagLength);
  152. parsedValue.isWeak = isWeak;
  153. }
  154. current = current + tagLength;
  155. }
  156. current = current + HttpRuleParser.GetWhitespaceLength(input, current);
  157. return current - startIndex;
  158. }
  159. object ICloneable.Clone()
  160. {
  161. if (this == any)
  162. {
  163. return any;
  164. }
  165. else
  166. {
  167. return new EntityTagHeaderValue(this);
  168. }
  169. }
  170. }
  171. }