10.3 In-memory Streams
There are two kinds of in-memory streams, string streams and queues.
String streams behave much like files, they can be read, written,
positioned etc, but they are implemented as buffer in memory.
Queues are intended mainly for message-passing-style communication
between ECLiPSeand a host language, and they are also implemented as
memory buffers.
10.3.1 String Streams
In ECLiPSe it is possible to associate a stream with a Prolog string
in its memory, and this string is then used in the same way as a file
for the input and output operations.
A string stream is opened like a file by the open/3 predicate call
open(string(InitString), Mode, Stream)
where InitString can be a ECLiPSe string or a variable and represents
the initial contents of the string stream.
If a variable is supplied for InitString, the initial value of the string
stream is the empty string and the variable is bound to this value:
[eclipse 1]: open(string(S), update, s).
S = ""
yes.
Once a string stream is opened, all predicates using streams
can take it as argument and perform I/O on it.
In particular the predicates
seek/2 and
at/2
can be used with them.
While writing into a stream changes the stream contents destructively,
the initial string that has been opened will never be affected.
The new stream contents can be retrieved either by reading from the string
stream, or as a whole by using
get_stream_info/3:
[eclipse 1]: S = "abcdef", open(string(S), write, s), write(s, ---).
S = "abcdef"
yes.
[eclipse 2]: get_stream_info(s, name, S).
S = "---def"
yes.
[eclipse 3]: seek(s, 1), write(s, .), get_stream_info(s, name, S).
S = "-.-def"
yes.
[eclipse 4]: seek(s, end_of_file), write(s, ine),
get_stream_info(s, name, S).
S = "-.-define"
yes.
10.3.2 Queue streams
A queue stream is opened by the open/3 predicate
open(queue(InitString), Mode, Stream)
The initial queue contents is InitString.
It can be seen as a string which gets extended at its end on writing
and consumed at its beginning on reading.
[eclipse 11]: open(queue(""), update, q), write(q, hello), write(q, " wo").
yes.
[eclipse 12]: read_string(q, " ", _, X).
S = "hello"
yes.
[eclipse 13]: write(q, "rld"), read(q, X).
S = world
yes.
[eclipse 14]: at_eof(q).
yes.
It is not allowed to seek on a queue. Therefore, once something is read
from a queue, it is no longer accessible. A queue is considered to be
at its end-of-file position when it is currently empty, however this
is no longer the case when the queue is written again.
A useful feature of queues is that they can raise a synchronous event
when data arrives on the empty queue. To create such an event-raising
queue, this has to be specified as an option when opening the queue with
open/4.
In the example we have chosen the same name for the stream and for the
event, which is not necessary but convenient when the same handler
is going to be used for different queues:
[eclipse 1]: [user].
handle_queue_event(Q) :-
read_string(Q, "", _, Data),
printf("Queue %s received data: %s\n", [Q,Data]).
yes.
[eclipse 2]: set_event_handler(eventq, handle_queue_event/1).
yes.
[eclipse 3]: open(queue(""), update, eventq, [event(eventq)]).
yes.
[eclipse 4]: write(eventq, hello).
Queue eventq received data: hello
yes.