April 06, 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1106

           Summary: Using Stream.readLine() and Stream.read(ubyte[])
                    requires understanding implementation details
           Product: D
           Version: 1.009
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Phobos
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: digitalmars-com@baysmith.com


There is a bug in the Stream class. If you mix, readLine() and read(ubyte[])
calls to a stream, readLine() may not appear to perform as documented. As
documented, readLine() stop at "some combination of carriage return [CR] and
line feed [LF]". However, this is not necessarily true. If the stream is
non-seekable, readLine() will stop at CR and set a prevCr flag indicating that
a LF should be consumed on the next read. However, this only takes place in the
getc() method and methods using getc(). Some methods, like read(ubyte[]), read
the stream directly and the prevCr flag is not processed.

At first, I thought this might just be odd behavior rather than a bug, but I decided that it is a bug. In order to understand how to use the stream effectively, one must understand the implementation details. One must know that the behavior for seekable streams is different that non-seekable streams, and adjust the client code accordingly. For this reason, it should be considered a bug.

Code example:
import std.stream;

void main() {
  char[] testString = "line one\r\nline two\r\n";
  File testFile = new File("testFile", FileMode.OutNew);
  testFile.writeString(testString);
  testFile.close();

  File input = new File("testFile", FileMode.In);
  input.seekable = false;
  char[] line1 = input.readLine();
  assert(line1 == "line one");  // correct
  ubyte[1] b;
  input.read(b);
  assert(b[0] == '\n');  // incorrect
}


--