X-Git-Url: http://www.lcore.org/git/lcore.git/blobdiff_plain/e27ef2c6aab3a2a8051314bd37bb3b2386775f36..3bf8ed9f9545a956985b6c3c0658893910e01f75:/readtxt2.pas?ds=inline diff --git a/readtxt2.pas b/readtxt2.pas index a5f7de4..e7ac690 100644 --- a/readtxt2.pas +++ b/readtxt2.pas @@ -22,30 +22,34 @@ uses const bufsize=4096; eoltype_none=0; + eoltype_any=0; eoltype_cr=1; eoltype_lf=2; eoltype_crlf=3; type treadtxt=class(tobject) + private + buf:array[0..bufsize-1] of byte; + numread:integer; + bufpointer:integer; + currenteol,preveol:integer; + fileeof,reachedeof:boolean; + fdetectedeol:integer; + procedure checkandread; public sourcestream:tstream; destroysourcestream:boolean; + allowedeol:integer; constructor create(asourcestream: tstream; adestroysourcestream:boolean); constructor createf(filename : string); function readline:ansistring; function eof:boolean; destructor destroy; override; - private - buf:array[0..bufsize-1] of byte; - numread:integer; - bufpointer:integer; - currenteol,preveol:integer; - fileeof,reachedeof:boolean; - eoltype:integer; + property detectedeol : integer read fdetectedeol; end; - + implementation constructor treadtxt.create(asourcestream: tstream; adestroysourcestream:boolean); @@ -54,39 +58,74 @@ begin sourcestream := asourcestream; destroysourcestream := adestroysourcestream; - if sourcestream.Position >= sourcestream.size then fileeof := true; + //if sourcestream.Position >= sourcestream.size then fileeof := true; bufpointer := bufsize; - destroysourcestream := false; end; constructor treadtxt.createf(filename: string); begin - create(tfilestream.create(filename,fmOpenRead),true); + create(tfilestream.create(filename,fmOpenRead or fmShareDenyWrite),true); end; +procedure treadtxt.checkandread; +begin + if bufpointer >= numread then begin + numread := sourcestream.read(buf,bufsize); + bufpointer := 0; + if numread = 0 then fileeof := true; + + end; +end; + function treadtxt.readline; var a,b,c,d:integer; + prevchar : integer; + trimchar : boolean; begin - + prevchar := 0; result := ''; repeat - if bufpointer >= bufsize then begin - numread := sourcestream.read(buf,bufsize); - bufpointer := 0; - if sourcestream.Position >= sourcestream.size then fileeof := true; - end; + checkandread; b := numread-1; - + trimchar := false; {core search loop begin} d := -1; for a := bufpointer to b do begin c := buf[a]; - if (c = 10) or (c = 13) then begin - d := a; - break; + //check if the character can possibly be a line ending before getting + //into the more complex checks that depend on eol type + if (c = 10) or (c = 13) then case allowedeol of + eoltype_any: begin + d := a; + break; + end; + eoltype_cr: begin + if (c = 13) then begin + d := a; + break; + end; + end; + eoltype_lf: begin + if (c = 10) then begin + d := a; + break; + end; + end; + eoltype_crlf: begin + if (c = 10) and (prevchar= 13) then begin + d := a; + trimchar := true; + break; + end; + prevchar := c; + end; + else begin + raise exception.create('undefined eol type set'); + end; end; + prevchar := c; end; {core search loop end} @@ -97,7 +136,8 @@ begin setlength(result,c+b); move(buf[bufpointer],result[c+1],b); bufpointer := numread; - if numread < bufsize then begin + if fileeof then begin + {we reached the end of the file, return what we have} reachedeof := true; exit; end; @@ -107,18 +147,24 @@ begin currenteol := buf[d]; {end of line before end of buffer} - if (currenteol = 10) and (preveol = 13) then begin + if (currenteol = 10) and (preveol = 13) and (bufpointer = d) then begin {it's the second EOL char of a DOS line ending, don't cause a line} bufpointer := d+1; - eoltype := eoltype_crlf; + fdetectedeol := eoltype_crlf; end else begin - if eoltype = eoltype_none then begin - if (currenteol = 10) then eoltype := eoltype_lf else eoltype := eoltype_cr; + if fdetectedeol = eoltype_none then begin + if (currenteol = 10) then fdetectedeol := eoltype_lf else fdetectedeol := eoltype_cr; end; b := d-bufpointer; - setlength(result,c+b); - move(buf[bufpointer],result[c+1],b); - bufpointer := d+1; + if trimchar then begin + setlength(result,c+b-1); + move(buf[bufpointer],result[c+1],b-1); + bufpointer := d+1; + end else begin + setlength(result,c+b); + move(buf[bufpointer],result[c+1],b); + bufpointer := d+1; + end; {EOF check} if fileeof then begin @@ -134,8 +180,8 @@ end; function treadtxt.eof:boolean; begin - - result := ((bufpointer >= bufsize) and fileeof) or reachedeof; + checkandread; + result := ((bufpointer >= numread) and fileeof) or reachedeof; end; destructor treadtxt.destroy;