include "sys.m"; # for Sys->OREAD, etc. include "bufio.m"; Iobuf: import Bufio; bufio:= load Bufio Bufio->PATH; SEEKSTART: con Sys->SEEKSTART; SEEKRELA: con Sys->SEEKRELA; SEEKEND: con Sys->SEEKEND; OREAD: con Sys->OREAD; OWRITE: con Sys->OWRITE; ORDWR: con Sys->ORDWR; EOF: con -1; ERROR: con -2; Iobuf: adt { seek: fn(b: self ref Iobuf, n, where: int): int; read: fn(b: self ref Iobuf, a: array of byte, n:int):int; write: fn(b: self ref Iobuf, a: array of byte, n:int):int; getb: fn(b: self ref Iobuf): int; ungetb:fn(b: self ref Iobuf): int; getc: fn(b: self ref Iobuf): int; ungetc:fn(b: self ref Iobuf): int; gets: fn(b: self ref Iobuf, sep: int): string; gett: fn(b: self ref Iobuf, sep: string): string; putb: fn(b: self ref Iobuf, b: byte): int; putc: fn(b: self ref Iobuf, c: int): int; puts: fn(b: self ref Iobuf, s: string): int; flush: fn(b: self ref Iobuf): int; close: fn(b: self ref Iobuf); }; # end of Iobuf declaration open: fn(name: string, mode: int): ref Iobuf; create: fn(name: string, mode, perm: int): ref Iobuf; fopen: fn(fd: ref Sys->FD, mode: int): ref Iobuf; flush: fn();
open: fn(name: string, mode: int): ref Iobuf;
## returns nil if unsuccessful.The open function takes two parameters, a filename and a mode. The mode must be one of OREAD, OWRITE, or ORDWR (defined to match the corresponding values in the
Sys
module). Both open
and fopen
return a ref Iobuf to be used in subsequent calls.
create: fn(name: string, mode, perm: int): ref Iobuf;
## returns nil if unsuccessful.The create function creates a new file or prepares to rewrite an existing file, and opens it according to mode (as described for open). It returns a ref Iobuf to be used in subsequent calls.
fopen: fn(fd: ref Sys->FD, mode: int): ref Iobuf;
## returns nil if unsuccessful.Buffered I/O on an already open file is made possible using fopen, which takes a file descriptor, fd, as its first argument and an open mode as its second argument. The mode of the file descriptor must be compatible with the mode passed to fopen.
flush: fn();The Bufio module keeps an internal reference to files opened for writing so that they can be flushed before being garbage collected. Flushing all dirty files must be done with an explicit call to flush(), usually just before exiting the program.
seek: fn(b: self ref Iobuf, n, where: int): int; read: fn(b: self ref Iobuf, a: array of byte, n:int):int; write: fn(b: self ref Iobuf, a: array of byte, n:int):int;Each function has parameters and return values analogous to its complement in the Sys module (see seek - change file offset and read, write, stream - read, write, or stream file in Chapter 8).
getb: fn(b: self ref Iobuf): int;
## returns a single byte (represented as an int); negative if unsuccessful.Read a single byte from the buffered stream and return its value as an int.
ungetb: fn(b: self ref Iobuf): int;
## returns 1 if successful, negative if unsuccessful.Put the last byte read back into the buffered stream, so that a subsequent getb will read it.
getc: fn(b: self ref Iobuf): int;
## returns single character (as int); negative on failure.Read a single Unicode character, encoded in UTF, and return its value as an int. (See UTF, Unicode, ASCII - character set and format in Appendix A.)
ungetc: fn(b: self ref Iobuf): int;
## returns 1 if successful, negative on failure.Put the last Unicode character read, encoded in UTF, back into the buffered stream so that a subsequent getc will read it.
gets: fn(b: self ref Iobuf, sep: int): string;
## returns nil if error or EOF.Read a line up to and including a character specified by sepchar, typically a newline. If none is found, read to the end of the file. The returned string includes the terminating character.
gett: fn(b: self ref Iobuf, sep: string): string;
## returns nil if error or EOF.Read characters until one of the characters in sepstr. The returned string includes the separator. If none of the separator characters is found, read to the end of the file.
putb: fn(b: self ref Iobuf, b: byte): int; putc: fn(b: self ref Iobuf, c: int): int; puts: fn(b: self ref Iobuf, s: string): int;
## returns putb and putc return 0 on success; negative on failure.Each function writes its respective argument: a byte (b), a Unicode character (c), or a string (s). Text is encoded in UTF.
puts returns len s on success; negative on failure.
flush: fn(b: self ref Iobuf): int;
## returns 0 on success; negative on failure.Flush remaining data in the buffer; if necessary. It is the programmer's responsibility to explicitly call flush() prior to exiting.
close: n(b: self ref Iobuf);Flush remaining data in the buffer; if necessary, close the associated file, and discard buffers associated with the file. After close, no further function calls are allowed on the Iobuf adt.
ref
type (create, open, fopen, gets, and gett) return nil when encountering end of file or errors. When an error occurs, the error string, printable with the %r format, will usually be set as a consequence of an error in the underlying Sys module. The other functions return EOF upon encountering end of file, and ERROR when encountering other errors.
implement bufio_test; include "sys.m"; include "draw.m"; include "bufio.m"; sys: Sys; draw: Draw; bufio: Bufio; Iobuf: import bufio; stderr, stdout, stdin: ref Sys->FD; bufio_test: module { init: fn(ctxt: ref Draw->Context, argv: list of string); }; init(ctxt: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; bufio = load Bufio Bufio->PATH; stdin = sys->fildes(0); stdout = sys->fildes(1); iobfd_in, iobfd_out: ref Iobuf; iobfd_in = bufio->fopen(stdin, bufio->OREAD); if (iobfd_in == nil) sys->print("iobfd_in: error opening %d: %r\n", stdin.fd); else sys->print("iobfd_in: file %d opened successfully\n", stdin.fd); iobfd_out = bufio->fopen(stdout, bufio->OWRITE); if (iobfd_out == nil) sys->print("iobfd_out: error opening %d: %r\n", stdout.fd); else sys->print("iobfd_out: file %d opened successfully\n", stdout.fd); sys->print("Enter input; end with \".\" on a line by itself.\n"); while () { line := iobfd_in.gets('\n'); if (line == ".\n") break; iobfd_out.puts(line); sys->print("%s", line); } iobfd_in.flush(); iobfd_out.flush(); }