/streams

Thoughts for replacing C++ iostreams.

Primary LanguageC++The UnlicenseUnlicense

streams

Experiments in replacing standard C++ iostreams. Comments welcome.

Overview

  • Use {fmt} for output formatting
  • Easy to create new streams
    • Override no more than two functions to create an output stream:
      • ptrdiff_t ostream::_write(span<const byte>)
      • void ostream::_flush()
    • Override one function to create an input stream:
      • span<byte> istream::_read(span<byte>)
  • Streams can be composed
    • Buffering provided as streams that can be composed with other streams
    • Filtering streams can be created
  • Easy to interoperate with stdio
    • Implement one function (FILE* file()) to create stdio istream/ostream subclasses
    • Non-owning ostream and istream classes to create a stream from a FILE*
    • Get the FILE* from a stdio-based stream with FILE* file()
  • Seekability as a mix-in class
  • No overloading of the shift operators
  • Formatted input is still an open question
    • I need to learn more about char traits and localization

This code uses...

Classes and functions

Anything marked "TBD" hasn't been implemented yet.

Common

  • seekable: Base class with seek and tell member functions
  • stdio_seekable: Seekable base class for seeking on std::FILE*

Unformatted output

A span of bytes can be written to any of the ostream classes via write(). The put() member function can be used to write individual binary objects (in host endianess.)

  • ostream: Base class for unformatted output
  • buf_ostream: Add buffering to another ostream
  • span_ostream: Write output to a span<byte>
  • vector_ostream: Write output to a vector<byte>
  • stdio_base_ostream: Base class for stdio-based ostreams
  • stdio_ostream: Stdio-based ostream that doesn't own its FILE*
  • stdio_file_ostream: Seekable stdio-based file ostream
  • file_ostream: TBD Typically an alias for a platform-specific file ostream
  • mmap_ostream: TBD

Formatted output

Free functions that take ostream classes.

  • print: Formatted output via the {fmt} library
    • Note that fmt::format can be used for formatting directly to strings. No string-stream needed.
  • basic_put_string: Output a string (without using a format string)
    • put_string and put_wstring
  • basic_put_line: Output a string followed by a newline.
    • put_line and put_wline
  • basic_put_char: Output a character
    • put_char and put_wchar

Unformatted input

A span of bytes can be read from these istream classes with read(). The get() member function can be used to read individual binary objects (in host endianess).

  • istream: Base class for unformatted input
  • buf_istream: Add buffering to another istream
  • span_istream: Read input from a span
  • unget_istream: Add an arbitrary unget buffer to another istream
  • stdio_base_istream: Base class for stdio-based istreams
  • stdio_istream: Stdio-based ostream that doesn't own its FILE*
  • stdio_file_istream: Seekable stdio-based file istream
  • file_istream: TBD Typically an alias for a platform-specific file istream
  • mmap_istream: In progress...

Formatted input

Free functions that take istream classes.

  • basic_get_regex: TBD Read a string using an regular expression
  • basic_get_line: Read a string up to a delimiter
    • get_line and get_wline
  • basic_get_char: Read a character
    • get_char and get_wchar

Standard streams

The standard streams wrapped in stdio_istream/stdio_ostream.

Since the standard names are macros, I couldn't just use, e.g., streams::stdout. So I added an extra "s". (For "stream".)

  • stdins: stdin
  • stdouts: stdout
  • stderrs: stderr

Platform specific

  • stdio_pipe_ostream: Output pipe to a command
  • stdio_pipe_istream: Input pipe from a command
  • posix_fd_seekable: Base class for seek/tell on POSIX file descriptors
  • posix_base_ostream: A base class of ostreams using a POSIX file descriptor.
  • posix_fd_ostream: A file descriptor ostream that doesn't own its fd
  • posix_file_ostream: A seekable file ostream that uses the POSIX file APIs
  • posix_base_istream: A base class of istreams using a POSIX file descriptor
  • posix_fd_istream: A file descriptor istream that doesn't own its fd
  • posix_file_istream: A seekable file istream that uses the POSIX file APIs

Example streams

Found in examples/example.cpp.

  • Shout_ostream: A filter to be used with another ostream that converts all output to upper case.
  • Line_number_ostream: A filter to be used with another ostream that prefixes each line with a line number.
  • Reverse_line_ostream: A filter to be used with another ostream that reverses each line of output.

Possible expansions

  • Input-formatting : scanf :: {fmt} : printf
  • Some quoting/unquoting functions