public void Peek() { var str = "Hello World!"; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) using (var bs = new BencodeStream(ms)) { Assert.AreEqual('H', bs.Peek()); } }
public void PeekAreChangedAfterRead() { var str = "abcdefghijkl"; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) using (var bs = new BencodeStream(ms)) { Assert.Equal('a', bs.Peek()); Assert.Equal('a', bs.Read()); Assert.Equal('b', bs.Peek()); Assert.Equal('b', bs.Read()); Assert.Equal('c', bs.Peek()); Assert.Equal('c', bs.Read()); Assert.Equal('d', bs.Peek()); Assert.Equal('d', bs.Read()); Assert.Equal('e', bs.Peek()); Assert.Equal('e', bs.Read()); } }
public void ReadPreviousUnaffectedByPeek() { var str = "Hello World!"; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) using (var bs = new BencodeStream(ms)) { bs.Read(1); Assert.AreEqual('H', bs.ReadPrevious()); Assert.AreEqual('e', bs.Peek()); Assert.AreEqual('H', bs.ReadPrevious()); } }
public void PeekUnnaffectedByReadPrevious() { var str = "abcdefghijkl"; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) using (var bs = new BencodeStream(ms)) { bs.Read(0); Assert.AreEqual('a', bs.Peek()); bs.ReadPrevious(); Assert.AreEqual('a', bs.Peek()); bs.Read(1); Assert.AreEqual('b', bs.Peek()); bs.ReadPrevious(); Assert.AreEqual('b', bs.Peek()); } }
public void PeekAtEndOfStreamThenReadSingleByte() { var str = "abcdefghijkl"; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) using (var bs = new BencodeStream(ms)) { bs.Read(12); Assert.AreEqual(-1, bs.Peek()); Assert.AreEqual(-1, bs.Read()); } }
public void PeekAreChangedAfterReadSingleByte() { var str = "abcdefghijkl"; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) using (var bs = new BencodeStream(ms)) { byte[] bytes; Assert.AreEqual('a', bs.Peek()); bytes = bs.Read(1); Assert.AreEqual('a', (char)bytes[0]); Assert.AreEqual('b', bs.Peek()); bytes = bs.Read(1); Assert.AreEqual('b', (char)bytes[0]); Assert.AreEqual('c', bs.Peek()); } }
public static BNumber DecodeNumber(BencodeStream stream) { if (stream == null) throw new ArgumentNullException("stream"); if (stream.Length < 3) throw new BencodeDecodingException<BNumber>("Minimum valid length of stream is 3 ('i0e').", stream.Position); // Numbers must start with 'i' if (stream.ReadChar() != 'i') throw new BencodeDecodingException<BNumber>(string.Format("Must begin with 'i' but began with '{0}'.", stream.ReadPreviousChar()), stream.Position); var isNegative = false; var digits = new List<char>(); while (stream.Peek() != 'e' && stream.Peek() != -1) { // We do not support numbers that cannot be stored as a long (Int64) if (digits.Count >= BNumber.MaxDigits) { throw new UnsupportedBencodeException( string.Format( "The number '{0}' has more than 19 digits and cannot be stored as a long (Int64) and therefore is not supported.", digits.AsString()), stream.Position); } var c = stream.ReadChar(); // There may be only one '-' if (c == '-' && !isNegative) { // '-' must be the first char after the beginning 'i' if (digits.Count > 0) throw new BencodeDecodingException<BNumber>("A '-' must be directly after 'i' and before any digits.", stream.Position); isNegative = true; continue; } // If it is not a digit at this point it is invalid if (!c.IsDigit()) throw new BencodeDecodingException<BNumber>(string.Format("Must only contain digits and a single prefixed '-'. Invalid character '{0}'", c), stream.Position); digits.Add(c); } // We need at least one digit if (digits.Count < 1) throw new BencodeDecodingException<BNumber>("It contains no digits.", stream.Position); // Leading zeros are not valid if (digits[0] == '0' && digits.Count > 1) throw new BencodeDecodingException<BNumber>("Leading '0's are not valid.", stream.Position); // '-0' is not valid either if (digits[0] == '0' && digits.Count == 1 && isNegative) throw new BencodeDecodingException<BNumber>("'-0' is not a valid number.", stream.Position); if (stream.ReadChar() != 'e') throw new BencodeDecodingException<BNumber>("Missing end character 'e'.", stream.Position); if (isNegative) digits.Insert(0, '-'); long number; if (!long.TryParse(digits.AsString(), out number)) { // This should only happen if the number is bigger than 9,223,372,036,854,775,807 (or smaller than the negative version) throw new UnsupportedBencodeException( string.Format( "The value {0} cannot be stored as a long (Int64) and is therefore not supported. The supported values range from {1:N0} to {2:N0}", digits.AsString(), long.MinValue, long.MaxValue), stream.Position); } return new BNumber(number); }
public static BList DecodeList(BencodeStream stream, Encoding encoding) { if (stream == null) throw new ArgumentNullException("stream"); if (encoding == null) throw new ArgumentNullException("encoding"); if (stream.Length < 2) throw new BencodeDecodingException<BList>("Minimum valid length is 2 (an empty list: 'le')", stream.Position); // Lists must start with 'l' if (stream.ReadChar() != 'l') throw new BencodeDecodingException<BList>(string.Format("Must begin with 'l' but began with '{0}'.", stream.ReadPreviousChar()), stream.Position); var list = new BList(); // Loop until next character is the end character 'e' or end of stream while (stream.Peek() != 'e' && stream.Peek() != -1) { // Decode next object in stream var bObject = Decode(stream, encoding); if (bObject == null) throw new BencodeDecodingException<BList>(string.Format("Invalid object beginning with '{0}'", stream.PeekChar()), stream.Position); list.Add(bObject); } if (stream.ReadChar() != 'e') throw new BencodeDecodingException<BList>("Missing end character 'e'.", stream.Position); return list; }
public static BDictionary DecodeDictionary(BencodeStream stream, Encoding encoding) { if (stream == null) throw new ArgumentNullException("stream"); if (encoding == null) throw new ArgumentNullException("encoding"); var startPosition = stream.Position; if (stream.Length < 2) throw new BencodeDecodingException<BDictionary>("Minimum valid length is 2 (an empty dictionary: 'de')", startPosition); // Dictionaries must start with 'd' if (stream.ReadChar() != 'd') throw new BencodeDecodingException<BDictionary>(string.Format("Must begin with 'd' but began with '{0}'", stream.ReadPreviousChar()), startPosition); var dictionary = new BDictionary(); // Loop until next character is the end character 'e' or end of stream while (stream.Peek() != 'e' && stream.Peek() != -1) { // Decode next string in stream as the key BString key; try { key = DecodeString(stream, encoding); } catch (BencodeDecodingException<BString> ex) { throw new BencodeDecodingException<BDictionary>("Dictionary keys must be strings.", stream.Position); } // Decode next object in stream as the value var value = Decode(stream, encoding); if (value == null) throw new BencodeDecodingException<BDictionary>("All keys must have a corresponding value.", stream.Position); dictionary.Add(key, value); } if (stream.ReadChar() != 'e') throw new BencodeDecodingException<BDictionary>("Missing end character 'e'.", stream.Position); return dictionary; }
public void PeekDoesNotAdvanceStreamPosition() { var str = "Hello World!"; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) using (var bs = new BencodeStream(ms)) { Assert.Equal(0, bs.Position); Assert.Equal('H', bs.Peek()); Assert.Equal(0, bs.Position); Assert.Equal('H', bs.Peek()); Assert.Equal(0, bs.Position); } }