scnlib  0.1.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
A Stream is something that the library can read values from.
A Stream contains a stream source or just source for short inside of it, which is where the stream gets its input. The source can be a buffer, a file, a socket, or whatever the Stream happens to implement.
In addition, a Stream contains a putback buffer. In practice, not all concrete stream types have one, but use the underlying source to their advantage, to achieve the same effect, under the as-if rule.
Every Stream has an associated character type, which must be either char or wchar_t. This is the type of the charact// exposition-onlyers that the external interface uses; the stream source can use whatever character type it likes.
An example of a Stream is scn::basic_cstdio_stream.
Valid expressions
A type S satisfies Stream, if
  • the type S satisfies MoveConstructible, MoveAssignable and Destructible, and
  • lvalues of type S satisfy Swappable, and
  • s, an lvalue of type S, and
  • ch, a value of type S::char_type,
the following expressions must be valid and have their specified effects:
  • S::char_type: character type of s
  • S::is_sized_stream::value -> bool
  • s.read_char() -> expected<S::char_type>: Reads a character from s, or returns an error. Precondition: s must be readable
  • s.putback(ch) -> error: Puts a character into the putback buffer of s. Postcondition: If the operation was successful, s will be readable
  • s.bad() -> bool: Returns true if s is bad
  • (bool)s: Equivalent to: !s.bad()
  • s.set_roll_back() -> error: Sets the current state of s as the recovery state. Precondition: s must not be bad
  • s.roll_back() -> error: Resets the state of s into the recovery state. Precondition: s must not be bad
  • s.rcount() -> std::size_t: Returns the number of characters read, minus the size of the putback buffer, since the last call to set_roll_back() or roll_back()
A Stream is bad if some non-recoverable error has occurred.
A Stream is readable if it is:
  • not bad, and
  • the previous call to read_char() did not return an error.
If the previous call to read_char() failed, either:
  • putback() must be called, or
  • the source must be modified (if supported)
for the stream to become readable again.
A call to read_char() first checks the top of the putback buffer, popping that if there's any characters there, and only if there's none, will it reach for the source.
A Stream has a recovery state, which is the state of the stream at construction, or after any subsequent set_roll_back() call. This state can be then rolled back to using roll_back(). This functionality can be used for error recovery; if a higher-level operation fails, and set_roll_back() was called before the operation, the stream can be rolled back to the recovery state with roll_back().
is_sized_stream::value is true if and only if the type also satisfies SizedStream.
If s.putback() is called, and then the underlying stream source is mutated, the behavior is undefined. Some concrete stream types may relax this requirement.
Exposition-only Concept
// exposition-only
template <typename S>
concept Stream =
std::Movable<S> && std::Destructible<S> &&
requires(S& s, typename S::char_type ch, typename S::is_sized_stream)
{ s.read_char() } -> expected<char_type>;
{ s.putback(ch) } -> error;
{ s.bad() } -> std::Boolean;
{ s } -> std::Boolean;
{ s.set_roll_back() } -> error;
{ s.roll_back() } -> error;
{ s.rcount() } -> std::size_t;
{ S::is_sized_stream::value } -> std::Boolean;