12.9.2 Creating an IO stream
A new stream is created using Snew().
Before we can create a stream we must create a function block of type IOFUNCTIONS
that provide function pointers for the basic operations on the stream.
This type is defined as follows:
typedef struct io_functions { Sread_function read; /* fill the buffer */ Swrite_function write; /* empty the buffer */ Sseek_function seek; /* seek to position */ Sclose_function close; /* close stream */ Scontrol_function control; /* Info/control */ Sseek64_function seek64; /* seek to position (large files) */ } IOFUNCTIONS;
- ssize_t (*Sread_function)(void *handle, char *buf, size_t bufsize)
- Read new data into buf that has size bufsize, return the number of bytes read or -1. Note that this is the same interface as the POSIX read() API. See section 12.9.4 for raising errors.
- ssize_t (*Swrite_function)(void *handle, char *buf, size_t bufsize)
- Write the bytes from buf with contains bufsize bytes and return the number of bytes written or -1. The number of bytes written may be less than bufsize. Bytes that were not written remain in the stream's output buffer. Note that this is the same interface as the POSIX write() API. See section 12.9.4 for raising errors.
- long (*Sseek_function)(void *handle, long pos, int whence)
- int64_t (*Sseek64_function)(void *handle, int64_t pos, int whence)
- Reposition the file pointer. These functions may be
NULL
if repositioning is not possible on this type or they may return -1 and seterrno
toEPIPE
if the pointer cannot be repositioned on this instance. The function returns the new file position. See Sseek() for details on how repositioning is implemented. See section 12.9.4 for raising errors. - int (*Sclose_function)(void *handle)
- Close the stream. This is used by Sclose(). Note that buffered output is first written using the Swrite_function(). See section 12.9.4 for raising errors.
- int (*Scontrol_function)(void *handle, int action, void *arg)
- Obtain information about the stream or modify the stream. The function
should return 0 on success and -1 on failure. If some action is not
implemented the function should return -1;
SIO_GETPENDING
,size_t*
- Return the number of bytes that may be written without blocking. Used by Spending().
SIO_LASTERROR
,char*
- Called after an error is raised on a stream. May return a C string that sets error details using Sseterr().
SIO_SETENCODING
,IOENC*
- Called by Ssetenc() to change the encoding of the stream. If the call does not return 0 the encoding is not changed.
SIO_FLUSHOUTPUT
,NULL
- Called by Sflush() after flushing the stream's output buffer. Note that this is only called on an explicit flush using Sflush() or flush_output/1. An implicit flush because the output buffer is full does not call this hook.
SIO_GETSIZE
,int64_t*
- Get the size of the underlying object in bytes. Used by Ssize().
SIO_GETFILENO
,int*
- If the stream is associated with an OS file handle, return this handle. Used by Sfileno().
SIO_GETWINSOCK
,SOCKET*
- Windows only. If the stream is associated to a Windows socket return
this handle. Used by Swinsock().
Given an IOFUNCTIONS
block we can create a new stream
from a
handle using Snew():
- IOSTREAM* Snew(void *handle, int flags, IOFUNCTIONS *functions)
- Create an
IOSTREAM*
from a handle, flags and a block of callback functions. The flags argument is a bitwise or of SIO_* flags. Flags that control the creation are:SIO_INPUT
SIO_OUTPUT
- One of these flags mut be present to indicate whether this is an input or output stream.
SIO_NBUF
SIO_LBUF
SIO_FBUF
- One of these flags must be present to select the buffering as one of
unbuffered (
SIO_NBUF
), line buffered (SIO_LBUF
) or fully buffered (SIO_FBUF
) SIO_TEXT
- If given, this is a text stream and the encoding is set to the default
encoding (see the Prolog flag encoding).
Otherwise this is a binary stream and the encoding is set to
ENC_OCTET
. SIO_RECORDPOS
- If given, enable position maintenance on the stream. This is used by Stell(), Sseek(), stream_property/2
using the
position
property and related predicates. SIO_NOMUTEX
- Used internally to create a stream that cannot be owned or locked.
If the stream is associated with an OS file handle the system initializes the
SIO_ISATTY
flag (on POSIX systems) and if possible tells the OS not to inherit this stream to child processes.The symbol
Sfilefunctions
is aIOFUNCTIONS
struct that contains the callbacks for accessing a regular file. After opening an file using the POSIX open() API we can create a stream to this file using Snew():int fno = open(path, O_RDONLY); IOSTREAM *s; if ( fno >= 0 ) s = Snew((void*)fno, SIO_INPUT|SIO_FBUF|SIO_RECORDPOS|SIO_TEXT, &Sfilefunctions); ...
Snew() can only fail if there is not enough memory. In that case the return value is
NULL
and errno is set toENOMEM
. - IOSTREAM* Sopen_pipe(const char *command, const char *type)
- Start a process from command and connect the input or output
to the returned stream. This wraps the POSIX popen() API. The type
string starts with
r
orw
and may be followed byb
to create a binary stream. The default is to create a text stream using the platform conventions and locale. - IOSTREAM* Sopenmem(char **buffer, size_t *sizep, const char *mode)
- Open a memory area as a stream. Output streams are automatically resized
using realloc() if *size = 0 or the stream is opened
with mode
"wa"
. If the buffer is allocated or enlarged, this is achieved using malloc() or realloc(). In this case the returned buffer should be freed by the caller when done. Example:{ char buf[1024]; // don't allocate for small stuff char *s = buf; IOSTREAM *fd; size_t size = sizeof(buf); fd = Sopenmem(&s, &size, "w"); ... Sclose(fd); ... if ( s != buf ) // appearently moved Sfree(s); }
The mode is
"r"
or"w"
. The mode "rF" callsPL_free(buffer)
when closed.Note: Its is not allowed to access streams created with this call from multiple threads. This is ok for all usage inside Prolog itself. This call is intended to use Sfprintf() and other output functions to create strings.
- void Sfree(void *ptr)
- This function must be used to free objects that are allocated by the stream interface. Currently this only applies to strings allocated by Sopenmem().
A stream can be made accessible from Prolog using PL_unify_stream():
- int PL_unify_stream(term_t t, IOSTREAM *s)
- Unify t with a blob that points at s. Note that a blob provides a unique and reliable reference to a stream. Blobs are subject to atom garbage collection. If an open stream is garbage collected the behaviour depends on the Prolog flag agc_close_streams. See also Sgcclose().