Faster Files.Read, Files.Readline, Strings.Length

This commit is contained in:
Dave Brown 2019-11-11 12:56:43 +00:00
parent 2ddbf5d517
commit 20943d67db
2 changed files with 57 additions and 24 deletions

69
src/runtime/Files.Mod Normal file → Executable file
View file

@ -398,18 +398,23 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
PROCEDURE Read* (VAR r: Rider; VAR x: SYSTEM.BYTE);
VAR offset: LONGINT; buf: Buffer;
BEGIN
buf := r.buf; offset := r.offset;
IF r.org # buf.org THEN
Set(r, buf.f, r.org + offset); buf := r.buf; offset := r.offset
END;
Assert(offset <= buf.size);
IF (offset < buf.size) THEN
x := buf.data[offset]; r.offset := offset + 1
ELSIF r.org + offset < buf.f.len THEN
Set(r, r.buf.f, r.org + offset);
x := r.buf.data[0]; r.offset := 1
ELSE
x := 0X; r.eof := TRUE
IF (r.org = r.buf.org) & (r.offset < r.buf.size) THEN (* Fast case *)
x := r.buf.data[r.offset];
INC(r.offset)
ELSE (* Slow case *)
buf := r.buf; offset := r.offset;
IF r.org # buf.org THEN
Set(r, buf.f, r.org + offset); buf := r.buf; offset := r.offset
END;
Assert(offset <= buf.size);
IF (offset < buf.size) THEN
x := buf.data[offset]; r.offset := offset + 1
ELSIF r.org + offset < buf.f.len THEN
Set(r, r.buf.f, r.org + offset);
x := r.buf.data[0]; r.offset := 1
ELSE
x := 0X; r.eof := TRUE
END
END
END Read;
@ -635,15 +640,43 @@ Especially Length would become fairly complex.
REPEAT Read(R, ch); x[i] := ch; INC(i) UNTIL ch = 0X
END ReadString;
PROCEDURE ReadLine* (VAR R: Rider; VAR x: ARRAY OF CHAR);
VAR i: INTEGER;
PROCEDURE ReadLine* (VAR r: Rider; VAR x: ARRAY OF CHAR);
VAR i: INTEGER; offset, limit: LONGINT; buffer: Buffer; eoln: BOOLEAN; ch: CHAR;
BEGIN
i := 0; REPEAT Read(R, x[i]); INC(i) UNTIL (x[i-1] = 0X) OR (x[i-1] = 0AX);
IF x[i-1] = 0AX THEN DEC(i) END; (* Omit trailing LF *)
IF (i > 0) & (x[i-1] = 0DX) THEN DEC(i) END; (* Also omit preceeding trailing CR if present. *)
x[i] := 0X; (* Guarantee zero termination. *)
i := 0; limit := LEN(x)-1;
offset := r.offset; buffer := r.buf;
eoln := r.eof OR (limit = 0);
WHILE ~eoln DO
IF (r.org # buffer.org) OR (offset >= buffer.size) THEN (* Refresh buffer *)
IF r.org + offset < buffer.f.len THEN
Set(r, buffer.f, r.org+offset);
offset := r.offset; buffer := r.buf; eoln := r.eof;
ELSE
r.eof := TRUE; eoln := TRUE;
END
END;
WHILE (offset < buffer.size) & ~eoln DO
ch := SYSTEM.VAL(CHAR, buffer.data[offset]); INC(offset);
IF (ch # 0X) & (ch # 0AX) THEN
x[i] := ch; INC(i); eoln := i >= limit
ELSE
eoln := TRUE
END
END;
r.offset := offset;
IF i=limit THEN eoln := TRUE END
END;
IF (i>0) & (x[i-1] = 0DX) THEN DEC(i) END; (* Exclude CR if present at eol *)
x[i] := 0X
END ReadLine;
(* old readline code:
REPEAT Read(R, x[i]); INC(i) UNTIL (x[i-1] = 0X) OR (x[i-1] = 0AX);
IF x[i-1] = 0AX THEN DEC(i) END; ( * Omit trailing LF * )
IF (i > 0) & (x[i-1] = 0DX) THEN DEC(i) END; ( * Also omit preceeding trailing CR if present. * )
x[i] := 0X; ( * Guarantee zero termination. * )
*)
PROCEDURE ReadNum*(VAR R: Rider; VAR x: ARRAY OF SYSTEM.BYTE);
VAR s, b: SYSTEM.INT8; q: SYSTEM.INT64;
BEGIN s := 0; q := 0; Read(R, b);

12
src/runtime/Strings.Mod Normal file → Executable file
View file

@ -29,9 +29,9 @@ Strings.Cap(s)
-------------------------------------------------------------*)
(* added from trianus v4 *)
MODULE Strings; (*HM 94-06-22 / *) (* noch 2017-06-21 *)
IMPORT Reals;
IMPORT Reals, SYSTEM;
PROCEDURE Length* (s: ARRAY OF CHAR): INTEGER;
PROCEDURE Length* (s: ARRAY [1] OF CHAR): INTEGER;
VAR i: LONGINT;
BEGIN
i := 0; WHILE (i < LEN(s)) & (s[i] # 0X) DO INC(i) END;
@ -160,14 +160,14 @@ BEGIN
WHILE (s[p] = " ") OR (s[p] = "0") DO INC(p) END;
IF s[p] = "-" THEN neg := TRUE; INC(p) ELSE neg := FALSE END;
WHILE (s[p] = " ") OR (s[p] = "0") DO INC(p) END;
y := 0;
WHILE ("0" <= s[p]) & (s[p] <= "9") DO
y := y * 10 + (ORD(s[p]) - 30H);
INC(p);
END;
IF s[p] = "." THEN
INC(p); g := 1;
INC(p); g := 1;
WHILE ("0" <= s[p]) & (s[p] <= "9") DO
g := g / 10; y := y + g * (ORD(s[p]) - 30H);
INC(p);
@ -195,14 +195,14 @@ BEGIN
WHILE (s[p] = " ") OR (s[p] = "0") DO INC(p) END;
IF s[p] = "-" THEN neg := TRUE; INC(p) ELSE neg := FALSE END;
WHILE (s[p] = " ") OR (s[p] = "0") DO INC(p) END;
y := 0;
WHILE ("0" <= s[p]) & (s[p] <= "9") DO
y := y * 10 + (ORD(s[p]) - 30H);
INC(p);
END;
IF s[p] = "." THEN
INC(p); g := 1;
INC(p); g := 1;
WHILE ("0" <= s[p]) & (s[p] <= "9") DO
g := g / 10; y := y + g * (ORD(s[p]) - 30H);
INC(p);