Revision: 29200
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Updated Code
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
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
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#