Merge branch 'BigIntegerParse'
[mono.git] / mcs / class / System.Net.Http / System.Net.Http.Headers / StringWithQualityHeaderValue.cs
1 //
2 // StringWithQualityHeaderValue.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.Globalization;
30 using System.Collections.Generic;
31
32 namespace System.Net.Http.Headers
33 {
34         public class StringWithQualityHeaderValue : ICloneable
35         {
36                 public StringWithQualityHeaderValue (string value)
37                 {
38                         Parser.Token.Check (value);
39                         this.Value = value;
40                 }
41
42                 public StringWithQualityHeaderValue (string value, double quality)
43                         : this (value)
44                 {
45                         if (quality < 0 || quality > 1)
46                                 throw new ArgumentOutOfRangeException ("quality");
47
48                         Quality = quality;
49                 }
50
51                 private StringWithQualityHeaderValue ()
52                 {
53                 }
54
55                 public double? Quality { get; private set; }
56                 public string Value { get; private set; }
57
58                 object ICloneable.Clone ()
59                 {
60                         return MemberwiseClone ();
61                 }
62
63                 public override bool Equals (object obj)
64                 {
65                         var source = obj as StringWithQualityHeaderValue;
66                         return source != null &&
67                                 string.Equals (source.Value, Value, StringComparison.OrdinalIgnoreCase) &&
68                                 source.Quality == Quality;
69                 }
70
71                 public override int GetHashCode ()
72                 {
73                         return Value.ToLowerInvariant ().GetHashCode () ^ Quality.GetHashCode ();
74                 }
75
76                 public static StringWithQualityHeaderValue Parse (string input)
77                 {
78                         StringWithQualityHeaderValue value;
79                         if (TryParse (input, out value))
80                                 return value;
81
82                         throw new FormatException (input);
83                 }
84                 
85                 public static bool TryParse (string input, out StringWithQualityHeaderValue parsedValue)
86                 {
87                         var lexer = new Lexer (input);
88                         Token token;
89                         if (TryParseElement (lexer, out parsedValue, out token) && token == Token.Type.End)
90                                 return true;
91
92                         parsedValue = null;
93                         return false;
94                 }
95
96                 internal static bool TryParse (string input, int minimalCount, out List<StringWithQualityHeaderValue> result)
97                 {
98                         return CollectionParser.TryParse (input, minimalCount, TryParseElement, out result);
99                 }
100
101                 static bool TryParseElement (Lexer lexer, out StringWithQualityHeaderValue parsedValue, out Token t)
102                 {
103                         parsedValue = null;
104                         t = lexer.Scan ();
105                         if (t != Token.Type.Token)
106                                 return false;
107
108                         var value = new StringWithQualityHeaderValue ();
109                         value.Value = lexer.GetStringValue (t);
110
111                         t = lexer.Scan ();
112                         if (t == Token.Type.SeparatorSemicolon) {
113                                 t = lexer.Scan ();
114                                 if (t != Token.Type.Token)
115                                         return false;
116
117                                 var s = lexer.GetStringValue (t);
118                                 if (s != "q" && s != "Q")
119                                         return false;
120
121                                 t = lexer.Scan ();
122                                 if (t != Token.Type.SeparatorEqual)
123                                         return false;
124
125                                 t = lexer.Scan ();
126
127                                 double d;
128                                 if (!lexer.TryGetDoubleValue (t, out d))
129                                         return false;
130
131                                 if (d > 1)
132                                         return false;
133
134                                 value.Quality = d;
135
136                                 t = lexer.Scan ();
137                         }
138
139                         parsedValue = value;
140                         return true;
141                 }
142
143                 public override string ToString ()
144                 {
145                         if (Quality != null)
146                                 return Value + "; q=" + Quality.Value.ToString ("0.0##", CultureInfo.InvariantCulture);
147
148                         return Value;
149                 }
150         }
151 }