123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- using System;
- using System.IO;
- using System.Text;
- namespace Google.ProtocolBuffers.Serialization.Http
- {
- /// <summary>
- /// Allows reading messages from a name/value dictionary
- /// </summary>
- public class FormUrlEncodedReader : AbstractTextReader
- {
- private readonly TextReader _input;
- private string _fieldName, _fieldValue;
- private bool _ready;
- /// <summary>
- /// Creates a dictionary reader from an enumeration of KeyValuePair data, like an IDictionary
- /// </summary>
- FormUrlEncodedReader(TextReader input)
- {
- _input = input;
- int ch = input.Peek();
- if (ch == '?')
- {
- input.Read();
- }
- _ready = ReadNext();
- }
- #region CreateInstance overloads
- /// <summary>
- /// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
- /// </summary>
- public static FormUrlEncodedReader CreateInstance(Stream stream)
- {
- return new FormUrlEncodedReader(new StreamReader(stream, Encoding.UTF8, false));
- }
- /// <summary>
- /// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
- /// </summary>
- public static FormUrlEncodedReader CreateInstance(byte[] bytes)
- {
- return new FormUrlEncodedReader(new StreamReader(new MemoryStream(bytes, false), Encoding.UTF8, false));
- }
- /// <summary>
- /// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
- /// </summary>
- public static FormUrlEncodedReader CreateInstance(string text)
- {
- return new FormUrlEncodedReader(new StringReader(text));
- }
- /// <summary>
- /// Constructs a FormUrlEncodedReader to parse form data, or url query text into a message.
- /// </summary>
- public static FormUrlEncodedReader CreateInstance(TextReader input)
- {
- return new FormUrlEncodedReader(input);
- }
- #endregion
- private bool ReadNext()
- {
- StringBuilder field = new StringBuilder(32);
- StringBuilder value = new StringBuilder(64);
- int ch;
- while (-1 != (ch = _input.Read()) && ch != '=' && ch != '&')
- {
- field.Append((char)ch);
- }
- if (ch != -1 && ch != '&')
- {
- while (-1 != (ch = _input.Read()) && ch != '&')
- {
- value.Append((char)ch);
- }
- }
- _fieldName = field.ToString();
- _fieldValue = Uri.UnescapeDataString(value.Replace('+', ' ').ToString());
-
- return !String.IsNullOrEmpty(_fieldName);
- }
- /// <summary>
- /// No-op
- /// </summary>
- public override void ReadMessageStart()
- { }
- /// <summary>
- /// No-op
- /// </summary>
- public override void ReadMessageEnd()
- { }
- /// <summary>
- /// Merges the contents of stream into the provided message builder
- /// </summary>
- public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
- {
- builder.WeakMergeFrom(this, registry);
- return builder;
- }
- /// <summary>
- /// Causes the reader to skip past this field
- /// </summary>
- protected override void Skip()
- {
- _ready = ReadNext();
- }
- /// <summary>
- /// Peeks at the next field in the input stream and returns what information is available.
- /// </summary>
- /// <remarks>
- /// This may be called multiple times without actually reading the field. Only after the field
- /// is either read, or skipped, should PeekNext return a different value.
- /// </remarks>
- protected override bool PeekNext(out string field)
- {
- field = _ready ? _fieldName : null;
- return field != null;
- }
- /// <summary>
- /// Returns true if it was able to read a String from the input
- /// </summary>
- protected override bool ReadAsText(ref string value, Type typeInfo)
- {
- if (_ready)
- {
- value = _fieldValue;
- _ready = ReadNext();
- return true;
- }
- return false;
- }
- /// <summary>
- /// It's unlikely this will work for anything but text data as bytes UTF8 are transformed to text and back to bytes
- /// </summary>
- protected override ByteString DecodeBytes(string bytes)
- { return ByteString.CopyFromUtf8(bytes); }
- /// <summary>
- /// Not Supported
- /// </summary>
- public override bool ReadGroup(IBuilderLite value, ExtensionRegistry registry)
- { throw new NotSupportedException(); }
- /// <summary>
- /// Not Supported
- /// </summary>
- protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
- { throw new NotSupportedException(); }
- }
- }
|