Return to Snippet

Revision: 29200
at July 12, 2011 00:27 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * BencodeDecoder.Decode("d8:Some Key10:Some Value13:Another Valuei42ee");
     * 
     * Feel free to use it.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bencoding
{
   	/// <summary>
	/// A class used for decoding Bencoding.
	/// </summary>
	public static class BencodeDecoder
	{
		/// <summary>
		/// Decodes the string.
		/// </summary>
		/// <param name="bencodedString">The bencoded string.</param>
		/// <returns>An array of root elements.</returns>
		public static BElement[] Decode(string bencodedString)
		{
			int index = 0;

			try
			{
				if (bencodedString == null) return null;

				List<BElement> rootElements = new List<BElement>();
				while (bencodedString.Length > index)
				{
					rootElements.Add(ReadElement(ref bencodedString, ref index));
				}

				return rootElements.ToArray();
			}
			catch (BencodingException) { throw; }
			catch (Exception e) { throw Error(e); }
		}

		private static BElement ReadElement(ref string bencodedString, ref int index)
		{
			switch (bencodedString[index])
			{
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9': return ReadString(ref bencodedString, ref index);
				case 'i': return ReadInteger(ref bencodedString, ref index);
				case 'l': return ReadList(ref bencodedString, ref index);
				case 'd': return ReadDictionary(ref bencodedString, ref index);
				default: throw Error();
			}
		}

		private static BDictionary ReadDictionary(ref string bencodedString, ref int index)
		{
			index++;
			BDictionary dict = new BDictionary();

			try
			{
				while (bencodedString[index] != 'e')
				{
					BString K = ReadString(ref bencodedString, ref index);
					BElement V = ReadElement(ref bencodedString, ref index);
					dict.Add(K, V);
				}
			}
			catch (BencodingException) { throw; }
			catch (Exception e) { throw Error(e); }

			index++;
			return dict;
		}

		private static BList ReadList(ref string bencodedString, ref int index)
		{
			index++;
			BList lst = new BList();

			try
			{
				while (bencodedString[index] != 'e')
				{
					lst.Add(ReadElement(ref bencodedString, ref index));
				}
			}
			catch (BencodingException) { throw; }
			catch (Exception e) { throw Error(e); }

			index++;
			return lst;
		}

		private static BInteger ReadInteger(ref string bencodedString, ref int index)
		{
			index++;

			int end = bencodedString.IndexOf('e', index);
			if (end == -1) throw Error();

			long integer;

			try
			{
				integer = Convert.ToInt64(bencodedString.Substring(index, end - index));
				index = end + 1;
			}
			catch (Exception e) { throw Error(e); }

			return new BInteger(integer);
		}

		private static BString ReadString(ref string bencodedString, ref int index)
		{
			int length, colon;

			try
			{
				colon = bencodedString.IndexOf(':', index);
				if (colon == -1) throw Error();
				length = Convert.ToInt32(bencodedString.Substring(index, colon - index));
			}
			catch (Exception e) { throw Error(e); }

			index = colon + 1;
			int tmpIndex = index;
			index += length;

			try
			{
				return new BString(bencodedString.Substring(tmpIndex, length));
			}
			catch (Exception e) { throw Error(e); }
		}

		private static Exception Error(Exception e)
		{
			return new BencodingException("Bencoded string invalid.", e);
		}

		private static Exception Error()
		{
			return new BencodingException("Bencoded string invalid.");
		}
	}

	/// <summary>
	/// An interface for bencoded elements.
	/// </summary>
	public interface BElement
	{
		/// <summary>
		/// Generates the bencoded equivalent of the element.
		/// </summary>
		/// <returns>The bencoded equivalent of the element.</returns>
		string ToBencodedString();

		/// <summary>
		/// Generates the bencoded equivalent of the element.
		/// </summary>
		/// <param name="u">The StringBuilder to append to.</param>
		/// <returns>The bencoded equivalent of the element.</returns>
		StringBuilder ToBencodedString(StringBuilder u);
	}

	/// <summary>
	/// A bencode integer.
	/// </summary>
	public class BInteger : BElement, IComparable<BInteger>
	{
		/// <summary>
		/// Allows you to set an integer to a BInteger.
		/// </summary>
		/// <param name="i">The integer.</param>
		/// <returns>The BInteger.</returns>
		public static implicit operator BInteger(int i)
		{
			return new BInteger(i);
		}

		/// <summary>
		/// The value of the bencoded integer.
		/// </summary>
		public long Value { get; set; }

		/// <summary>
		/// The main constructor.
		/// </summary>
		/// <param name="value">The value of the bencoded integer.</param>
		public BInteger(long value)
		{
			this.Value = value;
		}

		/// <summary>
		/// Generates the bencoded equivalent of the integer.
		/// </summary>
		/// <returns>The bencoded equivalent of the integer.</returns>
		public string ToBencodedString()
		{
			return this.ToBencodedString(new StringBuilder()).ToString();
		}

		/// <summary>
		/// Generates the bencoded equivalent of the integer.
		/// </summary>
		/// <returns>The bencoded equivalent of the integer.</returns>
		public StringBuilder ToBencodedString(StringBuilder u)
		{
			if (u == null) u = new StringBuilder('i');
			else u.Append('i');
			return u.Append(Value.ToString()).Append('e');
		}

		/// <see cref="Object.GetHashCode()"/>
		public override int GetHashCode()
		{
			return this.Value.GetHashCode();
		}

		/// <summary>
		/// Int32.Equals(object)
		/// </summary>
		public override bool Equals(object obj)
		{
			try
			{
				return this.Value.Equals(((BInteger)obj).Value);
			}
			catch { return false; }
		}

		/// <see cref="Object.ToString()"/>
		public override string ToString()
		{
			return this.Value.ToString();
		}

		/// <see cref="IComparable.CompareTo(object)"/>
		public int CompareTo(BInteger other)
		{
			return this.Value.CompareTo(other.Value);
		}
	}

	/// <summary>
	/// A bencode string.
	/// </summary>
	public class BString : BElement, IComparable<BString>
	{
		/// <summary>
		/// Allows you to set a string to a BString.
		/// </summary>
		/// <param name="s">The string.</param>
		/// <returns>The BString.</returns>
		public static implicit operator BString(string s)
		{
			return new BString(s);
		}

		/// <summary>
		/// The value of the bencoded integer.
		/// </summary>
		public string Value { get; set; }

		/// <summary>
		/// The main constructor.
		/// </summary>
		/// <param name="value"></param>
		public BString(string value)
		{
			this.Value = value;
		}

		/// <summary>
		/// Generates the bencoded equivalent of the string.
		/// </summary>
		/// <returns>The bencoded equivalent of the string.</returns>
		public string ToBencodedString()
		{
			return this.ToBencodedString(new StringBuilder()).ToString();
		}

		/// <summary>
		/// Generates the bencoded equivalent of the string.
		/// </summary>
		/// <param name="u">The StringBuilder to append to.</param>
		/// <returns>The bencoded equivalent of the string.</returns>
		public StringBuilder ToBencodedString(StringBuilder u)
		{
			if (u == null) u = new StringBuilder(this.Value.Length);
			else u.Append(this.Value.Length);
			return u.Append(':').Append(this.Value);
		}

		/// <see cref="Object.GetHashCode()"/>
		public override int GetHashCode()
		{
			return this.Value.GetHashCode();
		}

		/// <summary>
		/// String.Equals(object)
		/// </summary>
		public override bool Equals(object obj)
		{
			try
			{
				return this.Value.Equals(((BString)obj).Value);
			}
			catch { return false; }
		}

		/// <see cref="Object.ToString()"/>
		public override string ToString()
		{
			return this.Value.ToString();
		}

		/// <see cref="IComparable.CompareTo(Object)"/>
		public int CompareTo(BString other)
		{
			return this.Value.CompareTo(other.Value);
		}
	}

	/// <summary>
	/// A bencode list.
	/// </summary>
	public class BList : List<BElement>, BElement
	{
		/// <summary>
		/// Generates the bencoded equivalent of the list.
		/// </summary>
		/// <returns>The bencoded equivalent of the list.</returns>
		public string ToBencodedString()
		{
			return this.ToBencodedString(new StringBuilder()).ToString();
		}

		/// <summary>
		/// Generates the bencoded equivalent of the list.
		/// </summary>
		/// <param name="u">The StringBuilder to append to.</param>
		/// <returns>The bencoded equivalent of the list.</returns>
		public StringBuilder ToBencodedString(StringBuilder u)
		{
			if (u == null) u = new StringBuilder('l');
			else u.Append('l');

			foreach (BElement element in base.ToArray())
			{
				element.ToBencodedString(u);
			}

			return u.Append('e');
		}

		/// <summary>
		/// Adds the specified value to the list.
		/// </summary>
		/// <param name="value">The specified value.</param>
		public void Add(string value)
		{
			base.Add(new BString(value));
		}

		/// <summary>
		/// Adds the specified value to the list.
		/// </summary>
		/// <param name="value">The specified value.</param>
		public void Add(int value)
		{
			base.Add(new BInteger(value));
		}
	}

	/// <summary>
	/// A bencode dictionary.
	/// </summary>
	public class BDictionary : SortedDictionary<BString, BElement>, BElement
	{
		/// <summary>
		/// Generates the bencoded equivalent of the dictionary.
		/// </summary>
		/// <returns>The bencoded equivalent of the dictionary.</returns>
		public string ToBencodedString()
		{
			return this.ToBencodedString(new StringBuilder()).ToString();
		}

		/// <summary>
		/// Generates the bencoded equivalent of the dictionary.
		/// </summary>
		/// <param name="u">The StringBuilder to append to.</param>
		/// <returns>The bencoded equivalent of the dictionary.</returns>
		public StringBuilder ToBencodedString(StringBuilder u)
		{
			if (u == null) u = new StringBuilder('d');
			else u.Append('d');

			for (int i = 0; i < base.Count; i++)
			{
				base.Keys.ElementAt(i).ToBencodedString(u);
				base.Values.ElementAt(i).ToBencodedString(u);
			}

			return u.Append('e');
		}

		/// <summary>
		/// Adds the specified key-value pair to the dictionary.
		/// </summary>
		/// <param name="key">The specified key.</param>
		/// <param name="value">The specified value.</param>
		public void Add(string key, BElement value)
		{
			base.Add(new BString(key), value);
		}

		/// <summary>
		/// Adds the specified key-value pair to the dictionary.
		/// </summary>
		/// <param name="key">The specified key.</param>
		/// <param name="value">The specified value.</param>
		public void Add(string key, string value)
		{
			base.Add(new BString(key), new BString(value));
		}

		/// <summary>
		/// Adds the specified key-value pair to the dictionary.
		/// </summary>
		/// <param name="key">The specified key.</param>
		/// <param name="value">The specified value.</param>
		public void Add(string key, int value)
		{
			base.Add(new BString(key), new BInteger(value));
		}

		/// <summary>
		/// Gets or sets the value assosiated with the specified key.
		/// </summary>
		/// <param name="key">The key of the value to get or set.</param>
		/// <returns>The value assosiated with the specified key.</returns>
		public BElement this[string key]
		{
			get
			{
				return this[new BString(key)];
			}
			set
			{
				this[new BString(key)] = value;
			}
		}
	}

	/// <summary>
	/// A bencoding exception.
	/// </summary>
	public class BencodingException : FormatException
	{
		/// <summary>
		/// Creates a new BencodingException.
		/// </summary>
		public BencodingException() { }

		/// <summary>
		/// Creates a new BencodingException.
		/// </summary>
		/// <param name="message">The message.</param>
		public BencodingException(string message) : base(message) { }

		/// <summary>
		/// Creates a new BencodingException.
		/// </summary>
		/// <param name="message">The message.</param>
		/// <param name="inner">The inner exception.</param>
		public BencodingException(string message, Exception inner) : base(message, inner) { }
	}

	/// <summary>
	/// A class with extension methods for use with Bencoding.
	/// </summary>
	public static class BencodingExtensions
	{
		/// <summary>
		/// Decode the current instance.
		/// </summary>
		/// <param name="s">The current instance.</param>
		/// <returns>The root elements of the decoded string.</returns>
		public static BElement[] BDecode(this string s)
		{
			return BencodeDecoder.Decode(s);
		}
	}
}

Revision: 29199
at March 14, 2011 03:51 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * BencodeDecoder.Decode("d8:Some Key10:Some Value13:Another Valuei42ee");
     * 
     * Feel free to use it.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bencoding
{
    /// <summary>
    /// A bencoding exception.
    /// </summary>
    public class BencodingException : FormatException
    {
        /// <summary>
        /// Creates a new BencodingException.
        /// </summary>
        public BencodingException() { }

        /// <summary>
        /// Creates a new BencodingException.
        /// </summary>
        /// <param name="message">The message.</param>
        public BencodingException(string message) : base(message) { }

        /// <summary>
        /// Creates a new BencodingException.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="inner">The inner exception.</param>
        public BencodingException(string message, Exception inner) : base(message, inner) { }
    }

    /// <summary>
    /// A class with extension methods for use with Bencoding.
    /// </summary>
    public static class BencodingExtensions
    {
        /// <summary>
        /// Decode the current instance.
        /// </summary>
        /// <param name="s">The current instance.</param>
        /// <returns>The root elements of the decoded string.</returns>
        public static BElement[] BDecode(this string s)
        {
            return BencodeDecoder.Decode(s);
        }
    }

    /// <summary>
    /// A class used for decoding Bencoding.
    /// </summary>
    public class BencodeDecoder
    {
        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="s">The bencoded string to decode.</param>
        private BencodeDecoder(string s)
        {
            this.BencodedString = s;
        }

        /// <summary>
        /// Where the reader will start reading next.
        /// </summary>
        private int Index { get; set; }

        /// <summary>
        /// The bencoded string.
        /// </summary>
        private string BencodedString { get; set; }

        /// <summary>
        /// Decodes the specified string.
        /// </summary>
        /// <param name="s">The specified string.</param>
        /// <returns>An array of the root elements.</returns>
        public static BElement[] Decode(string s)
        {
            return new BencodeDecoder(s).Decode();
        }

        /// <summary>
        /// Decodes the string.
        /// </summary>
        /// <returns>An array of root elements.</returns>
        public BElement[] Decode()
        {
            this.Index = 0;

            try
            {
                if (this.BencodedString == null) return null;

                List<BElement> rootElements = new List<BElement>();
                while (this.BencodedString.Length > this.Index)
                {
                    rootElements.Add(this.ReadElement());
                }

                return rootElements.ToArray();
            }
            catch (BencodingException) { throw; }
            catch (Exception e) { throw this.Error(e); }
        }

        /// <summary>
        /// Reads and element.
        /// </summary>
        /// <returns>The element that was read.</returns>
        private BElement ReadElement()
        {
            switch (this.BencodedString[this.Index])
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': return this.ReadString();
                case 'i': return this.ReadInteger();
                case 'l': return this.ReadList();
                case 'd': return this.ReadDictionary();
                default: throw this.Error();
            }
        }

        /// <summary>
        /// Reads a dictionary.
        /// </summary>
        /// <returns>The dictionary that was read.</returns>
        private BDictionary ReadDictionary()
        {
            this.Index++;
            BDictionary dict = new BDictionary();

            try
            {
                while (this.BencodedString[this.Index] != 'e')
                {
                    BString K = this.ReadString();
                    BElement V = this.ReadElement();
                    dict.Add(K, V);
                }
            }
            catch (BencodingException) { throw; }
            catch (Exception e) { throw this.Error(e); }

            this.Index++;
            return dict;
        }

        /// <summary>
        /// Reads a list.
        /// </summary>
        /// <returns>The list that was read.</returns>
        private BList ReadList()
        {
            this.Index++;
            BList lst = new BList();

            try
            {
                while (this.BencodedString[this.Index] != 'e')
                {
                    lst.Add(this.ReadElement());
                }
            }
            catch (BencodingException) { throw; }
            catch (Exception e) { throw this.Error(e); }

            this.Index++;
            return lst;
        }

        /// <summary>
        /// Reads an integer.
        /// </summary>
        /// <returns>The integer that was read.</returns>
        private BInteger ReadInteger()
        {
            this.Index++;

            int end = this.BencodedString.IndexOf('e', this.Index);
            if (end == -1) throw this.Error();

            long integer;

            try
            {
                integer = Convert.ToInt64(this.BencodedString.Substring(this.Index, end - this.Index));
                this.Index = end + 1;
            }
            catch (Exception e) { throw this.Error(e); }

            return new BInteger(integer);
        }

        /// <summary>
        /// Reads a string.
        /// </summary>
        /// <returns>The string that was read.</returns>
        private BString ReadString()
        {
            int length;
            int semicolon;

            try
            {
                semicolon = this.BencodedString.IndexOf(':', this.Index);
                if (semicolon == -1) throw this.Error();
                length = Convert.ToInt32(this.BencodedString.Substring(this.Index, semicolon - Index));
            }
            catch (Exception e) { throw this.Error(e); }

            this.Index = semicolon + 1;
            int tmpIndex = this.Index;
            this.Index += length;

            try
            {
                return new BString(this.BencodedString.Substring(tmpIndex, length));
            }
            catch (Exception e) { throw this.Error(e); }
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <param name="e">The inner exception.</param>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error(Exception e)
        {
            return new BencodingException("Bencoded string invalid.", e);
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error()
        {
            return new BencodingException("Bencoded string invalid.");
        }
    }

    /// <summary>
    /// An interface for bencoded elements.
    /// </summary>
    public interface BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <returns>The bencoded equivalent of the element.</returns>
        string ToBencodedString();

        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the element.</returns>
        StringBuilder ToBencodedString(StringBuilder u);
    }

    /// <summary>
    /// A bencode integer.
    /// </summary>
    public class BInteger : BElement, IComparable<BInteger>
    {
        /// <summary>
        /// Allows you to set an integer to a BInteger.
        /// </summary>
        /// <param name="i">The integer.</param>
        /// <returns>The BInteger.</returns>
        public static implicit operator BInteger(int i)
        {
            return new BInteger(i);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public long Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value">The value of the bencoded integer.</param>
        public BInteger(long value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            if (u == null) u = new StringBuilder('i');
			else u.Append('i');
            return u.Append(Value.ToString()).Append('e');
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <summary>
        /// Int32.Equals(object)
        /// </summary>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BInteger)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable.CompareTo(object)"/>
        public int CompareTo(BInteger other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode string.
    /// </summary>
    public class BString : BElement, IComparable<BString>
    {
        /// <summary>
        /// Allows you to set a string to a BString.
        /// </summary>
        /// <param name="s">The string.</param>
        /// <returns>The BString.</returns>
        public static implicit operator BString(string s)
        {
            return new BString(s);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value"></param>
        public BString(string value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <returns>The bencoded equivalent of the string.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the string.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            if (u == null) u = new StringBuilder(this.Value.Length);
			else u.Append(this.Value.Length);
            return u.Append(':').Append(this.Value);
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <summary>
        /// String.Equals(object)
        /// </summary>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BString)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable.CompareTo(Object)"/>
        public int CompareTo(BString other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode list.
    /// </summary>
    public class BList : List<BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <returns>The bencoded equivalent of the list.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the list.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            if (u == null) u = new StringBuilder('l');
            else u.Append('l');

            foreach (BElement element in base.ToArray())
            {
                element.ToBencodedString(u);
            }

            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(string value)
        {
            base.Add(new BString(value));
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(int value)
        {
            base.Add(new BInteger(value));
        }
    }

    /// <summary>
    /// A bencode dictionary.
    /// </summary>
    public class BDictionary : SortedDictionary<BString, BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            if (u == null) u = new StringBuilder('d');
            else u.Append('d');

            for (int i = 0; i < base.Count; i++)
            {
                base.Keys.ElementAt(i).ToBencodedString(u);
                base.Values.ElementAt(i).ToBencodedString(u);
            }

            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, BElement value)
        {
            base.Add(new BString(key), value);
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, string value)
        {
            base.Add(new BString(key), new BString(value));
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, int value)
        {
            base.Add(new BString(key), new BInteger(value));
        }

        /// <summary>
        /// Gets or sets the value assosiated with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get or set.</param>
        /// <returns>The value assosiated with the specified key.</returns>
        public BElement this[string key]
        {
            get
            {
                return this[new BString(key)];
            }
            set
            {
                this[new BString(key)] = value;
            }
        }
    }
}

Revision: 29198
at January 13, 2011 05:43 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * BencodeDecoder.Decode("d8:Some Key10:Some Value13:Another Valuei42ee");
     * 
     * Feel free to use it.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

    /// <summary>
    /// A bencoding exception.
    /// </summary>
    public class BencodingException : FormatException
    {
        /// <summary>
        /// Creates a new BencodingException.
        /// </summary>
        public BencodingException() { }

        /// <summary>
        /// Creates a new BencodingException.
        /// </summary>
        /// <param name="message">The message.</param>
        public BencodingException(string message) : base(message) { }

        /// <summary>
        /// Creates a new BencodingException.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="inner">The inner exception.</param>
        public BencodingException(string message, Exception inner) : base(message, inner) { }
    }

    /// <summary>
    /// A class with extension methods for use with Bencoding.
    /// </summary>
    public static class BencodingExtensions
    {
        /// <summary>
        /// Decode the current instance.
        /// </summary>
        /// <param name="s">The current instance.</param>
        /// <returns>The root elements of the decoded string.</returns>
        public static BElement[] BDecode(this string s)
        {
            return BencodeDecoder.Decode(s);
        }
    }

    /// <summary>
    /// A class used for decoding Bencoding.
    /// </summary>
    public class BencodeDecoder
    {
        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="s">The bencoded string to decode.</param>
        private BencodeDecoder(string s)
        {
            this.BencodedString = s;
        }

        /// <summary>
        /// Where the reader will start reading next.
        /// </summary>
        private int Index { get; set; }

        /// <summary>
        /// The bencoded string.
        /// </summary>
        private string BencodedString { get; set; }

        /// <summary>
        /// Decodes the specified string.
        /// </summary>
        /// <param name="s">The specified string.</param>
        /// <returns>An array of the root elements.</returns>
        public static BElement[] Decode(string s)
        {
            return new BencodeDecoder(s).Decode();
        }

        /// <summary>
        /// Decodes the string.
        /// </summary>
        /// <returns>An array of root elements.</returns>
        public BElement[] Decode()
        {
            this.Index = 0;

            try
            {
                if (this.BencodedString == null) return null;

                List<BElement> rootElements = new List<BElement>();
                while (this.BencodedString.Length > this.Index)
                {
                    rootElements.Add(this.ReadElement());
                }

                return rootElements.ToArray();
            }
            catch (BencodingException) { throw; }
            catch (Exception e) { throw this.Error(e); }
        }

        /// <summary>
        /// Reads and element.
        /// </summary>
        /// <returns>The element that was read.</returns>
        private BElement ReadElement()
        {
            switch (this.BencodedString[this.Index])
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': return this.ReadString();
                case 'i': return this.ReadInteger();
                case 'l': return this.ReadList();
                case 'd': return this.ReadDictionary();
                default: throw this.Error();
            }
        }

        /// <summary>
        /// Reads a dictionary.
        /// </summary>
        /// <returns>The dictionary that was read.</returns>
        private BDictionary ReadDictionary()
        {
            this.Index++;
            BDictionary dict = new BDictionary();

            try
            {
                while (this.BencodedString[this.Index] != 'e')
                {
                    BString K = this.ReadString();
                    BElement V = this.ReadElement();
                    dict.Add(K, V);
                }
            }
            catch (BencodingException) { throw; }
            catch (Exception e) { throw this.Error(e); }

            this.Index++;
            return dict;
        }

        /// <summary>
        /// Reads a list.
        /// </summary>
        /// <returns>The list that was read.</returns>
        private BList ReadList()
        {
            this.Index++;
            BList lst = new BList();

            try
            {
                while (this.BencodedString[this.Index] != 'e')
                {
                    lst.Add(this.ReadElement());
                }
            }
            catch (BencodingException) { throw; }
            catch (Exception e) { throw this.Error(e); }

            this.Index++;
            return lst;
        }

        /// <summary>
        /// Reads an integer.
        /// </summary>
        /// <returns>The integer that was read.</returns>
        private BInteger ReadInteger()
        {
            this.Index++;

            int end = this.BencodedString.IndexOf('e', this.Index);
            if (end == -1) throw this.Error();

            long integer;

            try
            {
                integer = Convert.ToInt64(this.BencodedString.Substring(this.Index, end - this.Index));
                this.Index = end + 1;
            }
            catch (Exception e) { throw Error(e); }

            return new BInteger(integer);
        }

        /// <summary>
        /// Reads a string.
        /// </summary>
        /// <returns>The string that was read.</returns>
        private BString ReadString()
        {
            int length;
            int semicolon;

            try
            {
                semicolon = this.BencodedString.IndexOf(':', this.Index);
                if (semicolon == -1) throw this.Error();
                length = Convert.ToInt32(this.BencodedString.Substring(this.Index, semicolon - Index));
            }
            catch (Exception e) { throw this.Error(e); }

            this.Index = semicolon + 1;
            int tmpIndex = this.Index;
            this.Index += length;

            try
            {
                return new BString(this.BencodedString.Substring(tmpIndex, length));
            }
            catch (Exception e) { throw this.Error(e); }
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <param name="e">The inner exception.</param>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error(Exception e)
        {
            return new BencodingException("Bencoded string invalid.", e);
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error()
        {
            return new BencodingException("Bencoded string invalid.");
        }
    }

    /// <summary>
    /// An interface for bencoded elements.
    /// </summary>
    public interface BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <returns>The bencoded equivalent of the element.</returns>
        string ToBencodedString();

        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the element.</returns>
        StringBuilder ToBencodedString(StringBuilder u);
    }

    /// <summary>
    /// A bencode integer.
    /// </summary>
    public class BInteger : BElement, IComparable<BInteger>
    {
        /// <summary>
        /// Allows you to set an integer to a BInteger.
        /// </summary>
        /// <param name="i">The integer.</param>
        /// <returns>The BInteger.</returns>
        public static implicit operator BInteger(int i)
        {
            return new BInteger(i);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public long Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value">The value of the bencoded integer.</param>
        public BInteger(long value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u = u ?? new StringBuilder();

            return u.Append('i').Append(Value.ToString()).Append('e');
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="int.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BInteger)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable.CompareTo(object)"/>
        public int CompareTo(BInteger other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode string.
    /// </summary>
    public class BString : BElement, IComparable<BString>
    {
        /// <summary>
        /// Allows you to set a string to a BString.
        /// </summary>
        /// <param name="s">The string.</param>
        /// <returns>The BString.</returns>
        public static implicit operator BString(string s)
        {
            return new BString(s);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value"></param>
        public BString(string value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <returns>The bencoded equivalent of the string.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the string.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u = u ?? new StringBuilder();

            return u.Append(this.Value.Length).Append(':').Append(this.Value);
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="string.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BString)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable.CompareTo(object)"/>
        public int CompareTo(BString other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode list.
    /// </summary>
    public class BList : List<BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <returns>The bencoded equivalent of the list.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the list.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u = u ?? new StringBuilder();

            u.Append('l');

            foreach (BElement element in base.ToArray())
            {
                element.ToBencodedString(u);
            }

            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(string value)
        {
            base.Add(new BString(value));
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(int value)
        {
            base.Add(new BInteger(value));
        }
    }

    /// <summary>
    /// A bencode dictionary.
    /// </summary>
    public class BDictionary : SortedDictionary<BString, BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u = u ?? new StringBuilder();

            u.Append('d');

            for (int i = 0; i < base.Count; i++)
            {
                base.Keys.ElementAt(i).ToBencodedString(u);
                base.Values.ElementAt(i).ToBencodedString(u);
            }

            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, BElement value)
        {
            base.Add(new BString(key), value);
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, string value)
        {
            base.Add(new BString(key), new BString(value));
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, int value)
        {
            base.Add(new BString(key), new BInteger(value));
        }

        /// <summary>
        /// Gets or sets the value assosiated with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get or set.</param>
        /// <returns>The value assosiated with the specified key.</returns>
        public BElement this[string key]
        {
            get
            {
                return this[new BString(key)];
            }
            set
            {
                this[new BString(key)] = value;
            }
        }
    }

Revision: 29197
at December 18, 2010 07:34 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Value13:Another Valuei42ee").Decode();
     * 
     * Feel free to use it.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

    /// <summary>
    /// A bencoding exception.
    /// </summary>
    public class BencodingException : FormatException
    {
        /// <summary>
        /// Creates a new BencodingException.
        /// </summary>
        public BencodingException() { }

        /// <summary>
        /// Creates a new BencodingException.
        /// </summary>
        /// <param name="message">The message.</param>
        public BencodingException(string message) : base(message) { }

        /// <summary>
        /// Creates a new BencodingException.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="inner">The inner exception.</param>
        public BencodingException(string message, Exception inner) : base(message, inner) { }
    }

    /// <summary>
    /// A class with extension methods for use with Bencoding.
    /// </summary>
    public static class BencodingExtensions
    {
        /// <summary>
        /// Decode the current instance.
        /// </summary>
        /// <param name="s">The current instance.</param>
        /// <returns>The root elements of the decoded string.</returns>
        public static BElement[] BDecode(this string s)
        {
            return BencodeDecoder.Decode(s);
        }
    }

    /// <summary>
    /// A class used for decoding Bencoding.
    /// </summary>
    public class BencodeDecoder
    {
        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="s">The bencoded string to decode.</param>
        private BencodeDecoder(string s)
        {
            this.BencodedString = s;
        }

        /// <summary>
        /// Where the reader will start reading next.
        /// </summary>
        private int Index { get; set; }

        /// <summary>
        /// The bencoded string.
        /// </summary>
        private string BencodedString { get; set; }

        /// <summary>
        /// Decodes the specified string.
        /// </summary>
        /// <param name="s">The specified string.</param>
        /// <returns>An array of the root elements.</returns>
        public static BElement[] Decode(string s)
        {
            return new BencodeDecoder(s).Decode();
        }

        /// <summary>
        /// Decodes the string.
        /// </summary>
        /// <returns>An array of root elements.</returns>
        public BElement[] Decode()
        {
            this.Index = 0;

            try
            {
                if (this.BencodedString == null) return null;

                List<BElement> rootElements = new List<BElement>();
                while (this.BencodedString.Length > this.Index)
                {
                    rootElements.Add(this.ReadElement());
                }

                return rootElements.ToArray();
            }
            catch (BencodingException) { throw; }
            catch (Exception e) { throw this.Error(e); }
        }

        /// <summary>
        /// Reads and element.
        /// </summary>
        /// <returns>The element that was read.</returns>
        private BElement ReadElement()
        {
            switch (this.BencodedString[this.Index])
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': return this.ReadString();
                case 'i': return this.ReadInteger();
                case 'l': return this.ReadList();
                case 'd': return this.ReadDictionary();
                default: throw this.Error();
            }
        }

        /// <summary>
        /// Reads a dictionary.
        /// </summary>
        /// <returns>The dictionary that was read.</returns>
        private BDictionary ReadDictionary()
        {
            this.Index++;
            BDictionary dict = new BDictionary();

            try
            {
                while (this.BencodedString[this.Index] != 'e')
                {
                    BString K = this.ReadString();
                    BElement V = this.ReadElement();
                    dict.Add(K, V);
                }
            }
            catch (BencodingException) { throw; }
            catch (Exception e) { throw this.Error(e); }

            this.Index++;
            return dict;
        }

        /// <summary>
        /// Reads a list.
        /// </summary>
        /// <returns>The list that was read.</returns>
        private BList ReadList()
        {
            this.Index++;
            BList lst = new BList();

            try
            {
                while (this.BencodedString[this.Index] != 'e')
                {
                    lst.Add(this.ReadElement());
                }
            }
            catch (BencodingException) { throw; }
            catch (Exception e) { throw this.Error(e); }

            this.Index++;
            return lst;
        }

        /// <summary>
        /// Reads an integer.
        /// </summary>
        /// <returns>The integer that was read.</returns>
        private BInteger ReadInteger()
        {
            this.Index++;

            int end = this.BencodedString.IndexOf('e', this.Index);
            if (end == -1) throw this.Error();

            long integer;

            try
            {
                integer = Convert.ToInt64(this.BencodedString.Substring(this.Index, end - this.Index));
                this.Index = end + 1;
            }
            catch (Exception e) { throw Error(e); }

            return new BInteger(integer);
        }

        /// <summary>
        /// Reads a string.
        /// </summary>
        /// <returns>The string that was read.</returns>
        private BString ReadString()
        {
            int length;
            int semicolon;

            try
            {
                semicolon = this.BencodedString.IndexOf(':', this.Index);
                if (semicolon == -1) throw this.Error();
                length = Convert.ToInt32(this.BencodedString.Substring(this.Index, semicolon - Index));
            }
            catch (Exception e) { throw this.Error(e); }

            this.Index = semicolon + 1;
            int tmpIndex = this.Index;
            this.Index += length;

            try
            {
                return new BString(this.BencodedString.Substring(tmpIndex, length));
            }
            catch (Exception e) { throw this.Error(e); }
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <param name="e">The inner exception.</param>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error(Exception e)
        {
            return new BencodingException("Bencoded string invalid.", e);
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error()
        {
            return new BencodingException("Bencoded string invalid.");
        }
    }

    /// <summary>
    /// An interface for bencoded elements.
    /// </summary>
    public interface BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <returns>The bencoded equivalent of the element.</returns>
        string ToBencodedString();

        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the element.</returns>
        StringBuilder ToBencodedString(StringBuilder u);
    }

    /// <summary>
    /// A bencode integer.
    /// </summary>
    public class BInteger : BElement, IComparable<BInteger>
    {
        /// <summary>
        /// Allows you to set an integer to a BInteger.
        /// </summary>
        /// <param name="i">The integer.</param>
        /// <returns>The BInteger.</returns>
        public static implicit operator BInteger(int i)
        {
            return new BInteger(i);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public long Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value">The value of the bencoded integer.</param>
        public BInteger(long value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u = u ?? new StringBuilder();

            return u.Append('i').Append(Value.ToString()).Append('e');
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="int.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BInteger)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable.CompareTo(object)"/>
        public int CompareTo(BInteger other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode string.
    /// </summary>
    public class BString : BElement, IComparable<BString>
    {
        /// <summary>
        /// Allows you to set a string to a BString.
        /// </summary>
        /// <param name="s">The string.</param>
        /// <returns>The BString.</returns>
        public static implicit operator BString(string s)
        {
            return new BString(s);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value"></param>
        public BString(string value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <returns>The bencoded equivalent of the string.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the string.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u = u ?? new StringBuilder();

            return u.Append(this.Value.Length).Append(':').Append(this.Value);
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="string.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BString)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable.CompareTo(object)"/>
        public int CompareTo(BString other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode list.
    /// </summary>
    public class BList : List<BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <returns>The bencoded equivalent of the list.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the list.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u = u ?? new StringBuilder();

            u.Append('l');

            foreach (BElement element in base.ToArray())
            {
                element.ToBencodedString(u);
            }

            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(string value)
        {
            base.Add(new BString(value));
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(int value)
        {
            base.Add(new BInteger(value));
        }
    }

    /// <summary>
    /// A bencode dictionary.
    /// </summary>
    public class BDictionary : SortedDictionary<BString, BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u = u ?? new StringBuilder();

            u.Append('d');

            for (int i = 0; i < base.Count; i++)
            {
                base.Keys.ElementAt(i).ToBencodedString(u);
                base.Values.ElementAt(i).ToBencodedString(u);
            }

            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, BElement value)
        {
            base.Add(new BString(key), value);
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, string value)
        {
            base.Add(new BString(key), new BString(value));
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, int value)
        {
            base.Add(new BString(key), new BInteger(value));
        }

        /// <summary>
        /// Gets or sets the value assosiated with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get or set.</param>
        /// <returns>The value assosiated with the specified key.</returns>
        public BElement this[string key]
        {
            get
            {
                return this[new BString(key)];
            }
            set
            {
                this[new BString(key)] = value;
            }
        }
    }

Revision: 29196
at December 18, 2010 06:12 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Value13:Another Valuei42ee").Decode();
     * 
     * Feel free to use it.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

    /// <summary>
    /// A class used for decoding Bencoding.
    /// </summary>
    public class BencodeDecoder
    {
        /// <summary>
        /// A bencoding exception.
        /// </summary>
        public class BencodingException : FormatException
        {
            /// <summary>
            /// Creates a new BencodingException.
            /// </summary>
            public BencodingException() { }
            /// <summary>
            /// Creates a new BencodingException.
            /// </summary>
            /// <param name="message">The message.</param>
            public BencodingException(string message) : base(message) { }
            /// <summary>
            /// Creates a new BencodingException.
            /// </summary>
            /// <param name="message">The message.</param>
            /// <param name="inner">The inner exception.</param>
            public BencodingException(string message, Exception inner) : base(message, inner) { }
        }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="s">The bencoded string to decode.</param>
        public BencodeDecoder(string s)
        {
            BencodedString = s;
        }

        /// <summary>
        /// Where the reader will start reading next.
        /// </summary>
        private int Index = 0;
        /// <summary>
        /// The bencoded string.
        /// </summary>
        public string BencodedString = null;

        /// <summary>
        /// Decodes the string.
        /// </summary>
        /// <returns>An array of root elements.</returns>
        public BElement[] Decode()
        {
            try
            {
                List<BElement> rootElements = new List<BElement>();
                while (BencodedString.Length > Index)
                {
                    rootElements.Add(ReadElement());
                }
                return rootElements.ToArray();
            }
            catch (BencodingException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
        }

        /// <summary>
        /// Reads and element.
        /// </summary>
        /// <returns>The element that was read.</returns>
        private BElement ReadElement()
        {
            switch (BencodedString[Index])
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': return ReadString();
                case 'i': return ReadInteger();
                case 'l': return ReadList();
                case 'd': return ReadDictionary();
                default: throw Error();
            }
        }

        /// <summary>
        /// Reads a dictionary.
        /// </summary>
        /// <returns>The dictionary that was read.</returns>
        private BDictionary ReadDictionary()
        {
            Index++;
            BDictionary dict = new BDictionary();
            try
            {
                while (BencodedString[Index] != 'e')
                {
                    BString K = ReadString();
                    BElement V = ReadElement();
                    dict.Add(K, V);
                }
            }
            catch (BencodingException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            Index++;
            return dict;
        }

        /// <summary>
        /// Reads a list.
        /// </summary>
        /// <returns>The list that was read.</returns>
        private BList ReadList()
        {
            Index++;
            BList lst = new BList();
            try
            {
                while (BencodedString[Index] != 'e')
                {
                    lst.Add(ReadElement());
                }
            }
            catch (BencodingException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            Index++;
            return lst;
        }

        /// <summary>
        /// Reads an integer.
        /// </summary>
        /// <returns>The integer that was read.</returns>
        private BInteger ReadInteger()
        {
            Index++;
            int end = BencodedString.IndexOf('e', Index);
            if (end == -1) throw Error();
            long Integer = 0;
            try
            {
                Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                Index = end + 1;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            return new BInteger(Integer);
        }

        /// <summary>
        /// Reads a string.
        /// </summary>
        /// <returns>The string that was read.</returns>
        private BString ReadString()
        {
            int length = 0;
            int semicolon = 0;
            try
            {
                semicolon = BencodedString.IndexOf(':', Index);
                if (semicolon == -1) throw Error();
                length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
            }
            catch (Exception e)
            {
                throw Error(e);
            }

            Index = semicolon + 1;
            int tmpIndex = Index;
            Index += length;
            try
            {
                return new BString(BencodedString.Substring(tmpIndex, length));
            }
            catch (Exception e)
            {
                throw Error(e);
            }
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <param name="e">The inner exception.</param>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error(Exception e)
        {
            return new BencodingException("Bencoded string invalid.", e);
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error()
        {
            return new BencodingException("Bencoded string invalid.");
        }
    }

    /// <summary>
    /// An interface for bencoded elements.
    /// </summary>
    public interface BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <returns>The bencoded equivalent of the element.</returns>
        string ToBencodedString();

        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the element.</returns>
        StringBuilder ToBencodedString(StringBuilder u);
    }

    /// <summary>
    /// A bencode integer.
    /// </summary>
    public class BInteger : BElement, IComparable<BInteger>
    {
        /// <summary>
        /// Allows you to set an integer to a BInteger.
        /// </summary>
        /// <param name="i">The integer.</param>
        /// <returns>The BInteger.</returns>
        public static implicit operator BInteger(int i)
        {
            return new BInteger(i);
        }

        //public int Value { get; set; }
        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public long Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value">The value of the bencoded integer.</param>
        public BInteger(long value /*int value*/)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            return u.Append('i').Append(Value.ToString()).Append('e');
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="int.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BInteger)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable<BInteger>.CompareTo(object)"/>
        public int CompareTo(BInteger other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode string.
    /// </summary>
    public class BString : BElement, IComparable<BString>
    {
        /// <summary>
        /// Allows you to set a string to a BString.
        /// </summary>
        /// <param name="s">The string.</param>
        /// <returns>The BString.</returns>
        public static implicit operator BString(string s)
        {
            return new BString(s);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value"></param>
        public BString(string value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <returns>The bencoded equivalent of the string.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the string.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            return u.Append(this.Value.Length).Append(':').Append(this.Value);
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="string.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BString)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable<BString>.CompareTo(object)"/>
        public int CompareTo(BString other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode list.
    /// </summary>
    public class BList : List<BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <returns>The bencoded equivalent of the list.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the list.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u.Append('l');
            foreach (BElement element in base.ToArray())
            {
                element.ToBencodedString(u);
            }
            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(string value)
        {
            base.Add(new BString(value));
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(int value)
        {
            base.Add(new BInteger(value));
        }
    }

    /// <summary>
    /// A bencode dictionary.
    /// </summary>
    public class BDictionary : SortedDictionary<BString, BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u.Append('d');
            for (int i = 0; i < base.Count; i++)
            {
                base.Keys.ElementAt(i).ToBencodedString(u);
                base.Values.ElementAt(i).ToBencodedString(u);
            }
            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, BElement value)
        {
            base.Add(new BString(key), value);
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, string value)
        {
            base.Add(new BString(key), new BString(value));
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, int value)
        {
            base.Add(new BString(key), new BInteger(value));
        }

        /// <summary>
        /// Gets or sets the value assosiated with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get or set.</param>
        /// <returns>The value assosiated with the specified key.</returns>
        public BElement this[string key]
        {
            get
            {
                return this[new BString(key)];
            }
            set
            {
                this[new BString(key)] = value;
            }
        }
    }

Revision: 29195
at October 18, 2010 02:51 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Value13:Another Valuei42ee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

    /// <summary>
    /// A class used for decoding Bencoding.
    /// </summary>
    public class BencodeDecoder
    {
        /// <summary>
        /// A bencoding exception.
        /// </summary>
        public class BencodingException : FormatException
        {
            /// <summary>
            /// Creates a new BencodingException.
            /// </summary>
            public BencodingException() { }
            /// <summary>
            /// Creates a new BencodingException.
            /// </summary>
            /// <param name="message">The message.</param>
            public BencodingException(string message) : base(message) { }
            /// <summary>
            /// Creates a new BencodingException.
            /// </summary>
            /// <param name="message">The message.</param>
            /// <param name="inner">The inner exception.</param>
            public BencodingException(string message, Exception inner) : base(message, inner) { }
        }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="s">The bencoded string to decode.</param>
        public BencodeDecoder(string s)
        {
            BencodedString = s;
        }

        /// <summary>
        /// Where the reader will start reading next.
        /// </summary>
        private int Index = 0;
        /// <summary>
        /// The bencoded string.
        /// </summary>
        public string BencodedString = null;

        /// <summary>
        /// Decodes the string.
        /// </summary>
        /// <returns>An array of root elements.</returns>
        public BElement[] Decode()
        {
            try
            {
                List<BElement> rootElements = new List<BElement>();
                while (BencodedString.Length > Index)
                {
                    rootElements.Add(ReadElement());
                }
                return rootElements.ToArray();
            }
            catch (BencodingException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
        }

        /// <summary>
        /// Reads and element.
        /// </summary>
        /// <returns>The element that was read.</returns>
        private BElement ReadElement()
        {
            switch (BencodedString[Index])
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': return ReadString();
                case 'i': return ReadInteger();
                case 'l': return ReadList();
                case 'd': return ReadDictionary();
                default: throw Error();
            }
        }

        /// <summary>
        /// Reads a dictionary.
        /// </summary>
        /// <returns>The dictionary that was read.</returns>
        private BDictionary ReadDictionary()
        {
            Index++;
            BDictionary dict = new BDictionary();
            try
            {
                while (BencodedString[Index] != 'e')
                {
                    BString K = ReadString();
                    BElement V = ReadElement();
                    dict.Add(K, V);
                }
            }
            catch (BencodingException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            Index++;
            return dict;
        }

        /// <summary>
        /// Reads a list.
        /// </summary>
        /// <returns>The list that was read.</returns>
        private BList ReadList()
        {
            Index++;
            BList lst = new BList();
            try
            {
                while (BencodedString[Index] != 'e')
                {
                    lst.Add(ReadElement());
                }
            }
            catch (BencodingException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            Index++;
            return lst;
        }

        /// <summary>
        /// Reads an integer.
        /// </summary>
        /// <returns>The integer that was read.</returns>
        private BInteger ReadInteger()
        {
            Index++;
            int end = BencodedString.IndexOf('e', Index);
            if (end == -1) throw Error();
            long Integer = 0;
            try
            {
                Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                Index = end + 1;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            return new BInteger(Integer);
        }

        /// <summary>
        /// Reads a string.
        /// </summary>
        /// <returns>The string that was read.</returns>
        private BString ReadString()
        {
            int length = 0;
            int semicolon = 0;
            try
            {
                semicolon = BencodedString.IndexOf(':', Index);
                if (semicolon == -1) throw Error();
                length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
            }
            catch (Exception e)
            {
                throw Error(e);
            }

            Index = semicolon + 1;
            int tmpIndex = Index;
            Index += length;
            try
            {
                return new BString(BencodedString.Substring(tmpIndex, length));
            }
            catch (Exception e)
            {
                throw Error(e);
            }
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <param name="e">The inner exception.</param>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error(Exception e)
        {
            return new BencodingException("Bencoded string invalid.", e);
        }

        /// <summary>
        /// Generates an error.
        /// </summary>
        /// <returns>An exception that can then be thrown.</returns>
        private Exception Error()
        {
            return new BencodingException("Bencoded string invalid.");
        }
    }

    /// <summary>
    /// An interface for bencoded elements.
    /// </summary>
    public interface BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <returns>The bencoded equivalent of the element.</returns>
        string ToBencodedString();

        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the element.</returns>
        StringBuilder ToBencodedString(StringBuilder u);
    }

    /// <summary>
    /// A bencode integer.
    /// </summary>
    public class BInteger : BElement, IComparable<BInteger>
    {
        /// <summary>
        /// Allows you to set an integer to a BInteger.
        /// </summary>
        /// <param name="i">The integer.</param>
        /// <returns>The BInteger.</returns>
        public static implicit operator BInteger(int i)
        {
            return new BInteger(i);
        }

        //public int Value { get; set; }
        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public long Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value">The value of the bencoded integer.</param>
        public BInteger(long value /*int value*/)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            return u.Append('i').Append(Value.ToString()).Append('e');
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="int.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BInteger)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable<BInteger>.CompareTo(object)"/>
        public int CompareTo(BInteger other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode string.
    /// </summary>
    public class BString : BElement, IComparable<BString>
    {
        /// <summary>
        /// Allows you to set a string to a BString.
        /// </summary>
        /// <param name="s">The string.</param>
        /// <returns>The BString.</returns>
        public static implicit operator BString(string s)
        {
            return new BString(s);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value"></param>
        public BString(string value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <returns>The bencoded equivalent of the string.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the string.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            return u.Append(this.Value.Length).Append(':').Append(this.Value);
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="string.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BString)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable<BString>.CompareTo(object)"/>
        public int CompareTo(BString other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode list.
    /// </summary>
    public class BList : List<BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <returns>The bencoded equivalent of the list.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the list.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u.Append('l');
            foreach (BElement element in base.ToArray())
            {
                element.ToBencodedString(u);
            }
            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(string value)
        {
            base.Add(new BString(value));
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(int value)
        {
            base.Add(new BInteger(value));
        }
    }

    /// <summary>
    /// A bencode dictionary.
    /// </summary>
    public class BDictionary : SortedDictionary<BString, BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u.Append('d');
            for (int i = 0; i < base.Count; i++)
            {
                base.Keys.ElementAt(i).ToBencodedString(u);
                base.Values.ElementAt(i).ToBencodedString(u);
            }
            return u.Append('e');
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, BElement value)
        {
            base.Add(new BString(key), value);
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, string value)
        {
            base.Add(new BString(key), new BString(value));
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, int value)
        {
            base.Add(new BString(key), new BInteger(value));
        }

        /// <summary>
        /// Gets or sets the value assosiated with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get or set.</param>
        /// <returns>The value assosiated with the specified key.</returns>
        public BElement this[string key]
        {
            get
            {
                return this[new BString(key)];
            }
            set
            {
                this[new BString(key)] = value;
            }
        }
    }

Revision: 29194
at August 19, 2010 00:46 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Value13:Another Valuei42ee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

        /// <summary>
        /// A class used for decoding Bencoding.
        /// </summary>
        public class BencodeDecoder
        {
            /// <summary>
            /// A bencoding exception.
            /// </summary>
            public class BencodingException : FormatException
            {
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                public BencodingException() { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                public BencodingException(string message) : base(message) { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                /// <param name="inner">The inner exception.</param>
                public BencodingException(string message, Exception inner) : base(message, inner) { }
            }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="s">The bencoded string to decode.</param>
            public BencodeDecoder(string s)
            {
                BencodedString = s;
            }

            /// <summary>
            /// Where the reader will start reading next.
            /// </summary>
            private int Index = 0;
            /// <summary>
            /// The bencoded string.
            /// </summary>
            public string BencodedString = null;

            /// <summary>
            /// Decodes the string.
            /// </summary>
            /// <returns>An array of root elements.</returns>
            public BElement[] Decode()
            {
                try
                {
                    List<BElement> rootElements = new List<BElement>();
                    while (BencodedString.Length > Index)
                    {
                        rootElements.Add(ReadElement());
                    }
                    return rootElements.ToArray();
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Reads and element.
            /// </summary>
            /// <returns>The element that was read.</returns>
            private BElement ReadElement()
            {
                switch (BencodedString[Index])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': return ReadString();
                    case 'i': return ReadInteger();
                    case 'l': return ReadList();
                    case 'd': return ReadDictionary();
                    default: throw Error(new Exception());
                }
            }

            /// <summary>
            /// Reads a dictionary.
            /// </summary>
            /// <returns>The dictionary that was read.</returns>
            private BDictionary ReadDictionary()
            {
                Index++;
                BDictionary dict = new BDictionary();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        BString K = ReadString();
                        BElement V = ReadElement();
                        dict.Add(K, V);
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return dict;
            }

            /// <summary>
            /// Reads a list.
            /// </summary>
            /// <returns>The list that was read.</returns>
            private BList ReadList()
            {
                Index++;
                BList lst = new BList();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        lst.Add(ReadElement());
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return lst;
            }

            /// <summary>
            /// Reads an integer.
            /// </summary>
            /// <returns>The integer that was read.</returns>
            private BInteger ReadInteger()
            {
                Index++;
                int end = BencodedString.IndexOf('e', Index);
                if (end == -1) throw Error(new Exception());
                long Integer = 0;
                try
                {
                    Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                    Index = end + 1;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                return new BInteger(Integer);
            }

            /// <summary>
            /// Reads a string.
            /// </summary>
            /// <returns>The string that was read.</returns>
            private BString ReadString()
            {
                int length = 0;
                int semicolon = 0;
                try
                {
                    semicolon = BencodedString.IndexOf(':', Index);
                    if (semicolon == -1) throw Error(new Exception());
                    length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }

                Index = semicolon + 1;
                int tmpIndex = Index;
                Index += length;
                try
                {
                    return new BString(BencodedString.Substring(tmpIndex, length));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Generates an error.
            /// </summary>
            /// <param name="e">The inner exception.</param>
            /// <returns>An exception that can then be thrown.</returns>
            private Exception Error(Exception e)
            {
                return new BencodingException("Bencoded string invalid", e);
            }
        }

        /// <summary>
    /// An interface for bencoded elements.
    /// </summary>
    public interface BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <returns>The bencoded equivalent of the element.</returns>
        string ToBencodedString();

        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the element.</returns>
        StringBuilder ToBencodedString(StringBuilder u);
    }

    /// <summary>
    /// A bencode integer.
    /// </summary>
    public class BInteger : BElement, IComparable<BInteger>
    {
        /// <summary>
        /// Allows you to set an integer to a BInteger.
        /// </summary>
        /// <param name="i">The integer.</param>
        /// <returns>The BInteger.</returns>
        public static implicit operator BInteger(int i)
        {
            return new BInteger(i);
        }

        //public int Value { get; set; }
        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public long Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value">The value of the bencoded integer.</param>
        public BInteger(long value /*int value*/)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            return u.Append("i").Append(Value.ToString()).Append("e");
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="int.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BInteger)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable<BInteger>.CompareTo(object)"/>
        public int CompareTo(BInteger other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode string.
    /// </summary>
    public class BString : BElement, IComparable<BString>
    {
        /// <summary>
        /// Allows you to set a string to a BString.
        /// </summary>
        /// <param name="s">The string.</param>
        /// <returns>The BString.</returns>
        public static implicit operator BString(string s)
        {
            return new BString(s);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value"></param>
        public BString(string value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <returns>The bencoded equivalent of the string.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the string.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            return u.Append(this.Value.Length).Append(":").Append(this.Value);
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="string.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BString)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable<BString>.CompareTo(object)"/>
        public int CompareTo(BString other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode list.
    /// </summary>
    public class BList : List<BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <returns>The bencoded equivalent of the list.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the list.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u.Append("l");
            foreach (BElement element in base.ToArray())
            {
                element.ToBencodedString(u);
            }
            return u.Append("e");
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(string value)
        {
            base.Add(new BString(value));
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(int value)
        {
            base.Add(new BInteger(value));
        }
    }

    /// <summary>
    /// A bencode dictionary.
    /// </summary>
    public class BDictionary : SortedDictionary<BString, BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public string ToBencodedString()
        {
            return this.ToBencodedString(new StringBuilder()).ToString();
        }

        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <param name="u">The StringBuilder to append to.</param>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public StringBuilder ToBencodedString(StringBuilder u)
        {
            u.Append("d");
            for (int i = 0; i < base.Count; i++)
            {
                base.Keys.ElementAt(i).ToBencodedString(u);
                base.Values.ElementAt(i).ToBencodedString(u);
            }
            return u.Append("e");
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, BElement value)
        {
            base.Add(new BString(key), value);
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, string value)
        {
            base.Add(new BString(key), new BString(value));
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, int value)
        {
            base.Add(new BString(key), new BInteger(value));
        }

        /// <summary>
        /// Gets or sets the value assosiated with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get or set.</param>
        /// <returns>The value assosiated with the specified key.</returns>
        public BElement this[string key]
        {
            get
            {
                return this[new BString(key)];
            }
            set
            {
                this[new BString(key)] = value;
            }
        }
    }

Revision: 29193
at August 18, 2010 09:38 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Value13:Another Valuei42ee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

        /// <summary>
        /// A class used for decoding Bencoding.
        /// </summary>
        public class BencodeDecoder
        {
            /// <summary>
            /// A bencoding exception.
            /// </summary>
            public class BencodingException : FormatException
            {
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                public BencodingException() { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                public BencodingException(string message) : base(message) { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                /// <param name="inner">The inner exception.</param>
                public BencodingException(string message, Exception inner) : base(message, inner) { }
            }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="s">The bencoded string to decode.</param>
            public BencodeDecoder(string s)
            {
                BencodedString = s;
            }

            /// <summary>
            /// Where the reader will start reading next.
            /// </summary>
            private int Index = 0;
            /// <summary>
            /// The bencoded string.
            /// </summary>
            public string BencodedString = null;

            /// <summary>
            /// Decodes the string.
            /// </summary>
            /// <returns>An array of root elements.</returns>
            public BElement[] Decode()
            {
                try
                {
                    List<BElement> rootElements = new List<BElement>();
                    while (BencodedString.Length > Index)
                    {
                        rootElements.Add(ReadElement());
                    }
                    return rootElements.ToArray();
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Reads and element.
            /// </summary>
            /// <returns>The element that was read.</returns>
            private BElement ReadElement()
            {
                switch (BencodedString[Index])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': return ReadString();
                    case 'i': return ReadInteger();
                    case 'l': return ReadList();
                    case 'd': return ReadDictionary();
                    default: throw Error(new Exception());
                }
            }

            /// <summary>
            /// Reads a dictionary.
            /// </summary>
            /// <returns>The dictionary that was read.</returns>
            private BDictionary ReadDictionary()
            {
                Index++;
                BDictionary dict = new BDictionary();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        BString K = ReadString();
                        BElement V = ReadElement();
                        dict.Add(K, V);
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return dict;
            }

            /// <summary>
            /// Reads a list.
            /// </summary>
            /// <returns>The list that was read.</returns>
            private BList ReadList()
            {
                Index++;
                BList lst = new BList();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        lst.Add(ReadElement());
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return lst;
            }

            /// <summary>
            /// Reads an integer.
            /// </summary>
            /// <returns>The integer that was read.</returns>
            private BInteger ReadInteger()
            {
                Index++;
                int end = BencodedString.IndexOf('e', Index);
                if (end == -1) throw Error(new Exception());
                long Integer = 0;
                try
                {
                    Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                    Index = end + 1;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                return new BInteger(Integer);
            }

            /// <summary>
            /// Reads a string.
            /// </summary>
            /// <returns>The string that was read.</returns>
            private BString ReadString()
            {
                int length = 0;
                int semicolon = 0;
                try
                {
                    semicolon = BencodedString.IndexOf(':', Index);
                    if (semicolon == -1) throw Error(new Exception());
                    length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }

                Index = semicolon + 1;
                int tmpIndex = Index;
                Index += length;
                try
                {
                    return new BString(BencodedString.Substring(tmpIndex, length));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Generates an error.
            /// </summary>
            /// <param name="e">The inner exception.</param>
            /// <returns>An exception that can then be thrown.</returns>
            private Exception Error(Exception e)
            {
                return new BencodingException("Bencoded string invalid", e);
            }
        }

        /// <summary>
    /// An interface for bencoded elements.
    /// </summary>
    public interface BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the element.
        /// </summary>
        /// <returns>The bencoded equivalent of the element.</returns>
        string ToBencodedString();
    }

    /// <summary>
    /// A bencode integer.
    /// </summary>
    public class BInteger : BElement, IComparable<BInteger>
    {
        /// <summary>
        /// Allows you to set an integer to a BInteger.
        /// </summary>
        /// <param name="i">The integer.</param>
        /// <returns>The BInteger.</returns>
        public static implicit operator BInteger(int i)
        {
            return new BInteger(i);
        }

        //public int Value { get; set; }
        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public long Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value">The value of the bencoded integer.</param>
        public BInteger(long value /*int value*/)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the integer.
        /// </summary>
        /// <returns>The bencoded equivalent of the integer.</returns>
        public string ToBencodedString()
        {
            return "i" + Value.ToString() + "e";
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="int.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BInteger)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable<BInteger>.CompareTo(object)"/>
        public int CompareTo(BInteger other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode string.
    /// </summary>
    public class BString : BElement, IComparable<BString>
    {
        /// <summary>
        /// Allows you to set a string to a BString.
        /// </summary>
        /// <param name="s">The string.</param>
        /// <returns>The BString.</returns>
        public static implicit operator BString(string s)
        {
            return new BString(s);
        }

        /// <summary>
        /// The value of the bencoded integer.
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// The main constructor.
        /// </summary>
        /// <param name="value"></param>
        public BString(string value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Generates the bencoded equivalent of the string.
        /// </summary>
        /// <returns>The bencoded equivalent of the string.</returns>
        public string ToBencodedString()
        {
            return this.Value.Length + ":" + this.Value;
        }

        /// <see cref="Object.GetHashCode()"/>
        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        /// <see cref="string.Equals(object)"/>
        public override bool Equals(object obj)
        {
            try
            {
                return this.Value.Equals(((BString)obj).Value);
            }
            catch { return false; }
        }

        /// <see cref="Object.ToString()"/>
        public override string ToString()
        {
            return this.Value.ToString();
        }

        /// <see cref="IComparable<BString>.CompareTo(object)"/>
        public int CompareTo(BString other)
        {
            return this.Value.CompareTo(other.Value);
        }
    }

    /// <summary>
    /// A bencode list.
    /// </summary>
    public class BList : List<BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the list.
        /// </summary>
        /// <returns>The bencoded equivalent of the list.</returns>
        public string ToBencodedString()
        {
            string u = "l";
            foreach (BElement element in base.ToArray())
            {
                u += element.ToBencodedString();
            }
            return u + "e";
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(string value)
        {
            base.Add(new BString(value));
        }

        /// <summary>
        /// Adds the specified value to the list.
        /// </summary>
        /// <param name="value">The specified value.</param>
        public void Add(int value)
        {
            base.Add(new BInteger(value));
        }
    }

    /// <summary>
    /// A bencode dictionary.
    /// </summary>
    public class BDictionary : SortedDictionary<BString, BElement>, BElement
    {
        /// <summary>
        /// Generates the bencoded equivalent of the dictionary.
        /// </summary>
        /// <returns>The bencoded equivalent of the dictionary.</returns>
        public string ToBencodedString()
        {
            string u = "d";
            for (int i = 0; i < base.Count; i++)
            {
                u += base.Keys.ElementAt(i).ToBencodedString();
                u += base.Values.ElementAt(i).ToBencodedString();
            }
            return u + "e";
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, BElement value)
        {
            base.Add(new BString(key), value);
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, string value)
        {
            base.Add(new BString(key), new BString(value));
        }

        /// <summary>
        /// Adds the specified key-value pair to the dictionary.
        /// </summary>
        /// <param name="key">The specified key.</param>
        /// <param name="value">The specified value.</param>
        public void Add(string key, int value)
        {
            base.Add(new BString(key), new BInteger(value));
        }

        /// <summary>
        /// Gets or sets the value assosiated with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get or set.</param>
        /// <returns>The value assosiated with the specified key.</returns>
        public BElement this[string key]
        {
            get
            {
                return this[new BString(key)];
            }
            set
            {
                this[new BString(key)] = value;
            }
        }
    }

Revision: 29192
at August 6, 2010 23:09 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Value13:Another Valuei42ee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

        /// <summary>
        /// A class used for decoding Bencoding.
        /// </summary>
        public class BencodeDecoder
        {
            /// <summary>
            /// A bencoding exception.
            /// </summary>
            public class BencodingException : FormatException
            {
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                public BencodingException() { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                public BencodingException(string message) : base(message) { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                /// <param name="inner">The inner exception.</param>
                public BencodingException(string message, Exception inner) : base(message, inner) { }
            }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="s">The bencoded string to decode.</param>
            public BencodeDecoder(string s)
            {
                BencodedString = s;
            }

            /// <summary>
            /// Where the reader will start reading next.
            /// </summary>
            private int Index = 0;
            /// <summary>
            /// The bencoded string.
            /// </summary>
            public string BencodedString = null;

            /// <summary>
            /// Decodes the string.
            /// </summary>
            /// <returns>An array of root elements.</returns>
            public BElement[] Decode()
            {
                try
                {
                    List<BElement> rootElements = new List<BElement>();
                    while (BencodedString.Length > Index)
                    {
                        rootElements.Add(ReadElement());
                    }
                    return rootElements.ToArray();
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Reads and element.
            /// </summary>
            /// <returns>The element that was read.</returns>
            private BElement ReadElement()
            {
                switch (BencodedString[Index])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': return ReadString();
                    case 'i': return ReadInteger();
                    case 'l': return ReadList();
                    case 'd': return ReadDictionary();
                    default: throw Error(new Exception());
                }
            }

            /// <summary>
            /// Reads a dictionary.
            /// </summary>
            /// <returns>The dictionary that was read.</returns>
            private BDictionary ReadDictionary()
            {
                Index++;
                BDictionary dict = new BDictionary();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        BString K = ReadString();
                        BElement V = ReadElement();
                        dict.Add(K, V);
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return dict;
            }

            /// <summary>
            /// Reads a list.
            /// </summary>
            /// <returns>The list that was read.</returns>
            private BList ReadList()
            {
                Index++;
                BList lst = new BList();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        lst.Add(ReadElement());
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return lst;
            }

            /// <summary>
            /// Reads an integer.
            /// </summary>
            /// <returns>The integer that was read.</returns>
            private BInteger ReadInteger()
            {
                Index++;
                int end = BencodedString.IndexOf('e', Index);
                if (end == -1) throw Error(new Exception());
                long Integer = 0;
                try
                {
                    Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                    Index = end + 1;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                return new BInteger(Integer);
            }

            /// <summary>
            /// Reads a string.
            /// </summary>
            /// <returns>The string that was read.</returns>
            private BString ReadString()
            {
                int length = 0;
                int semicolon = 0;
                try
                {
                    semicolon = BencodedString.IndexOf(':', Index);
                    if (semicolon == -1) throw Error(new Exception());
                    length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }

                Index = semicolon + 1;
                int tmpIndex = Index;
                Index += length;
                try
                {
                    return new BString(BencodedString.Substring(tmpIndex, length));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Generates an error.
            /// </summary>
            /// <param name="e">The inner exception.</param>
            /// <returns>An exception that can then be thrown.</returns>
            private Exception Error(Exception e)
            {
                return new BencodingException("Bencoded string invalid", e);
            }
        }

        /// <summary>
        /// An interface for bencoded elements.
        /// </summary>
        public interface BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the element.
            /// </summary>
            /// <returns>The bencoded equivalent of the element.</returns>
            string ToBencodedString();
        }

        /// <summary>
        /// A bencode integer.
        /// </summary>
        public class BInteger : BElement
        {
            /// <summary>
            /// Allows you to set an integer to a BInteger.
            /// </summary>
            /// <param name="i">The integer.</param>
            /// <returns>The BInteger.</returns>
            public static implicit operator BInteger(int i)
            {
                return new BInteger(i);
            }

            //public int Value { get; set; }
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public long Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value">The value of the bencoded integer.</param>
            public BInteger(long value /*int value*/)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the integer.
            /// </summary>
            /// <returns>The bencoded equivalent of the integer.</returns>
            public string ToBencodedString()
            {
                return "i" + Value.ToString() + "e";
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.GetHashCode()"/>
            public override int GetHashCode()
            {
                return this.Value.GetHashCode();
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            /// <see cref="int.Equals(object)"/>
            public override bool Equals(object obj)
            {
                try
                {
                    return this.Value.Equals(((BInteger)obj).Value);
                }
                catch { return false; }
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode string.
        /// </summary>
        public class BString : BElement
        {
            /// <summary>
            /// Allows you to set a string to a BString.
            /// </summary>
            /// <param name="s">The string.</param>
            /// <returns>The BString.</returns>
            public static implicit operator BString(string s)
            {
                return new BString(s);
            }

            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value"></param>
            public BString(string value)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the string.
            /// </summary>
            /// <returns>The bencoded equivalent of the string.</returns>
            public string ToBencodedString()
            {
                return this.Value.Length + ":" + this.Value;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.GetHashCode()"/>
            public override int GetHashCode()
            {
                return this.Value.GetHashCode();
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            /// <see cref="string.Equals(object)"/>
            public override bool Equals(object obj)
            {
                try
                {
                    return this.Value.Equals(((BString)obj).Value);
                }
                catch { return false; }
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode list.
        /// </summary>
        public class BList : List<BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the list.
            /// </summary>
            /// <returns>The bencoded equivalent of the list.</returns>
            public string ToBencodedString()
            {
                string u = "l";
                foreach (BElement element in base.ToArray())
                {
                    u += element.ToBencodedString();
                }
                return u + "e";
            }

            /// <summary>
            /// Adds the specified value to the list.
            /// </summary>
            /// <param name="value">The specified value.</param>
            public void Add(string value)
            {
                base.Add(new BString(value));
            }

            /// <summary>
            /// Adds the specified value to the list.
            /// </summary>
            /// <param name="value">The specified value.</param>
            public void Add(int value)
            {
                base.Add(new BInteger(value));
            }
        }

        /// <summary>
        /// A bencode dictionary.
        /// </summary>
        public class BDictionary : SortedDictionary<BString, BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the dictionary.
            /// </summary>
            /// <returns>The bencoded equivalent of the dictionary.</returns>
            public string ToBencodedString()
            {
                string u = "d";
                for (int i = 0; i < base.Count; i++)
                {
                    u += base.Keys.ElementAt(i).ToBencodedString();
                    u += base.Values.ElementAt(i).ToBencodedString();
                }
                return u + "e";
            }

            /// <summary>
            /// Adds the specified key-value pair to the dictionary.
            /// </summary>
            /// <param name="key">The specified key.</param>
            /// <param name="value">The specified value.</param>
            public void Add(string key, BElement value)
            {
                base.Add(new BString(key), value);
            }

            /// <summary>
            /// Adds the specified key-value pair to the dictionary.
            /// </summary>
            /// <param name="key">The specified key.</param>
            /// <param name="value">The specified value.</param>
            public void Add(string key, string value)
            {
                base.Add(new BString(key), new BString(value));
            }

            /// <summary>
            /// Adds the specified key-value pair to the dictionary.
            /// </summary>
            /// <param name="key">The specified key.</param>
            /// <param name="value">The specified value.</param>
            public void Add(string key, int value)
            {
                base.Add(new BString(key), new BInteger(value));
            }

            /// <summary>
            /// Gets or sets the value assosiated with the specified key.
            /// </summary>
            /// <param name="key">The key of the value to get or set.</param>
            /// <returns>The value assosiated with the specified key.</returns>
            public BElement this[string key]
            {
                get
                {
                    return this[new BString(key)];
                }
                set
                {
                    this[new BString(key)] = value;
                }
            }
        }

Revision: 29191
at July 28, 2010 03:17 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {"Some Key", "Some Value"},
     *  {"Another Key", 42}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Value13:Another Valuei42ee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

        /// <summary>
        /// A class used for decoding Bencoding.
        /// </summary>
        public class BencodeDecoder
        {
            /// <summary>
            /// A bencoding exception.
            /// </summary>
            public class BencodingException : FormatException
            {
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                public BencodingException() { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                public BencodingException(string message) : base(message) { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                /// <param name="inner">The inner exception.</param>
                public BencodingException(string message, Exception inner) : base(message, inner) { }
            }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="s">The bencoded string to decode.</param>
            public BencodeDecoder(string s)
            {
                BencodedString = s;
            }

            /// <summary>
            /// Where the reader will start reading next.
            /// </summary>
            private int Index = 0;
            /// <summary>
            /// The bencoded string.
            /// </summary>
            public string BencodedString = null;

            /// <summary>
            /// Decodes the string.
            /// </summary>
            /// <returns>An array of root elements.</returns>
            public BElement[] Decode()
            {
                try
                {
                    List<BElement> rootElements = new List<BElement>();
                    while (BencodedString.Length > Index)
                    {
                        rootElements.Add(ReadElement());
                    }
                    return rootElements.ToArray();
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Reads and element.
            /// </summary>
            /// <returns>The element that was read.</returns>
            private BElement ReadElement()
            {
                switch (BencodedString[Index])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': return ReadString();
                    case 'i': return ReadInteger();
                    case 'l': return ReadList();
                    case 'd': return ReadDictionary();
                    default: throw Error(new Exception());
                }
            }

            /// <summary>
            /// Reads a dictionary.
            /// </summary>
            /// <returns>The dictionary that was read.</returns>
            private BDictionary ReadDictionary()
            {
                Index++;
                BDictionary dict = new BDictionary();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        BString K = ReadString();
                        BElement V = ReadElement();
                        dict.Add(K, V);
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return dict;
            }

            /// <summary>
            /// Reads a list.
            /// </summary>
            /// <returns>The list that was read.</returns>
            private BList ReadList()
            {
                Index++;
                BList lst = new BList();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        lst.Add(ReadElement());
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return lst;
            }

            /// <summary>
            /// Reads an integer.
            /// </summary>
            /// <returns>The integer that was read.</returns>
            private BInteger ReadInteger()
            {
                Index++;
                int end = BencodedString.IndexOf('e', Index);
                if (end == -1) throw Error(new Exception());
                long Integer = 0;
                try
                {
                    Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                    Index = end + 1;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                return new BInteger(Integer);
            }

            /// <summary>
            /// Reads a string.
            /// </summary>
            /// <returns>The string that was read.</returns>
            private BString ReadString()
            {
                int length = 0;
                int semicolon = 0;
                try
                {
                    semicolon = BencodedString.IndexOf(':', Index);
                    if (semicolon == -1) throw Error(new Exception());
                    length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }

                Index = semicolon + 1;
                int tmpIndex = Index;
                Index += length;
                try
                {
                    return new BString(BencodedString.Substring(tmpIndex, length));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Generates an error.
            /// </summary>
            /// <param name="e">The inner exception.</param>
            /// <returns>An exception that can then be thrown.</returns>
            private Exception Error(Exception e)
            {
                return new BencodingException("Bencoded string invalid", e);
            }
        }

        /// <summary>
        /// An interface for bencoded elements.
        /// </summary>
        public interface BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the element.
            /// </summary>
            /// <returns>The bencoded equivalent of the element.</returns>
            string ToBencodedString();
        }

        /// <summary>
        /// A bencode integer.
        /// </summary>
        public class BInteger : BElement
        {
            //public int Value { get; set; }
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public long Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value">The value of the bencoded integer.</param>
            public BInteger(long value /*int value*/)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the integer.
            /// </summary>
            /// <returns>The bencoded equivalent of the integer.</returns>
            public string ToBencodedString()
            {
                return "i" + Value.ToString() + "e";
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.GetHashCode()"/>
            public override int GetHashCode()
            {
                return this.Value.GetHashCode();
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            /// <see cref="int.Equals(object)"/>
            public override bool Equals(object obj)
            {
                try
                {
                    return this.Value.Equals(((BInteger)obj).Value);
                }
                catch { return false; }
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode string.
        /// </summary>
        public class BString : BElement
        {
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value"></param>
            public BString(string value)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the string.
            /// </summary>
            /// <returns>The bencoded equivalent of the string.</returns>
            public string ToBencodedString()
            {
                return this.Value.Length + ":" + this.Value;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.GetHashCode()"/>
            public override int GetHashCode()
            {
                return this.Value.GetHashCode();
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            /// <see cref="string.Equals(object)"/>
            public override bool Equals(object obj)
            {
                try
                {
                    return this.Value.Equals(((BString)obj).Value);
                }
                catch { return false; }
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode list.
        /// </summary>
        public class BList : List<BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the list.
            /// </summary>
            /// <returns>The bencoded equivalent of the list.</returns>
            public string ToBencodedString()
            {
                string u = "l";
                foreach (BElement element in base.ToArray())
                {
                    u += element.ToBencodedString();
                }
                return u + "e";
            }

            /// <summary>
            /// Adds the specified value to the list.
            /// </summary>
            /// <param name="value">The specified value.</param>
            public void Add(string value)
            {
                base.Add(new BString(value));
            }

            /// <summary>
            /// Adds the specified value to the list.
            /// </summary>
            /// <param name="value">The specified value.</param>
            public void Add(int value)
            {
                base.Add(new BInteger(value));
            }
        }

        /// <summary>
        /// A bencode dictionary.
        /// </summary>
        public class BDictionary : SortedDictionary<BString, BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the dictionary.
            /// </summary>
            /// <returns>The bencoded equivalent of the dictionary.</returns>
            public string ToBencodedString()
            {
                string u = "d";
                for (int i = 0; i < base.Count; i++)
                {
                    u += base.Keys.ElementAt(i).ToBencodedString();
                    u += base.Values.ElementAt(i).ToBencodedString();
                }
                return u + "e";
            }

            /// <summary>
            /// Adds the specified key-value pair to the dictionary.
            /// </summary>
            /// <param name="key">The specified key.</param>
            /// <param name="value">The specified value.</param>
            public void Add(string key, BElement value)
            {
                base.Add(new BString(key), value);
            }

            /// <summary>
            /// Adds the specified key-value pair to the dictionary.
            /// </summary>
            /// <param name="key">The specified key.</param>
            /// <param name="value">The specified value.</param>
            public void Add(string key, string value)
            {
                base.Add(new BString(key), new BString(value));
            }

            /// <summary>
            /// Adds the specified key-value pair to the dictionary.
            /// </summary>
            /// <param name="key">The specified key.</param>
            /// <param name="value">The specified value.</param>
            public void Add(string key, int value)
            {
                base.Add(new BString(key), new BInteger(value));
            }

            /// <summary>
            /// Gets or sets the value assosiated with the specified key.
            /// </summary>
            /// <param name="key">The key of the value to get or set.</param>
            /// <returns></returns>
            public BElement this[string key]
            {
                get
                {
                    return this[new BString(key)];
                }
                set
                {
                    this[new BString(key)] = value;
                }
            }
        }

Revision: 29190
at July 26, 2010 06:13 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {new BString("Some Key"), new BString("Some Value")}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Valuee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

        /// <summary>
        /// A class used for decoding Bencoding.
        /// </summary>
        public class BencodeDecoder
        {
            /// <summary>
            /// A bencoding exception.
            /// </summary>
            public class BencodingException : FormatException
            {
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                public BencodingException() { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                public BencodingException(string message) : base(message) { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                /// <param name="inner">The inner exception.</param>
                public BencodingException(string message, Exception inner) : base(message, inner) { }
            }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="s">The bencoded string to decode.</param>
            public BencodeDecoder(string s)
            {
                BencodedString = s;
            }

            /// <summary>
            /// Where the reader will start reading next.
            /// </summary>
            private int Index = 0;
            /// <summary>
            /// The bencoded string.
            /// </summary>
            public string BencodedString = null;

            /// <summary>
            /// Decodes the string.
            /// </summary>
            /// <returns>An array of root elements.</returns>
            public BElement[] Decode()
            {
                try
                {
                    List<BElement> rootElements = new List<BElement>();
                    while (BencodedString.Length > Index)
                    {
                        rootElements.Add(ReadElement());
                    }
                    return rootElements.ToArray();
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Reads and element.
            /// </summary>
            /// <returns>The element that was read.</returns>
            private BElement ReadElement()
            {
                switch (BencodedString[Index])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': return ReadString();
                    case 'i': return ReadInteger();
                    case 'l': return ReadList();
                    case 'd': return ReadDictionary();
                    default: throw Error(new Exception());
                }
            }

            /// <summary>
            /// Reads a dictionary.
            /// </summary>
            /// <returns>The dictionary that was read.</returns>
            private BDictionary ReadDictionary()
            {
                Index++;
                BDictionary dict = new BDictionary();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        BString K = ReadString();
                        BElement V = ReadElement();
                        dict.Add(K, V);
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return dict;
            }

            /// <summary>
            /// Reads a list.
            /// </summary>
            /// <returns>The list that was read.</returns>
            private BList ReadList()
            {
                Index++;
                BList lst = new BList();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        lst.Add(ReadElement());
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return lst;
            }

            /// <summary>
            /// Reads an integer.
            /// </summary>
            /// <returns>The integer that was read.</returns>
            private BInteger ReadInteger()
            {
                Index++;
                int end = BencodedString.IndexOf('e', Index);
                if (end == -1) throw Error(new Exception());
                long Integer = 0;
                try
                {
                    Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                    Index = end + 1;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                return new BInteger(Integer);
            }

            /// <summary>
            /// Reads a string.
            /// </summary>
            /// <returns>The string that was read.</returns>
            private BString ReadString()
            {
                int length = 0;
                int semicolon = 0;
                try
                {
                    semicolon = BencodedString.IndexOf(':', Index);
                    if (semicolon == -1) throw Error(new Exception());
                    length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }

                Index = semicolon + 1;
                int tmpIndex = Index;
                Index += length;
                try
                {
                    return new BString(BencodedString.Substring(tmpIndex, length));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Generates an error.
            /// </summary>
            /// <param name="e">The inner exception.</param>
            /// <returns>An exception that can then be thrown.</returns>
            private Exception Error(Exception e)
            {
                return new BencodingException("Bencoded string invalid", e);
            }
        }

        /// <summary>
        /// An interface for bencoded elements.
        /// </summary>
        public interface BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the element.
            /// </summary>
            /// <returns>The bencoded equivalent of the element.</returns>
            string ToBencodedString();
        }

        /// <summary>
        /// A bencode integer.
        /// </summary>
        public class BInteger : BElement
        {
            //public int Value { get; set; }
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public long Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value">The value of the bencoded integer.</param>
            public BInteger(long value /*int value*/)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the integer.
            /// </summary>
            /// <returns>The bencoded equivalent of the integer.</returns>
            public string ToBencodedString()
            {
                return "i" + Value.ToString() + "e";
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.GetHashCode()"/>
            public override int GetHashCode()
            {
                return this.Value.GetHashCode();
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            /// <see cref="int.Equals(object)"/>
            public override bool Equals(object obj)
            {
                try
                {
                    return this.Value.Equals(((BInteger)obj).Value);
                }
                catch { return false; }
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode string.
        /// </summary>
        public class BString : BElement
        {
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value"></param>
            public BString(string value)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the string.
            /// </summary>
            /// <returns>The bencoded equivalent of the string.</returns>
            public string ToBencodedString()
            {
                return this.Value.Length + ":" + this.Value;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.GetHashCode()"/>
            public override int GetHashCode()
            {
                return this.Value.GetHashCode();
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            /// <see cref="string.Equals(object)"/>
            public override bool Equals(object obj)
            {
                try
                {
                    return this.Value.Equals(((BString)obj).Value);
                }
                catch { return false; }
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode list.
        /// </summary>
        public class BList : List<BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the list.
            /// </summary>
            /// <returns>The bencoded equivalent of the list.</returns>
            public string ToBencodedString()
            {
                string u = "l";
                foreach (BElement element in base.ToArray())
                {
                    u += element.ToBencodedString();
                }
                return u + "e";
            }
        }

        /// <summary>
        /// A bencode dictionary.
        /// </summary>
        public class BDictionary : Dictionary<BString, BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the dictionary.
            /// </summary>
            /// <returns>The bencoded equivalent of the dictionary.</returns>
            public string ToBencodedString()
            {
                string u = "d";
                for (int i = 0; i < base.Count; i++)
                {
                    u += base.Keys.ElementAt(i).ToBencodedString();
                    u += base.Values.ElementAt(i).ToBencodedString();
                }
                return u + "e";
            }

            /// <summary>
            /// Gets or sets the value assosiated with the specified key.
            /// </summary>
            /// <param name="key">The key of the value to get or set.</param>
            /// <returns></returns>
            public BElement this[string key]
            {
                get
                {
                    return this[new BString(key)];
                }
                set
                {
                    this[new BString(key)] = value;
                }
            }
        }

Revision: 29189
at July 26, 2010 05:49 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {new BString("Some Key"), new BString("Some Value")}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Valuee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

        /// <summary>
        /// A class used for decoding Bencoding.
        /// </summary>
        public class BencodeDecoder
        {
            /// <summary>
            /// A bencoding exception.
            /// </summary>
            public class BencodingException : FormatException
            {
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                public BencodingException() { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                public BencodingException(string message) : base(message) { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                /// <param name="inner">The inner exception.</param>
                public BencodingException(string message, Exception inner) : base(message, inner) { }
            }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="s">The bencoded string to decode.</param>
            public BencodeDecoder(string s)
            {
                BencodedString = s;
            }

            /// <summary>
            /// Where the reader will start reading next.
            /// </summary>
            private int Index = 0;
            /// <summary>
            /// The bencoded string.
            /// </summary>
            public string BencodedString = null;

            /// <summary>
            /// Decodes the string.
            /// </summary>
            /// <returns>An array of root elements.</returns>
            public BElement[] Decode()
            {
                try
                {
                    List<BElement> rootElements = new List<BElement>();
                    while (BencodedString.Length > Index)
                    {
                        rootElements.Add(ReadElement());
                    }
                    return rootElements.ToArray();
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Reads and element.
            /// </summary>
            /// <returns>The element that was read.</returns>
            private BElement ReadElement()
            {
                switch (BencodedString[Index])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': return ReadString();
                    case 'i': return ReadInteger();
                    case 'l': return ReadList();
                    case 'd': return ReadDictionary();
                    default: throw Error(new Exception());
                }
            }

            /// <summary>
            /// Reads a dictionary.
            /// </summary>
            /// <returns>The dictionary that was read.</returns>
            private BDictionary ReadDictionary()
            {
                Index++;
                BDictionary dict = new BDictionary();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        BString K = ReadString();
                        BElement V = ReadElement();
                        dict.Add(K, V);
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return dict;
            }

            /// <summary>
            /// Reads a list.
            /// </summary>
            /// <returns>The list that was read.</returns>
            private BList ReadList()
            {
                Index++;
                BList lst = new BList();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        lst.Add(ReadElement());
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return lst;
            }

            /// <summary>
            /// Reads an integer.
            /// </summary>
            /// <returns>The integer that was read.</returns>
            private BInteger ReadInteger()
            {
                Index++;
                int end = BencodedString.IndexOf('e', Index);
                if (end == -1) throw Error(new Exception());
                long Integer = 0;
                try
                {
                    Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                    Index = end + 1;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                return new BInteger(Integer);
            }

            /// <summary>
            /// Reads a string.
            /// </summary>
            /// <returns>The string that was read.</returns>
            private BString ReadString()
            {
                int length = 0;
                int semicolon = 0;
                try
                {
                    semicolon = BencodedString.IndexOf(':', Index);
                    if (semicolon == -1) throw Error(new Exception());
                    length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }

                Index = semicolon + 1;
                int tmpIndex = Index;
                Index += length;
                try
                {
                    return new BString(BencodedString.Substring(tmpIndex, length));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Generates an error.
            /// </summary>
            /// <param name="e">The inner exception.</param>
            /// <returns>An exception that can then be thrown.</returns>
            private Exception Error(Exception e)
            {
                return new BencodingException("Bencoded string invalid", e);
            }
        }

        /// <summary>
        /// An interface for bencoded elements.
        /// </summary>
        public interface BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the element.
            /// </summary>
            /// <returns>The bencoded equivalent of the element.</returns>
            string ToBencodedString();
        }

        /// <summary>
        /// A bencode integer.
        /// </summary>
        public class BInteger : BElement
        {
            //public int Value { get; set; }
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public long Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value">The value of the bencoded integer.</param>
            public BInteger(long value /*int value*/)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the integer.
            /// </summary>
            /// <returns>The bencoded equivalent of the integer.</returns>
            public string ToBencodedString()
            {
                return "i" + Value.ToString() + "e";
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode string.
        /// </summary>
        public class BString : BElement
        {
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value"></param>
            public BString(string value)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the string.
            /// </summary>
            /// <returns>The bencoded equivalent of the string.</returns>
            public string ToBencodedString()
            {
                return this.Value.Length + ":" + this.Value;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode list.
        /// </summary>
        public class BList : List<BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the list.
            /// </summary>
            /// <returns>The bencoded equivalent of the list.</returns>
            public string ToBencodedString()
            {
                string u = "l";
                foreach (BElement element in base.ToArray())
                {
                    u += element.ToBencodedString();
                }
                return u + "e";
            }
        }

        /// <summary>
        /// A bencode dictionary.
        /// </summary>
        public class BDictionary : Dictionary<BString, BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the dictionary.
            /// </summary>
            /// <returns>The bencoded equivalent of the dictionary.</returns>
            public string ToBencodedString()
            {
                string u = "d";
                for (int i = 0; i < base.Count; i++)
                {
                    u += base.Keys.ElementAt(i).ToBencodedString();
                    u += base.Values.ElementAt(i).ToBencodedString();
                }
                return u + "e";
            }

            /// <summary>
            /// Gets or sets the value assosiated with the specified key.
            /// </summary>
            /// <param name="key">The key of the value to get or set.</param>
            /// <returns></returns>
            public BElement this[string key]
            {
                get
                {
                    return this[new BString(key)];
                }
                set
                {
                    this[new BString(key)] = value;
                }
            }
        }

Revision: 29188
at July 26, 2010 01:33 by SuprDewd


Updated Code
/*****
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {new BString("Some Key"), new BString("Some Value")}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Valuee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

        /// <summary>
        /// A class used for decoding Bencoding.
        /// </summary>
        public class BencodeDecoder
        {
            /// <summary>
            /// A bencoding exception.
            /// </summary>
            public class BencodingException : FormatException
            {
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                public BencodingException() { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                public BencodingException(string message) : base(message) { }
                /// <summary>
                /// Creates a new BencodingException.
                /// </summary>
                /// <param name="message">The message.</param>
                /// <param name="inner">The inner exception.</param>
                public BencodingException(string message, Exception inner) : base(message, inner) { }
            }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="s">The bencoded string to decode.</param>
            public BencodeDecoder(string s)
            {
                BencodedString = s;
            }

            /// <summary>
            /// Where the reader will start reading next.
            /// </summary>
            private int Index = 0;
            /// <summary>
            /// The bencoded string.
            /// </summary>
            public string BencodedString = null;

            /// <summary>
            /// Decodes the string.
            /// </summary>
            /// <returns>An array of root elements.</returns>
            public BElement[] Decode()
            {
                try
                {
                    List<BElement> rootElements = new List<BElement>();
                    while (BencodedString.Length > Index)
                    {
                        rootElements.Add(ReadElement());
                    }
                    return rootElements.ToArray();
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Reads and element.
            /// </summary>
            /// <returns>The element that was read.</returns>
            private BElement ReadElement()
            {
                switch (BencodedString[Index])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': return ReadString();
                    case 'i': return ReadInteger();
                    case 'l': return ReadList();
                    case 'd': return ReadDictionary();
                    default: throw Error(new Exception());
                }
            }

            /// <summary>
            /// Reads a dictionary.
            /// </summary>
            /// <returns>The dictionary that was read.</returns>
            private BDictionary ReadDictionary()
            {
                Index++;
                BDictionary dict = new BDictionary();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        BString K = ReadString();
                        BElement V = ReadElement();
                        dict.Add(K, V);
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return dict;
            }

            /// <summary>
            /// Reads a list.
            /// </summary>
            /// <returns>The list that was read.</returns>
            private BList ReadList()
            {
                Index++;
                BList lst = new BList();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        lst.Add(ReadElement());
                    }
                }
                catch (BencodingException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return lst;
            }

            /// <summary>
            /// Reads an integer.
            /// </summary>
            /// <returns>The integer that was read.</returns>
            private BInteger ReadInteger()
            {
                Index++;
                int end = BencodedString.IndexOf('e', Index);
                if (end == -1) throw Error(new Exception());
                long Integer = 0;
                try
                {
                    Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                    Index = end + 1;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                return new BInteger(Integer);
            }

            /// <summary>
            /// Reads a string.
            /// </summary>
            /// <returns>The string that was read.</returns>
            private BString ReadString()
            {
                int length = 0;
                int semicolon = 0;
                try
                {
                    semicolon = BencodedString.IndexOf(':', Index);
                    if (semicolon == -1) throw Error(new Exception());
                    length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }

                Index = semicolon + 1;
                int tmpIndex = Index;
                Index += length;
                try
                {
                    return new BString(BencodedString.Substring(tmpIndex, length));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Generates an error.
            /// </summary>
            /// <param name="e">The inner exception.</param>
            /// <returns>An exception that can then be thrown.</returns>
            private Exception Error(Exception e)
            {
                return new BencodingException("Bencoded string invalid", e);
            }
        }

        /// <summary>
        /// An interface for bencoded elements.
        /// </summary>
        public interface BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the element.
            /// </summary>
            /// <returns>The bencoded equivalent of the element.</returns>
            string ToBencodedString();
        }

        /// <summary>
        /// A bencode integer.
        /// </summary>
        public class BInteger : BElement
        {
            //public int Value { get; set; }
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public long Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value">The value of the bencoded integer.</param>
            public BInteger(long value /*int value*/)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the integer.
            /// </summary>
            /// <returns>The bencoded equivalent of the integer.</returns>
            public string ToBencodedString()
            {
                return "i" + Value.ToString() + "e";
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode string.
        /// </summary>
        public class BString : BElement
        {
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value"></param>
            public BString(string value)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the string.
            /// </summary>
            /// <returns>The bencoded equivalent of the string.</returns>
            public string ToBencodedString()
            {
                return this.Value.Length + ":" + this.Value;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode list.
        /// </summary>
        public class BList : List<BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the list.
            /// </summary>
            /// <returns>The bencoded equivalent of the list.</returns>
            public string ToBencodedString()
            {
                string u = "l";
                foreach (BElement element in base.ToArray())
                {
                    u += element.ToBencodedString();
                }
                return u + "e";
            }
        }

        /// <summary>
        /// A bencode dictionary.
        /// </summary>
        public class BDictionary : Dictionary<BString, BElement>, BElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the dictionary.
            /// </summary>
            /// <returns>The bencoded equivalent of the dictionary.</returns>
            public string ToBencodedString()
            {
                string u = "d";
                for (int i = 0; i < base.Count; i++)
                {
                    u += base.Keys.ElementAt(i).ToBencodedString();
                    u += base.Values.ElementAt(i).ToBencodedString();
                }
                return u + "e";
            }
        }

Revision: 29187
at July 25, 2010 01:50 by SuprDewd


Updated Code
/*
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {new BString("Some Key"), new BString("Some Value")}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Valuee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * Originally posted at http://snipplr.com/view/37790/ by SuprDewd.
     * */

        /// <summary>
        /// A class used for decoding Bencoding.
        /// </summary>
        public class BencodeDecoder
        {
            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="s">The bencoded string to decode.</param>
            public BencodeDecoder(string s)
            {
                BencodedString = s;
            }

            /// <summary>
            /// Where the reader will start reading next.
            /// </summary>
            private int Index = 0;
            /// <summary>
            /// The bencoded string.
            /// </summary>
            public string BencodedString = null;

            /// <summary>
            /// Decodes the string.
            /// </summary>
            /// <returns>An array of root elements.</returns>
            public IBElement[] Decode()
            {
                List<IBElement> rootElements = new List<IBElement>();
                while (BencodedString.Length > Index)
                {
                    rootElements.Add(ReadElement());
                }
                return rootElements.ToArray();
            }

            /// <summary>
            /// Reads and element.
            /// </summary>
            /// <returns>The element that was read.</returns>
            private IBElement ReadElement()
            {
                switch (BencodedString[Index])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': return ReadString();
                    case 'i': return ReadInteger();
                    case 'l': return ReadList();
                    case 'd': return ReadDictionary();
                    default: throw Error(new Exception());
                }
            }

            /// <summary>
            /// Reads a dictionary.
            /// </summary>
            /// <returns>The dictionary that was read.</returns>
            private BDictionary ReadDictionary()
            {
                Index++;
                BDictionary dict = new BDictionary();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        BString K = ReadString();
                        IBElement V = ReadElement();
                        dict.Add(K, V);
                    }
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return dict;
            }

            /// <summary>
            /// Reads a list.
            /// </summary>
            /// <returns>The list that was read.</returns>
            private BList ReadList()
            {
                Index++;
                BList lst = new BList();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        lst.Add(ReadElement());
                    }
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return lst;
            }

            /// <summary>
            /// Reads an integer.
            /// </summary>
            /// <returns>The integer that was read.</returns>
            private BInteger ReadInteger()
            {
                Index++;
                int end = BencodedString.IndexOf('e', Index);
                if (end == -1) throw Error(new Exception());
                long Integer = 0;
                try
                {
                    Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                    Index = end + 1;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                return new BInteger(Integer);
            }

            /// <summary>
            /// Reads a string.
            /// </summary>
            /// <returns>The string that was read.</returns>
            private BString ReadString()
            {
                int length = 0;
                int semicolon = 0;
                try
                {
                    semicolon = BencodedString.IndexOf(':', Index);
                    if (semicolon == -1) throw Error(new Exception());
                    length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }

                Index = semicolon + 1;
                int tmpIndex = Index;
                Index += length;
                try
                {
                    return new BString(BencodedString.Substring(tmpIndex, length));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Generates an error.
            /// </summary>
            /// <param name="e">The inner exception.</param>
            /// <returns>An exception that can then be thrown.</returns>
            private Exception Error(Exception e)
            {
                return new Exception("Bencoded string invalid", e);
            }
        }

        /// <summary>
        /// A bencode element.
        /// </summary>
        public interface IBElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the element.
            /// </summary>
            /// <returns>The bencoded equivalent of the element.</returns>
            string ToBencodedString();
        }

        /// <summary>
        /// A bencode integer.
        /// </summary>
        public class BInteger : IBElement
        {
            //public int Value { get; set; }
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public long Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value">The value of the bencoded integer.</param>
            public BInteger(long value /*int value*/)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the integer.
            /// </summary>
            /// <returns>The bencoded equivalent of the integer.</returns>
            public string ToBencodedString()
            {
                return "i" + Value.ToString() + "e";
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode string.
        /// </summary>
        public class BString : IBElement
        {
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value"></param>
            public BString(string value)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the string.
            /// </summary>
            /// <returns>The bencoded equivalent of the string.</returns>
            public string ToBencodedString()
            {
                return this.Value.Length + ":" + this.Value;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode list.
        /// </summary>
        public class BList : List<IBElement>, IBElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the list.
            /// </summary>
            /// <returns>The bencoded equivalent of the list.</returns>
            public string ToBencodedString()
            {
                string u = "l";
                foreach (IBElement element in base.ToArray())
                {
                    u += element.ToBencodedString();
                }
                return u + "e";
            }
        }

        /// <summary>
        /// A bencode dictionary.
        /// </summary>
        public class BDictionary : Dictionary<BString, IBElement>, IBElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the dictionary.
            /// </summary>
            /// <returns>The bencoded equivalent of the dictionary.</returns>
            public string ToBencodedString()
            {
                string u = "d";
                for (int i = 0; i < base.Count; i++)
                {
                    u += base.Keys.ElementAt(i).ToBencodedString();
                    u += base.Values.ElementAt(i).ToBencodedString();
                }
                return u + "e";
            }
        }

Revision: 29186
at July 25, 2010 01:46 by SuprDewd


Updated Code
/*
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {new BString("Some Key"), new BString("Some Value")}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Valuee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * */

    /// <summary>
        /// A class used for decoding Bencoding.
        /// </summary>
        public class BencodeDecoder
        {
            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="s">The bencoded string to decode.</param>
            public BencodeDecoder(string s)
            {
                BencodedString = s;
            }

            /// <summary>
            /// Where the reader will start reading next.
            /// </summary>
            private int Index = 0;
            /// <summary>
            /// The bencoded string.
            /// </summary>
            public string BencodedString = null;

            /// <summary>
            /// Decodes the string.
            /// </summary>
            /// <returns>An array of root elements.</returns>
            public IBElement[] Decode()
            {
                List<IBElement> rootElements = new List<IBElement>();
                while (BencodedString.Length > Index)
                {
                    rootElements.Add(ReadElement());
                }
                return rootElements.ToArray();
            }

            /// <summary>
            /// Reads and element.
            /// </summary>
            /// <returns>The element that was read.</returns>
            private IBElement ReadElement()
            {
                switch (BencodedString[Index])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': return ReadString();
                    case 'i': return ReadInteger();
                    case 'l': return ReadList();
                    case 'd': return ReadDictionary();
                    default: throw Error(new Exception());
                }
            }

            /// <summary>
            /// Reads a dictionary.
            /// </summary>
            /// <returns>The dictionary that was read.</returns>
            private BDictionary ReadDictionary()
            {
                Index++;
                BDictionary dict = new BDictionary();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        BString K = ReadString();
                        IBElement V = ReadElement();
                        dict.Add(K, V);
                    }
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return dict;
            }

            /// <summary>
            /// Reads a list.
            /// </summary>
            /// <returns>The list that was read.</returns>
            private BList ReadList()
            {
                Index++;
                BList lst = new BList();
                try
                {
                    while (BencodedString[Index] != 'e')
                    {
                        lst.Add(ReadElement());
                    }
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                Index++;
                return lst;
            }

            /// <summary>
            /// Reads an integer.
            /// </summary>
            /// <returns>The integer that was read.</returns>
            private BInteger ReadInteger()
            {
                Index++;
                int end = BencodedString.IndexOf('e', Index);
                if (end == -1) throw Error(new Exception());
                long Integer = 0;
                try
                {
                    Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                    Index = end + 1;
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
                return new BInteger(Integer);
            }

            /// <summary>
            /// Reads a string.
            /// </summary>
            /// <returns>The string that was read.</returns>
            private BString ReadString()
            {
                int length = 0;
                int semicolon = 0;
                try
                {
                    semicolon = BencodedString.IndexOf(':', Index);
                    if (semicolon == -1) throw Error(new Exception());
                    length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }

                Index = semicolon + 1;
                int tmpIndex = Index;
                Index += length;
                try
                {
                    return new BString(BencodedString.Substring(tmpIndex, length));
                }
                catch (Exception e)
                {
                    throw Error(e);
                }
            }

            /// <summary>
            /// Generates an error.
            /// </summary>
            /// <param name="e">The inner exception.</param>
            /// <returns>An exception that can then be thrown.</returns>
            private Exception Error(Exception e)
            {
                return new Exception("Bencoded string invalid", e);
            }
        }

        /// <summary>
        /// A bencode element.
        /// </summary>
        public interface IBElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the element.
            /// </summary>
            /// <returns>The bencoded equivalent of the element.</returns>
            string ToBencodedString();
        }

        /// <summary>
        /// A bencode integer.
        /// </summary>
        public class BInteger : IBElement
        {
            //public int Value { get; set; }
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public long Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value">The value of the bencoded integer.</param>
            public BInteger(long value /*int value*/)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the integer.
            /// </summary>
            /// <returns>The bencoded equivalent of the integer.</returns>
            public string ToBencodedString()
            {
                return "i" + Value.ToString() + "e";
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode string.
        /// </summary>
        public class BString : IBElement
        {
            /// <summary>
            /// The value of the bencoded integer.
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// The main constructor.
            /// </summary>
            /// <param name="value"></param>
            public BString(string value)
            {
                this.Value = value;
            }

            /// <summary>
            /// Generates the bencoded equivalent of the string.
            /// </summary>
            /// <returns>The bencoded equivalent of the string.</returns>
            public string ToBencodedString()
            {
                return this.Value.Length + ":" + this.Value;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            /// <see cref="Object.ToString()"/>
            public override string ToString()
            {
                return this.Value.ToString();
            }
        }

        /// <summary>
        /// A bencode list.
        /// </summary>
        public class BList : List<IBElement>, IBElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the list.
            /// </summary>
            /// <returns>The bencoded equivalent of the list.</returns>
            public string ToBencodedString()
            {
                string u = "l";
                foreach (IBElement element in base.ToArray())
                {
                    u += element.ToBencodedString();
                }
                return u + "e";
            }
        }

        /// <summary>
        /// A bencode dictionary.
        /// </summary>
        public class BDictionary : Dictionary<BString, IBElement>, IBElement
        {
            /// <summary>
            /// Generates the bencoded equivalent of the dictionary.
            /// </summary>
            /// <returns>The bencoded equivalent of the dictionary.</returns>
            public string ToBencodedString()
            {
                string u = "d";
                for (int i = 0; i < base.Count; i++)
                {
                    u += base.Keys.ElementAt(i).ToBencodedString();
                    u += base.Values.ElementAt(i).ToBencodedString();
                }
                return u + "e";
            }
        }

Revision: 29185
at July 23, 2010 09:52 by SuprDewd


Updated Code
/*
     * Encoding usage:
     * 
     * new BDictionary()
     * {
     *  {new BString("Some Key"), new BString("Some Value")}
     * }.ToBencodedString();
     * 
     * Decoding usage:
     * 
     * new BencodeDecoder("d8:Some Key10:Some Valuee").Decode();
     * 
     * Feel free to use it in the code in your projects.
     * More info about Bencoding at http://wiki.theory.org/BitTorrentSpecification#bencoding
     * 
     * */

    public class BencodeDecoder
    {
        public BencodeDecoder(string s)
        {
            BencodedString = s;
        }

        private int Index = 0;
        private string BencodedString = null;

        public IBElement[] Decode()
        {
            List<IBElement> rootElements = new List<IBElement>();
            while (BencodedString.Length > Index)
            {
                rootElements.Add(ReadElement());
            }
            return rootElements.ToArray();
        }

        private IBElement ReadElement()
        {
            switch (BencodedString[Index])
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': return ReadString();
                case 'i': return ReadInt();
                case 'l': return ReadList();
                case 'd': return ReadDictionary();
                default: throw Error(new Exception());
            }
        }

        private IBElement ReadDictionary()
        {
            Index++;
            BDictionary dict = new BDictionary();
            try
            {
                while (BencodedString[Index] != 'e')
                {
                    BString K = ReadString();
                    IBElement V = ReadElement();
                    dict.Add(K, V);
                }
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            Index++;
            return dict;
        }

        private IBElement ReadList()
        {
            Index++;
            BList lst = new BList();
            try
            {
                while (BencodedString[Index] != 'e')
                {
                    lst.Add(ReadElement());
                }
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            Index++;
            return lst;
        }

        private BInteger ReadInt()
        {
            Index++;
            int end = BencodedString.IndexOf('e', Index);
            if (end == -1) throw Error(new Exception());
            long Integer = 0;
            try
            {
                Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                Index = end + 1;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            return new BInteger(Integer);
        }

        private Exception Error(Exception e)
        {
            return new Exception("Bencoded string invalid", e);
        }

        private BString ReadString()
        {
            int length = 0;
            int semicolon = 0;
            try
            {
                semicolon = BencodedString.IndexOf(':', Index);
                if (semicolon == -1) throw Error(new Exception());
                length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
            }
            catch (Exception e)
            {
                throw Error(e);
            }

            Index = semicolon + 1;
            int tmpIndex = Index;
            Index += length;
            try
            {
                return new BString(BencodedString.Substring(tmpIndex, length));
            }
            catch (Exception e)
            {
                throw Error(e);
            }
        }
    }

    public interface IBElement
    {
        string ToBencodedString();
    }

    public class BInteger : IBElement
    {
        //public int Value { get; set; }
        public long Value { get; set; }

        public BInteger(long value /*int value*/)
        {
            this.Value = value;
        }

        public string ToBencodedString()
        {
            return "i" + Value.ToString() + "e";
        }

        public override string ToString()
        {
            return this.Value.ToString();
        }
    }

    public class BString : IBElement
    {
        public string Value { get; set; }

        public BString(string value)
        {
            this.Value = value;
        }

        public string ToBencodedString()
        {
            return this.Value.Length + ":" + this.Value;
        }

        public override string ToString()
        {
            return this.Value.ToString();
        }
    }

    public class BList : List<IBElement>, IBElement
    {
        public string ToBencodedString()
        {
            string u = "l";
            foreach (IBElement element in base.ToArray())
            {
                u += element.ToBencodedString();
            }
            return u + "e";
        }
    }

    public class BDictionary : Dictionary<BString, IBElement>, IBElement
    {
        public string ToBencodedString()
        {
            string u = "d";
            for (int i = 0; i < base.Count; i++)
            {
                u += base.Keys.ElementAt(i).ToBencodedString();
                u += base.Values.ElementAt(i).ToBencodedString();
            }
            return u + "e";
        }
    }

Revision: 29184
at July 23, 2010 09:46 by SuprDewd


Initial Code
public class BencodeDecoder
    {
        public BencodeDecoder(string s)
        {
            BencodedString = s;
        }

        private int Index = 0;
        private string BencodedString = null;

        public IBElement[] Decode()
        {
            List<IBElement> rootElements = new List<IBElement>();
            while (BencodedString.Length > Index)
            {
                rootElements.Add(ReadElement());
            }
            return rootElements.ToArray();
        }

        private IBElement ReadElement()
        {
            switch (BencodedString[Index])
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': return ReadString();
                case 'i': return ReadInt();
                case 'l': return ReadList();
                case 'd': return ReadDictionary();
                default: throw Error(new Exception());
            }
        }

        private IBElement ReadDictionary()
        {
            Index++;
            BDictionary dict = new BDictionary();
            try
            {
                while (BencodedString[Index] != 'e')
                {
                    BString K = ReadString();
                    IBElement V = ReadElement();
                    dict.Add(K, V);
                }
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            Index++;
            return dict;
        }

        private IBElement ReadList()
        {
            Index++;
            BList lst = new BList();
            try
            {
                while (BencodedString[Index] != 'e')
                {
                    lst.Add(ReadElement());
                }
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            Index++;
            return lst;
        }

        private BInteger ReadInt()
        {
            Index++;
            int end = BencodedString.IndexOf('e', Index);
            if (end == -1) throw Error(new Exception());
            long Integer = 0;
            try
            {
                Integer = Convert.ToInt64(BencodedString.Substring(Index, end - Index));
                Index = end + 1;
            }
            catch (Exception e)
            {
                throw Error(e);
            }
            return new BInteger(Integer);
        }

        private Exception Error(Exception e)
        {
            return new Exception("Bencoded string invalid", e);
        }

        private BString ReadString()
        {
            int length = 0;
            int semicolon = 0;
            try
            {
                semicolon = BencodedString.IndexOf(':', Index);
                if (semicolon == -1) throw Error(new Exception());
                length = Convert.ToInt32(BencodedString.Substring(Index, semicolon - Index));
            }
            catch (Exception e)
            {
                throw Error(e);
            }

            Index = semicolon + 1;
            int tmpIndex = Index;
            Index += length;
            try
            {
                return new BString(BencodedString.Substring(tmpIndex, length));
            }
            catch (Exception e)
            {
                throw Error(e);
            }
        }
    }

    public interface IBElement
    {
        string ToBencodedString();
    }

    public class BInteger : IBElement
    {
        //public int Value { get; set; }
        public long Value { get; set; }

        public BInteger(long value /*int value*/)
        {
            this.Value = value;
        }

        public string ToBencodedString()
        {
            return "i" + Value.ToString() + "e";
        }

        public override string ToString()
        {
            return this.Value.ToString();
        }
    }

    public class BString : IBElement
    {
        public string Value { get; set; }

        public BString(string value)
        {
            this.Value = value;
        }

        public string ToBencodedString()
        {
            return this.Value.Length + ":" + this.Value;
        }

        public override string ToString()
        {
            return this.Value.ToString();
        }
    }

    public class BList : List<IBElement>, IBElement
    {
        public string ToBencodedString()
        {
            string u = "l";
            foreach (IBElement element in base.ToArray())
            {
                u += element.ToBencodedString();
            }
            return u + "e";
        }
    }

    public class BDictionary : Dictionary<BString, IBElement>, IBElement
    {
        public string ToBencodedString()
        {
            string u = "d";
            for (int i = 0; i < base.Count; i++)
            {
                u += base.Keys.ElementAt(i).ToBencodedString();
                u += base.Values.ElementAt(i).ToBencodedString();
            }
            return u + "e";
        }
    }

Initial URL

                                

Initial Description
For those having trouble with encoding and decoding bencode, here is something to help you.

Initial Title
Bencoding encoder and decoder

Initial Tags
c#

Initial Language
C#