@@ -683,25 +683,73 @@ test "import io tests" {
683
683
}
684
684
}
685
685
686
- pub fn readLine (buf : []u8 ) ! usize {
687
- var stdin = getStdIn () catch return error .StdInUnavailable ;
688
- var adapter = stdin .inStream ();
689
- var stream = & adapter .stream ;
690
- var index : usize = 0 ;
686
+ pub fn readLine (buf : * std.Buffer ) ! []u8 {
687
+ var stdin = try getStdIn ();
688
+ var stdin_stream = stdin .inStream ();
689
+ return readLineFrom (& stdin_stream .stream , buf );
690
+ }
691
+
692
+ /// Reads all characters until the next newline into buf, and returns
693
+ /// a slice of the characters read (excluding the newline character(s)).
694
+ pub fn readLineFrom (stream : var , buf : * std.Buffer ) ! []u8 {
695
+ const start = buf .len ();
691
696
while (true ) {
692
- const byte = stream .readByte () catch return error . EndOfFile ;
697
+ const byte = try stream .readByte ();
693
698
switch (byte ) {
694
699
'\r ' = > {
695
700
// trash the following \n
696
- _ = stream .readByte () catch return error .EndOfFile ;
697
- return index ;
698
- },
699
- '\n ' = > return index ,
700
- else = > {
701
- if (index == buf .len ) return error .InputTooLong ;
702
- buf [index ] = byte ;
703
- index += 1 ;
701
+ _ = try stream .readByte ();
702
+ return buf .toSlice ()[start .. ];
704
703
},
704
+ '\n ' = > return buf .toSlice ()[start .. ],
705
+ else = > try buf .appendByte (byte ),
705
706
}
706
707
}
707
708
}
709
+
710
+ test "io.readLineFrom" {
711
+ var bytes : [128 ]u8 = undefined ;
712
+ const allocator = & std .heap .FixedBufferAllocator .init (bytes [0.. ]).allocator ;
713
+
714
+ var buf = try std .Buffer .initSize (allocator , 0 );
715
+ var mem_stream = SliceInStream .init (
716
+ \\Line 1
717
+ \\Line 22
718
+ \\Line 333
719
+ );
720
+ const stream = & mem_stream .stream ;
721
+
722
+ debug .assert (mem .eql (u8 , "Line 1" , try readLineFrom (stream , & buf )));
723
+ debug .assert (mem .eql (u8 , "Line 22" , try readLineFrom (stream , & buf )));
724
+ debug .assertError (readLineFrom (stream , & buf ), error .EndOfStream );
725
+ debug .assert (mem .eql (u8 , buf .toSlice (), "Line 1Line 22Line 333" ));
726
+ }
727
+
728
+ pub fn readLineSlice (slice : []u8 ) ! []u8 {
729
+ var stdin = try getStdIn ();
730
+ var stdin_stream = stdin .inStream ();
731
+ return readLineSliceFrom (& stdin_stream .stream , slice );
732
+ }
733
+
734
+ /// Reads all characters until the next newline into slice, and returns
735
+ /// a slice of the characters read (excluding the newline character(s)).
736
+ pub fn readLineSliceFrom (stream : var , slice : []u8 ) ! []u8 {
737
+ // We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte
738
+ // after taking ownership, which would always require an allocation.
739
+ var buf = std.Buffer { .list = std .ArrayList (u8 ).fromOwnedSlice (debug .failing_allocator , slice ) };
740
+ try buf .resize (0 );
741
+ return try readLineFrom (stream , & buf );
742
+ }
743
+
744
+ test "io.readLineSliceFrom" {
745
+ var buf : [7 ]u8 = undefined ;
746
+ var mem_stream = SliceInStream .init (
747
+ \\Line 1
748
+ \\Line 22
749
+ \\Line 333
750
+ );
751
+ const stream = & mem_stream .stream ;
752
+
753
+ debug .assert (mem .eql (u8 , "Line 1" , try readLineSliceFrom (stream , buf [0.. ])));
754
+ debug .assertError (readLineSliceFrom (stream , buf [0.. ]), error .OutOfMemory );
755
+ }
0 commit comments