Skip to content

Commit eb6587f

Browse files
committed
Refactored DecodeNumber a bit
1 parent 9ac74b5 commit eb6587f

File tree

2 files changed

+30
-46
lines changed

2 files changed

+30
-46
lines changed

BencodeNET.Net45/Bencode.cs

Lines changed: 24 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -232,69 +232,53 @@ public static BNumber DecodeNumber(BencodeStream stream)
232232
if (stream.Length < 3)
233233
throw new BencodeDecodingException<BNumber>("Minimum valid length of stream is 3 ('i0e').", stream.Position);
234234

235+
var startPosition = stream.Position;
236+
235237
// Numbers must start with 'i'
236238
if (stream.ReadChar() != 'i')
237239
throw new BencodeDecodingException<BNumber>(string.Format("Must begin with 'i' but began with '{0}'.", stream.ReadPreviousChar()), stream.Position);
238240

239-
var isNegative = false;
240241
var digits = new StringBuilder();
241242
while (stream.Peek() != 'e' && stream.Peek() != -1)
242243
{
243-
// We do not support numbers that cannot be stored as a long (Int64)
244-
if (digits.Length >= BNumber.MaxDigits)
245-
{
246-
throw new UnsupportedBencodeException(
247-
string.Format(
248-
"The number '{0}' has more than 19 digits and cannot be stored as a long (Int64) and therefore is not supported.",
249-
digits),
250-
stream.Position);
251-
}
252-
253-
var c = stream.ReadChar();
254-
255-
// There may be only one '-'
256-
if (c == '-' && !isNegative)
257-
{
258-
// '-' must be the first char after the beginning 'i'
259-
if (digits.Length > 0)
260-
throw new BencodeDecodingException<BNumber>("A '-' must be directly after 'i' and before any digits.", stream.Position);
261-
262-
isNegative = true;
263-
continue;
264-
}
244+
digits.Append(stream.ReadChar());
245+
}
265246

266-
// If it is not a digit at this point it is invalid
267-
if (!c.IsDigit())
268-
throw new BencodeDecodingException<BNumber>(string.Format("Must only contain digits and a single prefixed '-'. Invalid character '{0}'", c), stream.Position);
247+
var isNegative = digits[0] == '-';
248+
var numberOfDigits = isNegative ? digits.Length - 1 : digits.Length;
269249

270-
digits.Append(c);
250+
// We do not support numbers that cannot be stored as a long (Int64)
251+
if (numberOfDigits > BNumber.MaxDigits)
252+
{
253+
throw new UnsupportedBencodeException(
254+
string.Format(
255+
"The number '{0}' has more than 19 digits and cannot be stored as a long (Int64) and therefore is not supported.",
256+
digits),
257+
stream.Position);
271258
}
272259

273260
// We need at least one digit
274-
if (digits.Length < 1)
275-
throw new BencodeDecodingException<BNumber>("It contains no digits.", stream.Position);
261+
if (numberOfDigits < 1)
262+
throw new BencodeDecodingException<BNumber>("It contains no digits.", startPosition);
263+
264+
var firstDigit = isNegative ? digits[1] : digits[0];
276265

277266
// Leading zeros are not valid
278-
if (digits[0] == '0' && digits.Length > 1)
279-
throw new BencodeDecodingException<BNumber>("Leading '0's are not valid.", stream.Position);
267+
if (firstDigit == '0' && numberOfDigits > 1)
268+
throw new BencodeDecodingException<BNumber>("Leading '0's are not valid.", startPosition);
280269

281270
// '-0' is not valid either
282-
if (digits[0] == '0' && digits.Length == 1 && isNegative)
283-
throw new BencodeDecodingException<BNumber>("'-0' is not a valid number.", stream.Position);
271+
if (firstDigit == '0' && numberOfDigits == 1 && isNegative)
272+
throw new BencodeDecodingException<BNumber>("'-0' is not a valid number.", startPosition);
284273

285274
if (stream.ReadChar() != 'e')
286275
throw new BencodeDecodingException<BNumber>("Missing end character 'e'.", stream.Position);
287276

288-
if (isNegative)
289-
digits.Insert(0, '-');
290-
291277
long number;
292278
if (!long.TryParse(digits.ToString(), out number))
293279
{
294-
// This should only happen if the number is bigger than 9,223,372,036,854,775,807 (or smaller than the negative version)
295-
throw new UnsupportedBencodeException(
296-
string.Format(
297-
"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}",
280+
throw new BencodeDecodingException<BNumber>(
281+
string.Format("The value '{0}' is invalid. Supported values range from {1:N0} to {2:N0}",
298282
digits, long.MinValue, long.MaxValue),
299283
stream.Position);
300284
}

BencodeNET.Tests/BencodeDecodeNumberTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,21 @@ public void DecodeNumber_Invalid_NegativeSignInsideNumber()
9696
}
9797

9898
[Fact]
99-
public void DecodeNumber_Unsupported_GreaterThanMaxDigits19()
99+
public void DecodeNumber_Invalid_BiggerThanInt64MaxValue()
100100
{
101-
Assert.Throws<UnsupportedBencodeException>(() => Bencode.DecodeNumber("i12345678901234567890e"));
101+
Assert.Throws<BencodeDecodingException<BNumber>>(() => Bencode.DecodeNumber("i9223372036854775808e"));
102102
}
103103

104104
[Fact]
105-
public void DecodeNumber_Unsupported_BiggerThanInt64MaxValue()
105+
public void DecodeNumber_Invalid_SmallerThanInt64MinValue()
106106
{
107-
Assert.Throws<UnsupportedBencodeException>(() => Bencode.DecodeNumber("i9223372036854775808e"));
107+
Assert.Throws<BencodeDecodingException<BNumber>>(() => Bencode.DecodeNumber("i-9223372036854775809e"));
108108
}
109109

110110
[Fact]
111-
public void DecodeNumber_Unsupported_SmallerThanInt64MinValue()
111+
public void DecodeNumber_Unsupported_GreaterThanMaxDigits19()
112112
{
113-
Assert.Throws<UnsupportedBencodeException>(() => Bencode.DecodeNumber("i-9223372036854775809e"));
113+
Assert.Throws<UnsupportedBencodeException>(() => Bencode.DecodeNumber("i12345678901234567890e"));
114114
}
115115
}
116116
}

0 commit comments

Comments
 (0)