1 { Copyright (C) 2009 Bas Steendijk and Peter Green
\r
2 For conditions of distribution and use, see copyright notice in zlib_license.txt
\r
3 which is included in the package
\r
4 ----------------------------------------------------------------------------- }
\r
14 this can be used to read a text file exposed as a tstream line by line.
\r
15 automatic handling of CR, LF, and CRLF line endings, and readout of detected line ending type.
\r
16 fast: 1.5-2 times faster than textfile readln in tests.
\r
30 treadtxt=class(tobject)
\r
32 sourcestream:tstream;
\r
33 destroysourcestream:boolean;
\r
34 constructor create(asourcestream: tstream; adestroysourcestream:boolean);
\r
35 constructor createf(filename : string);
\r
37 function readline:ansistring;
\r
38 function eof:boolean;
\r
39 destructor destroy; override;
\r
41 buf:array[0..bufsize-1] of byte;
\r
44 currenteol,preveol:integer;
\r
45 fileeof,reachedeof:boolean;
\r
51 constructor treadtxt.create(asourcestream: tstream; adestroysourcestream:boolean);
\r
54 sourcestream := asourcestream;
\r
55 destroysourcestream := adestroysourcestream;
\r
57 if sourcestream.Position >= sourcestream.size then fileeof := true;
\r
58 bufpointer := bufsize;
\r
61 constructor treadtxt.createf(filename: string);
\r
63 create(tfilestream.create(filename,fmOpenRead),true);
\r
67 function treadtxt.readline;
\r
74 if bufpointer >= bufsize then begin
\r
75 numread := sourcestream.read(buf,bufsize);
\r
77 if sourcestream.Position >= sourcestream.size then fileeof := true;
\r
81 {core search loop begin}
\r
83 for a := bufpointer to b do begin
\r
85 if (c = 10) or (c = 13) then begin
\r
90 {core search loop end}
\r
92 c := length(result);
\r
93 if (d = -1) then begin
\r
94 {ran out of buffer before end of line}
\r
95 b := numread-bufpointer;
\r
96 setlength(result,c+b);
\r
97 move(buf[bufpointer],result[c+1],b);
\r
98 bufpointer := numread;
\r
99 if numread < bufsize then begin
\r
100 reachedeof := true;
\r
105 preveol := currenteol;
\r
106 currenteol := buf[d];
\r
108 {end of line before end of buffer}
\r
109 if (currenteol = 10) and (preveol = 13) then begin
\r
110 {it's the second EOL char of a DOS line ending, don't cause a line}
\r
112 eoltype := eoltype_crlf;
\r
114 if eoltype = eoltype_none then begin
\r
115 if (currenteol = 10) then eoltype := eoltype_lf else eoltype := eoltype_cr;
\r
118 setlength(result,c+b);
\r
119 move(buf[bufpointer],result[c+1],b);
\r
123 if fileeof then begin
\r
124 if (bufpointer >= numread) then reachedeof := true;
\r
125 if (currenteol = 13) and (bufpointer = numread-1) then if (buf[bufpointer] = 10) then reachedeof := true;
\r
134 function treadtxt.eof:boolean;
\r
137 result := ((bufpointer >= bufsize) and fileeof) or reachedeof;
\r
140 destructor treadtxt.destroy;
\r
142 if destroysourcestream then if assigned(sourcestream) then sourcestream.destroy;
\r