Index | PAL Intro | Commands | Registers | Indices | Stack | Macros | Classes | Attributes | Errors
ps_stream - Introduction to PROSE stream module
Description
File Position
File Flags
Advisory Locks
Standard File Streams
See Also
Author
Support for file streams in PROSE is provided by the ps_stream module, a sub-module of ps_core. This allows files to be opened for reading and writing as well as the standard streams stdin, stdout, stderr and stdbug.
To perform I/O on a file, first a reference to a file is needed, as described in ps_file(5). For example, here we obtain a handle to the current working directory:
.fs_cwd % Set-up top of new virtual fs branch, pointing to cwd obj/def P0 class/add P0, [psFileHook] attr/add P0, [psFilePath], [.] obj/commit ![+], [cwd], P0
Now a file in the current working directory called testfile.txt may be referenced using the notation ![+cwd.testfile.txt].
The file may now be opened for reading by adding the psStreamOpen class to the file object and setting the psStreamMode attribute to r (for read-only access). For example:
.open_readonly % Open file read-only obj/edit P1, ![+cwd.testfile.txt] class/add P1, [psStreamOpen] attr/add P1, [psStreamMode], [r] obj/commitref P0, P1 | |
Now register P0 will hold a reference to the file object that has been opened in read-only mode. This is a unique file handle. The file will remain open as long as the reference in register P0 is left open and as long as the file object has the psStreamMode attribute assigned to it. When the register is cleared with reg/clr P0 and if that was the last open reference to the file handle, or if the psStreamMode attribute is deleted from the object, then the handle will be closed with fclose(3).
As a result of this operation, additional attributes become available within the object:
psStreamIn | |
for reading the next line of input from the file. | |
psByteStream | |
for reading a fixed number of bytes from or the entire contents of the file. The number of bytes read may be varied by the psStreamReadSize attribute (see below). | |
Reading the file one line at a time and sending each line to stdout would be written as:
.cat_to_stdout % Send one line at a time to stdout attr/load P13, [psStreamIn], P14, [psStreamOut] reg/load P15, ![.prose.sys.io] error/jmp &[.loop_end], ![.prose.error.sys.AttributeEmpty] | |
If an attempt is made to read data from psStreamIn when the end of file has been reached, two possible outcomes will result. If the attr/direct instruction was used, the AttributeEmpty error is generated, otherwise if attr/copy or attr/xcopy are used the resulting target register will contain NULL.
The psStreamMode attribute takes all the same mode arguments as fopen(3), i.e.
r | open text file for reading |
rb | open binary file for reading |
r+ | open text file for reading and writing |
r+b | open binary file for reading and writing |
w | create/truncate text file for writing |
wb | create/truncate binary file for writing |
w+ | create/truncate text file for reading and writing |
w+b | create/truncate binary file for reading and writing |
a | open text file for appending (write only) |
ab | open binary file for appending (write only) |
a+ | open text file for appending (read and write) |
a+b | open binary file for appending (read and write) |
Here is an example of opening a file for writing in the current working directory as prepared above:
.open_for_writing % Open file for writing obj/def P0 class/add P0, [psFile], [psStreamOpen] attr/add P0, [statMode], #0100600, [psStreamMode], [w] obj/commitref P0, ![+cwd], [testfile.txt], P0 | |
A reference to the open file object will be found in register P0.
When a file is opened for writing, the following additional attributes become available within the object:
psStreamOut | |
for writing a string to the file. Note that this attribute will not be visible as it is not actually assigned to the object. Each attempt to give it a value sends more data to the file stream. Output buffers are discussed below. | |
All file objects have the psStream super-class which add the following attributes:
psStreamFileDescriptor | |
for reading the file descriptor number as a psInteger as obtained through fileno(3). This attribute may also be abbreviated to psStreamFD. | |
psStreamBufferMode | |
may optionally be assigned to a file object to change the type of I/O buffer used. This may be a string or an index number where IOFBF(0) is fully buffered IOLBF(1) is line buffered and IONBF(2) is unbuffered, as described in setvbuf(3). If this attribute is unassigned then it defaults to IOFBF unless the file handle is for the stderr or stdbug standard streams in which case IONBF is default, or if the stream is a terminal as determined by isatty(3) in which case the default will be IOLBF. | |
psStreamBufferSize | |
may optionally be assigned to a file object that will create a user I/O buffer on the file stream with setvbuf(3) of the given number of bytes in size. The number may be provided as a psInteger. | |
psStreamBufferAllocated | |
is a read-only attribute that returns TRUE if a user buffer has been allocated with psStreamBufferSize. | |
psStreamReadSize | |
if set, specifies the maximum number of bytes that will be read from the psByteStream attribute as a psInteger. If set to 0 or not present, then psByteStream reads to end-of-file. | |
psStreamDirection | |
is a read-only attribute that may be used to determine whether the last I/O operation on this file handle was a read (IN) or a write (OUT). Will be NONE if no I/O has occurred yet with this handle. | |
To flush an output file stream ensuring that all buffered data is sent to
the file, use the
obj/refresh instruction on the file object. This will be performed by
fflush(3).
FILE POSITION
The following attributes become available to a file object when the psStreamSeek class is assigned to it:
psStreamSet may optionally be assigned to a file object to change the "whence" argument of the following fseek(3) call that will be triggered when psStreamPosition is written to. This may be a string or an index number where SET(0) requests that the file position be set relative to the start of the file, CUR(1) relative to the current file position and END(2) relative to the end of the file. If this attribute is unassigned then it defaults to SET. psStreamPosition when set, repositions the file stream to the given offset position in bytes specified as a psInteger. The offset position may be relative to the start of the file, the current position or the end of the file depending on the value of the psStreamSet attribute. When read, returns the current absolute file position in bytes from the beginning of the file as determined by ftell(3) returned as a psInteger.
The following attributes become available to a file object when the psStreamFlags class is assigned to it:
psStreamFlagEOF read-only boolean attribute that returns TRUE if the file stream has reached end-of-file, as determined by feof(3). psStreamFlagError boolean attribute that returns TRUE if the error indicator is set for the file stream, as determined by ferror(3). If any number is written to the psStreamFlagError attribute, or if an attempt is made to delete the attribute from the file object, then the error indicator will be cleared with clearerr(3).
An advisory lock, as described in fcntl(2), may be placed on an open file stream by assigning the psFileLock class to the object. By default this will request an exclusive non-blocking lock. If the file is already locked, the error prose.error.sys.AlreadyLocked will be generated.
If a shared lock is required, then the attribute psLockType should be assigned with the value Shared. This attribute may also be set to Exclusive which requests the default behaviour. If dynamically switching the lock type, after modifying the attribute with attr/mod the object must be refreshed with obj/refresh.
If a blocking lock is required, then the attribute psBlocking should be assigned with the value TRUE. By default, if the file is already locked, then the obj/commit instruction will wait forever until the lock is released. Optionally a timeout may be specified with the psBlockingTimeout attribute, which behaves as a 128-bit precision psFloat. This triggers calls to timer_create(2) and timer_settime(2). If the lock is not released within the given time then the error prose.error.sys.AlreadyLocked will be generated.
In the following example, a file is opened for reading with an advisory exclusive lock. The obj/commitref instruction will block waiting for the lock for a maximum of 2.5 seconds:
.lock_file % Open file for reading with an advisory lock obj/edit P0, ![-fs_root.testfile] class/add P0, [psStreamOpen], [psFileLock] attr/add P0, [psStreamMode], [r] attr/add P0, [psBlocking], [TRUE] attr/add P0, [psBlockingTimeout], [2.5] obj/commitref P0, P0
There are four standard file streams available to any program in PROSE:
stdin standard input stdout standard output stderr standard error stdbug standard debug
The stdbug stream is unique to PROSE and provides a standard mechanism for separating ordinary output and debug messages. By default, data written to stdbug will be redirected to the stderr stream, although it is possible to redirect it to a separate log file if required.
Each file stream may be accessed through a single multiplexer object .prose.sys.io which has the class psStreamMulti assigned to it. In this case, each of the standard file streams are accessed through the following virtual attributes:
psStreamIn | |
for reading the next line of input from the standard input stream. | |
psStreamByteStream | |
for reading a fixed number of bytes from or the standard input stream, or alternatively all bytes up to end-of-file. The number of bytes read may be varied by the psStreamReadSize attribute (see above). | |
psStreamOut | |
for writing a string to the standard output stream. | |
psStreamError | |
for writing a string to the standard error stream. | |
psStreamDebug | |
for writing a string to the standard debug stream. | |
Alternatively, each file stream has its own file object as a separate node underneath .prose.sys.io which have the psStream class assigned. This allows for the full functionality of an ordinary file object as described above in DESCRIPTION, for example the file descriptor number may be obtained, a user input buffer may be assigned and the end-of-file or error indicators may be read. In this case, each standard file stream also possesses its own class for identification:
.prose.sys.io.stdin | |
identified by the psStdIn class and accessed via the attributes psStreamIn and psByteStream. | |
.prose.sys.io.stdout | |
identified by the psStdOut class and accessed via the attribute psStreamOut. | |
.prose.sys.io.stderr | |
identified by the psStdErr class and accessed via the attribute psStreamOut. | |
.prose.sys.io.stdbug | |
identified by the psStdBug class and accessed via the attribute psStreamOut. | |
pal_intro(5), pal_commands(5), pal_registers(5), pal_indices(5), ps_classes(5), ps_attributes(5), ps_errortypes(5), ps_file(5), obj_def(5), obj_edit(5), obj_commit(5), obj_commitref(5), obj_refresh(5), fopen(3), fclose(3), fileno(3), setvbuf(3), isatty(3), fflush(3), fseek(3), ftell(3), feof(3), ferror(3), clearerr(3), fcntl(2), timer_create(2), timer_settime(2),
PROSE Assembly Language at prose.sourceforge.net.
Copyright (c) 2002-2018 Mark R. Bannister <cambridge@users.sourceforge.net>.
This is free software and can be downloaded from prose.sourceforge.net; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
PAL 1.0 | ps_stream (5) | 11 January 2018 |