Streams

Streams — Input and output abstractions

Functions

Types and Values

Includes

#include <libchimara/glk.h>

Description

All character output in Glk is done through streams. Every window has an output stream associated with it. You can also write to files on disk; every open file is represented by an output stream as well.

There are also input streams; these are used for reading from files on disk. It is possible for a stream to be both an input and an output stream.

Player input is done through line and character input events, not streams. This is a small inelegance in theory. In practice, player input is slow and things can interrupt it, whereas file input is immediate. If a network extension to Glk were proposed, it would probably use events and not streams, since network communication is not immediate.

It is also possible to create a stream that reads or writes to a buffer in memory.

Finally, there may be platform-specific types of streams, which are created before your program starts running.

For example, a program running under Unix may have access to standard input as a stream, even though there is no Glk call to explicitly open standard input. On the Mac, data in a Mac resource may be available through a resource-reading stream.

You do not need to worry about the origin of such streams; just read or write them as usual. For information about how platform-specific streams come to be, see Startup Options.

A stream is opened with a particular file mode, see the filemode_ constants below.

In the stdio library, using fopen(), filemode_Write would be mode "w"; filemode_Read would be mode "r"; filemode_ReadWrite would be mode "r+". Confusingly, filemode_WriteAppend cannot be mode "a", because the stdio spec says that when you open a file with mode "a", then fseek() doesn't work. So we have to use mode "r+" for appending. Then we run into the other stdio problem, which is that "r+" never creates a new file. So filemode_WriteAppend has to first open the file with "a", close it, reopen with "r+", and then fseek() to the end of the file. For filemode_ReadWrite, the process is the same, except without the fseek() — we begin at the beginning of the file.

We must also obey an obscure geas of ANSI C "r+" files: you can't switch from reading to writing without doing an fseek() in between. Switching from writing to reading has the same restriction, except that an fflush() also works.

For information on opening streams, see the discussion of each specific type of stream in The Types of Streams. Remember that it is always possible that opening a stream will fail, in which case the creation function will return NULL.

Each stream remembers two character counts, the number of characters printed to and read from that stream. The write-count is exactly one per glk_put_char() call; it is figured before any platform-dependent character cookery.

For example, if a newline character is converted to linefeed-plus-carriage-return, the stream's count still only goes up by one; similarly if an accented character is displayed as two characters.

The read-count is exactly one per glk_get_char_stream() call, as long as the call returns an actual character (as opposed to an end-of-file token.)

Glk has a notion of the “current (output) stream”. If you print text without specifying a stream, it goes to the current output stream. The current output stream may be NULL, meaning that there isn't one. It is illegal to print text to stream NULL, or to print to the current stream when there isn't one.

If the stream which is the current stream is closed, the current stream becomes NULL.

Functions

glk_stream_set_current ()

void
glk_stream_set_current (strid_t str);

Sets the current stream to str , which must be an output stream. You may set the current stream to NULL, which means the current stream is not set to anything.

Parameters

str

An output stream, or NULL.

 

glk_stream_get_current ()

strid_t
glk_stream_get_current (void);

Returns the current stream, or NULL if there is none.

Returns

A stream, or NULL.

Types and Values

filemode_Write

#define filemode_Write (0x01)

An output stream.

Corresponds to mode "w" in the stdio library, using fopen().


filemode_Read

#define filemode_Read (0x02)

An input stream.

Corresponds to mode "r" in the stdio library, using fopen().


filemode_ReadWrite

#define filemode_ReadWrite (0x03)

Both an input and an output stream.

Corresponds to mode "r+" in the stdio library, using fopen().


filemode_WriteAppend

#define filemode_WriteAppend (0x05)

An output stream, but the data will added to the end of whatever already existed in the destination, instead of replacing it.

Confusingly, filemode_WriteAppend cannot be mode "a", because the stdio spec says that when you open a file with mode "a", then fseek() doesn't work. So we have to use mode "r+" for appending. Then we run into the other stdio problem, which is that "r+" never creates a new file. So filemode_WriteAppend has to first open the file with "a", close it, reopen with "r+", and then fseek() to the end of the file. For filemode_ReadWrite, the process is the same, except without the fseek() — we begin at the beginning of the file.