Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / System.Net.Http / System.Net.Http.Headers / NameValueWithParametersHeaderValue.cs
1 //
2 // NameValueWithParametersHeaderValue.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 NameValueWithParametersHeaderValue : NameValueHeaderValue, ICloneable
34         {
35                 List<NameValueHeaderValue> parameters;
36
37                 public NameValueWithParametersHeaderValue (string name)
38                         : base (name)
39                 {
40                 }
41
42                 public NameValueWithParametersHeaderValue (string name, string value)
43                         : base (name, value)
44                 {
45                 }
46
47                 protected NameValueWithParametersHeaderValue (NameValueWithParametersHeaderValue source)
48                         : base (source)
49                 {
50                         if (source.parameters != null) {
51                                 foreach (var item in source.parameters)
52                                         Parameters.Add (item);
53                         }
54                 }
55
56                 private NameValueWithParametersHeaderValue ()
57                         : base ()
58                 {
59                 }
60
61                 public ICollection<NameValueHeaderValue> Parameters {
62                         get {
63                                 return parameters ?? (parameters = new List<NameValueHeaderValue> ());
64                         }
65                 }
66
67                 object ICloneable.Clone ()
68                 {
69                         return new NameValueWithParametersHeaderValue (this);
70                 }
71
72                 public override bool Equals (object obj)
73                 {
74                         var source = obj as NameValueWithParametersHeaderValue;
75                         if (source == null)
76                                 return false;
77
78                         return base.Equals (obj) && source.parameters.SequenceEqual (parameters);
79                 }
80
81                 public override int GetHashCode ()
82                 {
83                         return base.GetHashCode () ^ HashCodeCalculator.Calculate (parameters);
84                 }
85
86                 public static new NameValueWithParametersHeaderValue Parse (string input)
87                 {
88                         NameValueWithParametersHeaderValue value;
89                         if (TryParse (input, out value))
90                                 return value;
91
92                         throw new FormatException (input);
93                 }
94
95                 public override string ToString ()
96                 {
97                         if (parameters == null || parameters.Count == 0)
98                                 return base.ToString ();
99
100                         return base.ToString () + CollectionExtensions.ToString (parameters);
101                 }
102
103                 public static bool TryParse (string input, out NameValueWithParametersHeaderValue parsedValue)
104                 {
105                         var lexer = new Lexer (input);
106                         Token token;
107                         if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
108                                 return true;
109
110                         parsedValue = null;
111                         return false;
112                 }
113
114                 internal static bool TryParse (string input, int minimalCount, out List<NameValueWithParametersHeaderValue> result)
115                 {
116                         return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
117                 }
118
119                 static bool TryParseElement (Lexer lexer, out NameValueWithParametersHeaderValue parsedValue, out Token t)
120                 {
121                         parsedValue = null;
122
123                         t = lexer.Scan ();
124                         if (t != Token.Type.Token)
125                                 return false;
126
127                         parsedValue = new NameValueWithParametersHeaderValue () {
128                                 Name = lexer.GetStringValue (t),
129                         };
130
131                         t = lexer.Scan ();
132                         if (t == Token.Type.SeparatorEqual) {
133                                 t = lexer.Scan ();
134
135                                 if (t == Token.Type.Token || t == Token.Type.QuotedString) {
136                                         parsedValue.value = lexer.GetStringValue (t);
137                                         t = lexer.Scan ();
138                                 } else {
139                                         return false;
140                                 }
141                         }
142
143                         if (t == Token.Type.SeparatorSemicolon) {
144                                 List<NameValueHeaderValue> result;
145                                 if (!TryParseParameters (lexer,  out result, out t))
146                                         return false;
147
148                                 parsedValue.parameters = result;
149                         }
150
151                         return true;
152                 }
153         }
154 }