| ... | ... | @@ -449,7 +449,6 @@ pub fn readVecAll(r: *Reader, data: [][]u8) Error!void { |
| 449 | 449 | /// is returned instead. |
| 450 | 450 | /// |
| 451 | 451 | /// See also: |
| 452 | | /// * `peek` |
| 453 | 452 | /// * `toss` |
| 454 | 453 | pub fn peek(r: *Reader, n: usize) Error![]u8 { |
| 455 | 454 | try r.fill(n); |
| ... | ... | @@ -700,7 +699,7 @@ pub const DelimiterError = error{ |
| 700 | 699 | }; |
| 701 | 700 | |
| 702 | 701 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 703 | | /// `sentinel` is found, advancing the seek position. |
| 702 | /// `sentinel` is found, advancing the seek position past the sentinel. |
| 704 | 703 | /// |
| 705 | 704 | /// Returned slice has a sentinel. |
| 706 | 705 | /// |
| ... | ... | @@ -733,7 +732,7 @@ pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel |
| 733 | 732 | } |
| 734 | 733 | |
| 735 | 734 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 736 | | /// `delimiter` is found, advancing the seek position. |
| 735 | /// `delimiter` is found, advancing the seek position past the delimiter. |
| 737 | 736 | /// |
| 738 | 737 | /// Returned slice includes the delimiter as the last byte. |
| 739 | 738 | /// |
| ... | ... | @@ -786,7 +785,8 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 786 | 785 | } |
| 787 | 786 | |
| 788 | 787 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 789 | | /// `delimiter` is found, advancing the seek position. |
| 788 | /// `delimiter` is found, advancing the seek position up to (but not past) |
| 789 | /// the delimiter. |
| 790 | 790 | /// |
| 791 | 791 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent |
| 792 | 792 | /// to a delimiter, unless it would result in a length 0 return value, in which |
| ... | ... | @@ -800,20 +800,44 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 800 | 800 | /// Invalidates previously returned values from `peek`. |
| 801 | 801 | /// |
| 802 | 802 | /// See also: |
| 803 | /// * `takeDelimiter` |
| 803 | 804 | /// * `takeDelimiterInclusive` |
| 804 | 805 | /// * `peekDelimiterExclusive` |
| 805 | 806 | pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 806 | | const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { |
| 807 | const result = try r.peekDelimiterExclusive(delimiter); |
| 808 | r.toss(result.len); |
| 809 | return result; |
| 810 | } |
| 811 | |
| 812 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 813 | /// `delimiter` is found, advancing the seek position past the delimiter. |
| 814 | /// |
| 815 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent |
| 816 | /// to a delimiter, unless it would result in a length 0 return value, in which |
| 817 | /// case `null` is returned instead. |
| 818 | /// |
| 819 | /// If the delimiter is not found within a number of bytes matching the |
| 820 | /// capacity of this `Reader`, `error.StreamTooLong` is returned. In |
| 821 | /// such case, the stream state is unmodified as if this function was never |
| 822 | /// called. |
| 823 | /// |
| 824 | /// Invalidates previously returned values from `peek`. |
| 825 | /// |
| 826 | /// See also: |
| 827 | /// * `takeDelimiterInclusive` |
| 828 | /// * `takeDelimiterExclusive` |
| 829 | pub fn takeDelimiter(r: *Reader, delimiter: u8) error{ ReadFailed, StreamTooLong }!?[]u8 { |
| 830 | const inclusive = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { |
| 807 | 831 | error.EndOfStream => { |
| 808 | 832 | const remaining = r.buffer[r.seek..r.end]; |
| 809 | | if (remaining.len == 0) return error.EndOfStream; |
| 833 | if (remaining.len == 0) return null; |
| 810 | 834 | r.toss(remaining.len); |
| 811 | 835 | return remaining; |
| 812 | 836 | }, |
| 813 | 837 | else => |e| return e, |
| 814 | 838 | }; |
| 815 | | r.toss(result.len); |
| 816 | | return result[0 .. result.len - 1]; |
| 839 | r.toss(inclusive.len); |
| 840 | return inclusive[0 .. inclusive.len - 1]; |
| 817 | 841 | } |
| 818 | 842 | |
| 819 | 843 | /// Returns a slice of the next bytes of buffered data from the stream until |
| ... | ... | @@ -1336,6 +1360,9 @@ test peekSentinel { |
| 1336 | 1360 | var r: Reader = .fixed("ab\nc"); |
| 1337 | 1361 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); |
| 1338 | 1362 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); |
| 1363 | r.toss(3); |
| 1364 | try testing.expectError(error.EndOfStream, r.peekSentinel('\n')); |
| 1365 | try testing.expectEqualStrings("c", try r.peek(1)); |
| 1339 | 1366 | } |
| 1340 | 1367 | |
| 1341 | 1368 | test takeDelimiterInclusive { |
| ... | ... | @@ -1350,22 +1377,52 @@ test peekDelimiterInclusive { |
| 1350 | 1377 | try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n')); |
| 1351 | 1378 | r.toss(3); |
| 1352 | 1379 | try testing.expectError(error.EndOfStream, r.peekDelimiterInclusive('\n')); |
| 1380 | try testing.expectEqualStrings("c", try r.peek(1)); |
| 1353 | 1381 | } |
| 1354 | 1382 | |
| 1355 | 1383 | test takeDelimiterExclusive { |
| 1356 | 1384 | var r: Reader = .fixed("ab\nc"); |
| 1385 | |
| 1357 | 1386 | try testing.expectEqualStrings("ab", try r.takeDelimiterExclusive('\n')); |
| 1387 | try testing.expectEqualStrings("", try r.takeDelimiterExclusive('\n')); |
| 1388 | try testing.expectEqualStrings("", try r.takeDelimiterExclusive('\n')); |
| 1389 | try testing.expectEqualStrings("\n", try r.take(1)); |
| 1390 | |
| 1358 | 1391 | try testing.expectEqualStrings("c", try r.takeDelimiterExclusive('\n')); |
| 1359 | 1392 | try testing.expectError(error.EndOfStream, r.takeDelimiterExclusive('\n')); |
| 1360 | 1393 | } |
| 1361 | 1394 | |
| 1362 | 1395 | test peekDelimiterExclusive { |
| 1363 | 1396 | var r: Reader = .fixed("ab\nc"); |
| 1397 | |
| 1364 | 1398 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); |
| 1365 | 1399 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); |
| 1366 | | r.toss(3); |
| 1400 | r.toss(2); |
| 1401 | try testing.expectEqualStrings("", try r.peekDelimiterExclusive('\n')); |
| 1402 | try testing.expectEqualStrings("\n", try r.take(1)); |
| 1403 | |
| 1367 | 1404 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); |
| 1368 | 1405 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); |
| 1406 | r.toss(1); |
| 1407 | try testing.expectError(error.EndOfStream, r.peekDelimiterExclusive('\n')); |
| 1408 | } |
| 1409 | |
| 1410 | test takeDelimiter { |
| 1411 | var r: Reader = .fixed("ab\nc\n\nd"); |
| 1412 | try testing.expectEqualStrings("ab", (try r.takeDelimiter('\n')).?); |
| 1413 | try testing.expectEqualStrings("c", (try r.takeDelimiter('\n')).?); |
| 1414 | try testing.expectEqualStrings("", (try r.takeDelimiter('\n')).?); |
| 1415 | try testing.expectEqualStrings("d", (try r.takeDelimiter('\n')).?); |
| 1416 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| 1417 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| 1418 | |
| 1419 | r = .fixed("ab\nc\n\nd\n"); // one trailing newline does not affect behavior |
| 1420 | try testing.expectEqualStrings("ab", (try r.takeDelimiter('\n')).?); |
| 1421 | try testing.expectEqualStrings("c", (try r.takeDelimiter('\n')).?); |
| 1422 | try testing.expectEqualStrings("", (try r.takeDelimiter('\n')).?); |
| 1423 | try testing.expectEqualStrings("d", (try r.takeDelimiter('\n')).?); |
| 1424 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| 1425 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| 1369 | 1426 | } |
| 1370 | 1427 | |
| 1371 | 1428 | test streamDelimiter { |