% This LaTeX document was generated using the LaTeX backend of PlDoc,
% The SWI-Prolog documentation system



\section{library(iostream): Utilities to deal with streams}

\label{sec:iostream}

\begin{tags}
    \tag{See also}
\verb$library(archive)$, \verb$library(process)$, \verb$library(zlib)$,
\verb$library(http/http_stream)$
\end{tags}

This library contains utilities that deal with streams, notably
originating from non-built-in sources such as URLs, archives, windows,
processes, etc.

The predicate \predref{open_any}{5} acts as a \textit{broker} between applications that
can process data from a stream and libraries that can create streams
from diverse sources. Without this predicate, processing data inevitally
follows the pattern below. As \textit{call_some_open_variation} can be
anything, this blocks us from writing predicates such as \verb$load_xml(From, DOM)$ that can operate on arbitrary input sources.

\begin{code}
setup_call_cleanup(
    call_some_open_variation(Spec, In),
    process(In),
    close(In)).
\end{code}

Libraries that can open streams can install the hook
\qpredref{iostream}{open_hook}{6} to make their functionality available through
\predref{open_any}{5}.\vspace{0.7cm}

\begin{description}
    \predicate{open_any}{5}{+Specification, +Mode, -Stream, -Close, +Options}
Establish a stream from \arg{Specification} that should be closed
using \arg{Close}, which can either be called or passed to
\predref{close_any}{1}. \arg{Options} processed:

\begin{description}
    \termitem{encoding}{Enc}
Set stream to encoding \arg{Enc}.
\end{description}

Without loaded plugins, the \predref{open_any}{5} processes the following
values for \arg{Specification}. If no rule matches, \predref{open_any}{5}
processes \arg{Specification} as \verb$file(Specification)$.

\begin{description}
    \termitem{\arg{Stream}}{}
A plain stream handle. Possisible post-processing options such
as encoding are applied. \arg{Close} does \textit{not} close the stream,
but resets other side-effects such as the encoding.
    \termitem{stream}{Stream}
Same as a plain \arg{Stream}.
    \termitem{\arg{FileURL}}{}
If \arg{Specification} is of the form =file://...=, the pointed
to file is opened using \predref{open}{4}. Requires \verb$library(uri)$ to
be installed.
    \termitem{file}{Path}
Explicitly open the file \arg{Path}. \arg{Path} can be an \arg{Path}(File)
term as accepted by \predref{absolute_file_name}{3}.
    \termitem{string}{String}
Open a Prolog string, atom, list of characters or codes
as an \textit{input} stream.
\end{description}

The typical usage scenario is given in the code below, where
$<$process$>$ processes the input.

\begin{code}
setup_call_cleanup(
    open_any(Spec, read, In, Close, Options),
    <process>(In),
    Close).
\end{code}

Currently, the following libraries extend this predicate:

\begin{description}
    \termitem{library}{http/http_open}
Adds support for URLs using the \const{http} and \const{https} schemes.
\end{description}

    \predicate{close_any}{1}{+Goal}
Execute the \arg{Close} closure returned by \predref{open_any}{5}. The closure
can also be called directly. Using \predref{close_any}{1} can be considered
better style and enhances tractability of the source code.

    \predicate[semidet,multifile]{open_hook}{6}{+Spec, +Mode, -Stream, -Close, +Options0, -Options}
Open \arg{Spec} in \arg{Mode}, producing \arg{Stream}.

\begin{arguments}
\arg{Close} & is unified to a goal that must be called to undo the
side-effects of the action, e.g., typically the term \verb$close(Stream)$ \\
\arg{Options0} & are the options passed to \predref{open_any}{5} \\
\arg{Options} & are passed to the post processing filters that
may be installed by \predref{open_any}{5}. \\
\end{arguments}
\end{description}

