Merge pull request #820 from brendanzagaeski/master
[mono.git] / mcs / class / System.Net.Http / System.Net.Http.Headers / TransferCodingHeaderValue.cs
1 //
2 // TransferCodingHeaderValue.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.Collections.Generic;
30
31 namespace System.Net.Http.Headers
32 {
33         public class TransferCodingHeaderValue : ICloneable
34         {
35                 internal string value;
36                 internal List<NameValueHeaderValue> parameters;
37
38                 public TransferCodingHeaderValue (string value)
39                 {
40                         Parser.Token.Check (value);
41                         this.value = value;
42                 }
43
44                 protected TransferCodingHeaderValue (TransferCodingHeaderValue source)
45                 {
46                         this.value = source.value;
47                         if (source.parameters != null) {
48                                 foreach (var p in source.parameters) {
49                                         Parameters.Add (new NameValueHeaderValue (p));
50                                 }
51                         }
52                 }
53
54                 internal TransferCodingHeaderValue ()
55                 {
56                 }
57
58                 public ICollection<NameValueHeaderValue> Parameters {
59                         get {
60                                 return parameters ?? (parameters = new List<NameValueHeaderValue> ());
61                         }
62                 }
63
64                 public string Value {
65                         get {
66                                 return value;
67                         }
68                 }
69
70                 object ICloneable.Clone ()
71                 {
72                         return new TransferCodingHeaderValue (this);
73                 }
74
75                 public override bool Equals (object obj)
76                 {
77                         var fchv = obj as TransferCodingHeaderValue;
78                         return fchv != null &&
79                                 string.Equals (value, fchv.value, StringComparison.OrdinalIgnoreCase) &&
80                                 parameters.SequenceEqual (fchv.parameters);
81                 }
82
83                 public override int GetHashCode ()
84                 {
85                         var hc = value.ToLowerInvariant ().GetHashCode ();
86                         if (parameters != null)
87                                 hc ^= HashCodeCalculator.Calculate (parameters);
88
89                         return hc;
90                 }
91
92                 public static TransferCodingHeaderValue Parse (string input)
93                 {
94                         TransferCodingHeaderValue value;
95
96                         if (TryParse (input, out value))
97                                 return value;
98
99                         throw new FormatException (input);
100                 }
101
102                 public override string ToString ()
103                 {
104                         return value + CollectionExtensions.ToString (parameters);
105                 }
106
107                 public static bool TryParse (string input, out TransferCodingHeaderValue parsedValue)
108                 {
109                         var lexer = new Lexer (input);
110                         Token token;
111                         if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
112                                 return true;
113
114                         parsedValue = null;
115                         return false;
116                 }
117
118                 internal static bool TryParse (string input, int minimalCount, out List<TransferCodingHeaderValue> result)
119                 {
120                         return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
121                 }       
122
123                 static bool TryParseElement (Lexer lexer, out TransferCodingHeaderValue parsedValue, out Token t)
124                 {
125                         parsedValue = null;
126
127                         t = lexer.Scan ();
128                         if (t != Token.Type.Token)
129                                 return false;
130
131                         var result = new TransferCodingHeaderValue ();
132                         result.value = lexer.GetStringValue (t);
133
134                         t = lexer.Scan ();
135
136                         // Parameters parsing
137                         if (t == Token.Type.SeparatorSemicolon && (!NameValueHeaderValue.TryParseParameters (lexer, out result.parameters, out t) || t != Token.Type.End))
138                                 return false;
139
140                         parsedValue = result;
141                         return true;
142                 }
143         }
144 }