The input-output system of SmartEiffel.

Usage

When creating streams, one should procede as follows:

  1. Create a terminal stream: that's the "back-end", i.e. where the bytes really come from and/or go to. Such a back-end may be either connected to an OS-related resource (such as a file, a standard stream, or a socket), or an Eiffel resource (such as a string);
  2. Create zero or more filters, connected one to another using the connect_to feature of filter streams;
  3. Let clients only use the front-end filter. Any intermediary filter, and the terminal stream, will refuse to be used directly when they are attached to a filter.

Taken together, interconnected filters and terminal make a filtered stream; one reads and/or writes from one side of the "pipe", while the terminal reads/writes at the other side.

Architecture

First of all, input and output streams have symmetrical hierarchies. They also have a common ancestor.

Those classes are split in two hierarchies: on the one hand, filters, on the other hand, terminals.

Filtered streams are in fact a double-linked objects: each filter points to an underlying stream (be it another filter or a terminal) while each stream points to a filter. The "stream-to-filter" back-link is used for assertions, to ensure one does not bypass filters.

Filters

Filters are stuck in front of a stream (be it another filter or a terminal). They provide extra functionality: compression, buffers, and so on.

Note: you cannot directly use streams that are connected to a filter; use that filter instead.

Terminals

Terminals are back-end bytes readers and/or writers. There are many such terminals: files, sockets, strings and so on. There are even the equivalent of the good old Unix /dev/null device, which eats bytes and provides zeroes.

There are three kinds of terminal streams: TERMINAL_INPUT_STREAM, TERMINAL_OUTPUT_STREAM, and TERMINAL_INPUT_OUTPUT_STREAM

Note that there are only terminal input-output streams. Filters do not have this notion: you use either an input or an output stream, even if the underlying resource has input-output capabilities.

Standard streams

The class STANDARD_STREAMS provides access to the standard streams. GENERAL provides an access to a STANDARD_STREAMS once object, along with shortcuts to the most used features: the standard streams std_input, std_output, std_error, and the most used io which is but a centralized access to the former two.

STANDARD_STREAMS provides features to dynamically change standard streams. It allows to:

Standard patterns for reading

The easiest way for reading characters on an input_stream is as follow:

from -- connect my_input_stream if needed here my_input_stream.read_character until my_input_stream.end_of_input loop -- use my_input_stream.last_character my_input_stream.read_character end my_input_stream.disconnect

The easiest way for reading lines on an input_stream is as follow:

from -- connect my_input_stream if needed here until my_input_stream.end_of_input loop my_input_stream.read_line if my_input_stream.end_of_input then -- The last line of the file does not end with a new line -- character. Remove this test if you don't care. -- use my_input_stream.last_string else -- use my_input_stream.last_string end end my_input_stream.disconnect

Note:

Also available in this cluster

Apart from the Streams and Filters system, the io cluster also provides: