0,0 → 1,209 |
(* |
BSD 2-Clause License |
|
Copyright (c) 2018, Anton Krotov |
All rights reserved. |
*) |
|
MODULE TEXTDRV; |
|
IMPORT FILES, C := COLLECTIONS; |
|
|
CONST |
|
CR = 0DX; LF = 0AX; |
|
CHUNK = 1024 * 256; |
|
|
TYPE |
|
TEXT* = POINTER TO RECORD (C.ITEM) |
|
chunk: ARRAY CHUNK OF BYTE; |
pos, size: INTEGER; |
file: FILES.FILE; |
utf8: BOOLEAN; |
CR: BOOLEAN; |
|
line*, col*: INTEGER; |
eof*: BOOLEAN; |
eol*: BOOLEAN; |
|
open*: PROCEDURE (text: TEXT; name: ARRAY OF CHAR): BOOLEAN; |
peak*: PROCEDURE (text: TEXT): CHAR; |
nextc*: PROCEDURE (text: TEXT) |
|
END; |
|
|
VAR |
|
texts: C.COLLECTION; |
|
|
PROCEDURE reset (text: TEXT); |
BEGIN |
text.chunk[0] := 0; |
text.pos := 0; |
text.size := 0; |
text.file := NIL; |
text.utf8 := FALSE; |
text.CR := FALSE; |
text.line := 1; |
text.col := 1; |
text.eof := FALSE; |
text.eol := FALSE |
END reset; |
|
|
PROCEDURE peak (text: TEXT): CHAR; |
RETURN CHR(text.chunk[text.pos]) |
END peak; |
|
|
PROCEDURE load (text: TEXT); |
BEGIN |
IF ~text.eof THEN |
text.size := FILES.read(text.file, text.chunk, LEN(text.chunk)); |
text.pos := 0; |
IF text.size = 0 THEN |
text.eof := TRUE; |
text.chunk[0] := 0 |
END |
END |
END load; |
|
|
PROCEDURE next (text: TEXT); |
VAR |
c: CHAR; |
BEGIN |
IF text.pos < text.size - 1 THEN |
INC(text.pos) |
ELSE |
load(text) |
END; |
|
IF ~text.eof THEN |
|
c := peak(text); |
|
IF c = CR THEN |
INC(text.line); |
text.col := 0; |
text.eol := TRUE; |
text.CR := TRUE |
ELSIF c = LF THEN |
IF ~text.CR THEN |
INC(text.line); |
text.col := 0; |
text.eol := TRUE |
ELSE |
text.eol := FALSE |
END; |
text.CR := FALSE |
ELSE |
text.eol := FALSE; |
IF text.utf8 THEN |
IF (c < 80X) OR (c > 0BFX) THEN |
INC(text.col) |
END |
ELSE |
INC(text.col) |
END; |
text.CR := FALSE |
END |
|
END |
|
END next; |
|
|
PROCEDURE init (text: TEXT); |
BEGIN |
|
IF (text.pos = 0) & (text.size >= 3) THEN |
IF (text.chunk[0] = 0EFH) & |
(text.chunk[1] = 0BBH) & |
(text.chunk[2] = 0BFH) THEN |
text.pos := 3; |
text.utf8 := TRUE |
END |
END; |
|
IF text.size = 0 THEN |
text.chunk[0] := 0; |
text.size := 1; |
text.eof := FALSE |
END; |
|
text.line := 1; |
text.col := 1 |
|
END init; |
|
|
PROCEDURE open (text: TEXT; name: ARRAY OF CHAR): BOOLEAN; |
BEGIN |
ASSERT(text # NIL); |
|
reset(text); |
text.file := FILES.open(name); |
IF text.file # NIL THEN |
load(text); |
init(text) |
END |
|
RETURN text.file # NIL |
END open; |
|
|
PROCEDURE NewText (): TEXT; |
VAR |
text: TEXT; |
citem: C.ITEM; |
|
BEGIN |
citem := C.pop(texts); |
IF citem = NIL THEN |
NEW(text) |
ELSE |
text := citem(TEXT) |
END |
|
RETURN text |
END NewText; |
|
|
PROCEDURE create* (): TEXT; |
VAR |
text: TEXT; |
BEGIN |
text := NewText(); |
reset(text); |
text.open := open; |
text.peak := peak; |
text.nextc := next |
|
RETURN text |
END create; |
|
|
PROCEDURE destroy* (VAR text: TEXT); |
BEGIN |
IF text # NIL THEN |
IF text.file # NIL THEN |
FILES.close(text.file) |
END; |
|
C.push(texts, text); |
text := NIL |
END |
END destroy; |
|
|
BEGIN |
texts := C.create() |
END TEXTDRV. |