mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-30 09:54:49 +00:00
258 lines
6.1 KiB
ObjectPascal
258 lines
6.1 KiB
ObjectPascal
//
|
|
//
|
|
// The Nimrod Compiler
|
|
// (c) Copyright 2009 Andreas Rumpf
|
|
//
|
|
// See the file "copying.txt", included in this
|
|
// distribution, for details about the copyright.
|
|
//
|
|
unit llstream;
|
|
|
|
// Low-level streams for high performance.
|
|
|
|
interface
|
|
|
|
uses
|
|
nsystem, charsets, strutils;
|
|
|
|
type
|
|
TLLStreamKind = (
|
|
llsNone, // null stream: reading and writing has no effect
|
|
llsString, // stream encapsulates a string
|
|
llsFile, // stream encapsulates a file
|
|
llsStdIn); // stream encapsulates stdin
|
|
TLLStream = object(NObject)
|
|
kind: TLLStreamKind; // accessible for low-level access (lexbase uses this)
|
|
f: TBinaryFile;
|
|
s: string;
|
|
rd, wr: int; // for string streams
|
|
end;
|
|
PLLStream = ^TLLStream;
|
|
|
|
|
|
function LLStreamOpen(const data: string): PLLStream; overload;
|
|
function LLStreamOpen(var f: TBinaryFile): PLLStream; overload;
|
|
function LLStreamOpen(const filename: string; mode: TFileMode): PLLStream; overload;
|
|
function LLStreamOpen(): PLLStream; overload;
|
|
function LLStreamOpenStdIn(): PLLStream;
|
|
|
|
procedure LLStreamClose(s: PLLStream);
|
|
|
|
function LLStreamRead(s: PLLStream; buf: pointer; bufLen: int): int;
|
|
function LLStreamReadLine(s: PLLStream): string;
|
|
function LLStreamReadAll(s: PLLStream): string;
|
|
|
|
procedure LLStreamWrite(s: PLLStream; const data: string); overload;
|
|
procedure LLStreamWrite(s: PLLStream; data: Char); overload;
|
|
procedure LLStreamWrite(s: PLLStream; buf: pointer; buflen: int); overload;
|
|
|
|
procedure LLStreamWriteln(s: PLLStream; const data: string);
|
|
|
|
function LLStreamAtEnd(s: PLLStream): bool;
|
|
|
|
implementation
|
|
|
|
function LLStreamOpen(const data: string): PLLStream; overload;
|
|
begin
|
|
new(result);
|
|
{@ignore}
|
|
fillChar(result^, sizeof(result^), 0);
|
|
{@emit}
|
|
result.s := data;
|
|
result.kind := llsString;
|
|
end;
|
|
|
|
function LLStreamOpen(var f: TBinaryFile): PLLStream; overload;
|
|
begin
|
|
new(result);
|
|
{@ignore}
|
|
fillChar(result^, sizeof(result^), 0);
|
|
{@emit}
|
|
result.f := f;
|
|
result.kind := llsFile;
|
|
end;
|
|
|
|
function LLStreamOpen(const filename: string; mode: TFileMode): PLLStream; overload;
|
|
begin
|
|
new(result);
|
|
{@ignore}
|
|
fillChar(result^, sizeof(result^), 0);
|
|
{@emit}
|
|
result.kind := llsFile;
|
|
if not OpenFile(result.f, filename, mode) then result := nil;
|
|
end;
|
|
|
|
function LLStreamOpen(): PLLStream; overload;
|
|
begin
|
|
new(result);
|
|
{@ignore}
|
|
fillChar(result^, sizeof(result^), 0);
|
|
{@emit}
|
|
result.kind := llsNone;
|
|
end;
|
|
|
|
function LLStreamOpenStdIn(): PLLStream;
|
|
begin
|
|
new(result);
|
|
{@ignore}
|
|
fillChar(result^, sizeof(result^), 0);
|
|
{@emit}
|
|
result.kind := llsStdIn;
|
|
result.s := '';
|
|
end;
|
|
|
|
procedure LLStreamClose(s: PLLStream);
|
|
begin
|
|
case s.kind of
|
|
llsNone, llsString, llsStdIn: begin end;
|
|
llsFile: nimCloseFile(s.f);
|
|
end
|
|
end;
|
|
|
|
function LLreadFromStdin(s: PLLStream; buf: pointer; bufLen: int): int;
|
|
var
|
|
line: string;
|
|
L: int;
|
|
begin
|
|
s.s := '';
|
|
s.rd := 0;
|
|
while true do begin
|
|
write(output, 'Nimrod> ');
|
|
line := readLine(input);
|
|
L := length(line);
|
|
add(s.s, line);
|
|
add(s.s, nl);
|
|
if (L > 0) and (line[L-1+strStart] = '#') then break;
|
|
end;
|
|
result := min(bufLen, length(s.s)-s.rd);
|
|
if result > 0 then begin
|
|
copyMem(buf, addr(s.s[strStart+s.rd]), result);
|
|
inc(s.rd, result)
|
|
end
|
|
end;
|
|
|
|
function LLStreamRead(s: PLLStream; buf: pointer; bufLen: int): int;
|
|
begin
|
|
case s.kind of
|
|
llsNone: result := 0;
|
|
llsString: begin
|
|
result := min(bufLen, length(s.s)-s.rd);
|
|
if result > 0 then begin
|
|
copyMem(buf, addr(s.s[strStart+s.rd]), result);
|
|
inc(s.rd, result)
|
|
end
|
|
end;
|
|
llsFile: result := readBuffer(s.f, buf, bufLen);
|
|
llsStdIn: result := LLreadFromStdin(s, buf, bufLen);
|
|
end
|
|
end;
|
|
|
|
function LLStreamReadLine(s: PLLStream): string;
|
|
begin
|
|
case s.kind of
|
|
llsNone: result := '';
|
|
llsString: begin
|
|
result := '';
|
|
while s.rd < length(s.s) do begin
|
|
case s.s[s.rd+strStart] of
|
|
#13: begin
|
|
inc(s.rd);
|
|
if s.s[s.rd+strStart] = #10 then inc(s.rd);
|
|
break
|
|
end;
|
|
#10: begin inc(s.rd); break end;
|
|
else begin
|
|
addChar(result, s.s[s.rd+strStart]);
|
|
inc(s.rd);
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
llsFile: result := readLine(s.f);
|
|
llsStdIn: result := readLine(input);
|
|
end
|
|
end;
|
|
|
|
function LLStreamAtEnd(s: PLLStream): bool;
|
|
begin
|
|
case s.kind of
|
|
llsNone: result := true;
|
|
llsString: result := s.rd >= length(s.s);
|
|
llsFile: result := endOfFile(s.f);
|
|
llsStdIn: result := false;
|
|
end
|
|
end;
|
|
|
|
procedure LLStreamWrite(s: PLLStream; const data: string); overload;
|
|
begin
|
|
case s.kind of
|
|
llsNone, llsStdIn: begin end;
|
|
llsString: begin add(s.s, data); inc(s.wr, length(data)) end;
|
|
llsFile: nimWrite(s.f, data);
|
|
end;
|
|
end;
|
|
|
|
procedure LLStreamWriteln(s: PLLStream; const data: string);
|
|
begin
|
|
LLStreamWrite(s, data);
|
|
LLStreamWrite(s, nl);
|
|
end;
|
|
|
|
procedure LLStreamWrite(s: PLLStream; data: Char); overload;
|
|
var
|
|
c: char;
|
|
begin
|
|
case s.kind of
|
|
llsNone, llsStdIn: begin end;
|
|
llsString: begin addChar(s.s, data); inc(s.wr); end;
|
|
llsFile: begin
|
|
c := data;
|
|
{@discard} writeBuffer(s.f, addr(c), sizeof(c));
|
|
end
|
|
end
|
|
end;
|
|
|
|
procedure LLStreamWrite(s: PLLStream; buf: pointer; buflen: int); overload;
|
|
begin
|
|
case s.kind of
|
|
llsNone, llsStdIn: begin end;
|
|
llsString: begin
|
|
if bufLen > 0 then begin
|
|
setLength(s.s, length(s.s) + bufLen);
|
|
copyMem(addr(s.s[strStart+s.wr]), buf, bufLen);
|
|
inc(s.wr, bufLen);
|
|
end
|
|
end;
|
|
llsFile: {@discard} writeBuffer(s.f, buf, bufLen);
|
|
end
|
|
end;
|
|
|
|
function LLStreamReadAll(s: PLLStream): string;
|
|
const
|
|
bufSize = 2048;
|
|
var
|
|
bytes, i: int;
|
|
begin
|
|
case s.kind of
|
|
llsNone, llsStdIn: result := '';
|
|
llsString: begin
|
|
if s.rd = 0 then result := s.s
|
|
else result := ncopy(s.s, s.rd+strStart);
|
|
s.rd := length(s.s);
|
|
end;
|
|
llsFile: begin
|
|
result := newString(bufSize);
|
|
bytes := readBuffer(s.f, addr(result[strStart]), bufSize);
|
|
i := bytes;
|
|
while bytes = bufSize do begin
|
|
setLength(result, i+bufSize);
|
|
bytes := readBuffer(s.f, addr(result[i+strStart]), bufSize);
|
|
inc(i, bytes);
|
|
end;
|
|
setLength(result, i);
|
|
end
|
|
end
|
|
end;
|
|
|
|
end.
|