|  |  |  |  | using System; | 
					
						
							|  |  |  |  | using System.Collections.Generic; | 
					
						
							|  |  |  |  | using System.Linq; | 
					
						
							|  |  |  |  | using System.Text; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | namespace BestHTTP.Extensions | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     /// <summary> | 
					
						
							|  |  |  |  |     /// Used in string parsers. Its Value is optional. | 
					
						
							|  |  |  |  |     /// </summary> | 
					
						
							|  |  |  |  |     public sealed class HeaderValue | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         #region Public Properties | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public string Key { get; set; } | 
					
						
							|  |  |  |  |         public string Value { get; set; } | 
					
						
							|  |  |  |  |         public List<HeaderValue> Options { get; set; } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public bool HasValue { get { return !string.IsNullOrEmpty(this.Value); } } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #endregion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #region Constructors | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public HeaderValue() | 
					
						
							|  |  |  |  |         { } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public HeaderValue(string key) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             this.Key = key; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #endregion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #region Public Helper Functions | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public void Parse(string headerStr, ref int pos) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             ParseImplementation(headerStr, ref pos, true); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public bool TryGetOption(string key, out HeaderValue option) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             option = null; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             if (Options == null || Options.Count == 0) | 
					
						
							|  |  |  |  |                 return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             for (int i = 0; i < Options.Count; ++i) | 
					
						
							|  |  |  |  |                 if (String.Equals(Options[i].Key, key, StringComparison.OrdinalIgnoreCase)) | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                     option = Options[i]; | 
					
						
							|  |  |  |  |                     return true; | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             return false; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #endregion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #region Private Helper Functions | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         private void ParseImplementation(string headerStr, ref int pos, bool isOptionIsAnOption) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             string key = headerStr.Read(ref pos, (ch) => ch != ';' && ch != '=' && ch != ',', true); | 
					
						
							|  |  |  |  |             this.Key = key; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             char? skippedChar = headerStr.Peek(pos - 1); | 
					
						
							|  |  |  |  |             bool isValue = skippedChar == '='; | 
					
						
							|  |  |  |  |             bool isOption = isOptionIsAnOption && skippedChar == ';'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             while (skippedChar != null && isValue || isOption) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 if (isValue) | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                     string value = headerStr.ReadPossibleQuotedText(ref pos); | 
					
						
							|  |  |  |  |                     this.Value = value; | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |                 else if (isOption) | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                     HeaderValue option = new HeaderValue(); | 
					
						
							|  |  |  |  |                     option.ParseImplementation(headerStr, ref pos, false); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     if (this.Options == null) | 
					
						
							|  |  |  |  |                         this.Options = new List<HeaderValue>(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     this.Options.Add(option); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 if (!isOptionIsAnOption) | 
					
						
							|  |  |  |  |                     return; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 skippedChar = headerStr.Peek(pos - 1); | 
					
						
							|  |  |  |  |                 isValue = skippedChar == '='; | 
					
						
							|  |  |  |  |                 isOption = isOptionIsAnOption && skippedChar == ';'; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #endregion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #region Overrides | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public override string ToString() | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             if (!string.IsNullOrEmpty(Value)) | 
					
						
							|  |  |  |  |                 return String.Concat(Key, '=', Value); | 
					
						
							|  |  |  |  |             else | 
					
						
							|  |  |  |  |                 return Key; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #endregion | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } |