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 
NULLif repositioning is not possible on this type or they may return -1 and seterrnotoEPIPEif 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_INPUTSIO_OUTPUT- One of these flags mut be present to indicate whether this is an input or output stream.
 SIO_NBUFSIO_LBUFSIO_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
positionproperty 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_ISATTYflag (on POSIX systems) and if possible tells the OS not to inherit this stream to child processes.The symbol
Sfilefunctionsis aIOFUNCTIONSstruct 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
NULLand 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 
rorwand may be followed bybto 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().