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