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#