This file defines serialization and deserialization functions read and write, as well as the print function for all fundamental types and core data structures.

The file also contains the definition and implementation of the core::memory_stream class, which may be used to read/write to an in-memory buffer.

Scribes

The read, write, and print functions in this library follow a very regular argument structure: The first argument is the object to read/write/print. The second argument is the stream to read from/write to/print to. Most functions also require a third (optional) argument called the scribe, which controls how the subobjects are read/written/printed. The scribe is typically passed to the read/write/print functions when operating on subobjects of the given object.

Calling read/write/print with core::default_scribe will call the same function without the third argument. This largely corresponds to the "default" behavior of those functions.

For example, write(const core::array<T>& a, Stream& out, Writer&&... writer) will call the function write(a[i], out, writer) for every element a[i] in a. This enables users to define their own scribes, and define new ways to read/write/print objects without having to re-implement the read/write/print functions for container structures such as core::array. The following example demonstrates how the behavior of the print function for an array of integers can be altered using a custom scribe.

#include <core/io.h>
using namespace core;

struct my_string_scribe {
    const char* strings[3];
};

template<typename Stream>
bool print(int i, Stream& out, const my_string_scribe& printer) {
    return print(printer.strings[i], out);
}

int main() {
    array<int> a = array<int>(8);
    a.add(1); a.add(2); a.add(0);

    print(a, stdout); print(' ', stdout);

    default_scribe def;
    print(a, stdout, def); print(' ', stdout);

    my_string_scribe printer;
    printer.strings[0] = "vici";
    printer.strings[1] = "veni";
    printer.strings[2] = "vidi";

    print(a, stdout, printer);
}

This example has expected output [1, 2, 0] [1, 2, 0] [veni, vidi, vici].

Classes, functions, and variables in this file
structis_readable
structis_writeable
structis_printable
boolread (T & value, FILE * in)
boolread (T * values, FILE * in, unsigned int length)
boolwrite (const T & value, FILE * out)
boolwrite (const T * values, FILE * out, unsigned int length)
boolprint (const char & value, FILE * out)
boolprint (const int & value, FILE * out)
boolprint (const unsigned int & value, FILE * out)
boolprint (const unsigned long & value, FILE * out)
boolprint (const unsigned long long & value, FILE * out)
boolprint (const float & value, FILE * out)
boolprint (const double & value, FILE * out)
boolprint (const float & value, FILE * out, unsigned int precision)
boolprint (const double & value, FILE * out, unsigned int precision)
boolprint (const char * values, FILE * out)
structmemory_stream
boolread (T & value, memory_stream & in)
boolread (T * values, memory_stream & in, unsigned int length)
boolwrite (const T & value, memory_stream & out)
boolwrite (const T * values, memory_stream & out, unsigned int length)
size_tfwrite (const void * src, size_t size, size_t n, memory_stream & out)
wint_tfgetwc (memory_stream & out)
intfputc (int c, memory_stream & out)
intfputs (const char * s, memory_stream & out)
intfprintf (memory_stream & out, const char * format, ... )
boolwrite (const char * values, Stream & out)
structdefault_scribe
boolread (T & value, Stream & in, default_scribe & scribe)
boolwrite (const T & value, Stream & out, default_scribe & scribe)
autoprint (const T & value, Stream & out, default_scribe & scribe)
boolprint (const T * values, SizeType length, Stream & out, Printer & printer)
boolprint (const T * values, unsigned int length, Stream & out)
boolprint (const T (&values)[N], Stream & out, Printer &&... printer)
boolprint (const T (&values)[N], Stream & out)
boolread (T * a, Stream & in, unsigned int length, Reader &&... reader)
boolread (array< T > & a, Stream & in, Reader &&... reader)
boolwrite (const T * a, Stream & out, unsigned int length, Writer &&... writer)
boolwrite (const array< T > & a, Stream & out, Writer &&... writer)
boolprint (const array< T > & a, Stream & out, Printer &&... printer)
boolread (hash_set< T > & set, Stream & in, alloc_keys_func alloc_keys, Reader &&... reader)
boolread (hash_set< T > & set, Stream & in, Reader &&... reader)
boolwrite (const hash_set< T > & set, Stream & out, Writer &&... writer)
boolread (hash_map< K, V > & map, Stream & in, alloc_keys_func alloc_keys, KeyReader & key_reader, ValueReader & value_reader)
boolread (hash_map< K, V > & map, Stream & in, KeyReader & key_reader, alloc_keys_func alloc_keys = calloc)
boolread (hash_map< K, V > & map, Stream & in, alloc_keys_func alloc_keys = calloc)
boolwrite (const hash_map< K, V > & map, Stream & out, KeyWriter & key_writer, ValueWriter & value_writer)
boolwrite (const hash_map< K, V > & map, Stream & out, KeyWriter & key_writer)
boolwrite (const hash_map< K, V > & map, Stream & out)
boolread (array_map< K, V > & map, Stream & in, KeyReader & key_reader, ValueReader & value_reader)
boolread (array_map< K, V > & map, Stream & in, KeyReader & key_reader)
boolread (array_map< K, V > & map, Stream & in)
boolwrite (const array_map< K, V > & map, Stream & out, KeyWriter & key_writer, ValueWriter & value_writer)
boolwrite (const array_map< K, V > & map, Stream & out, KeyWriter & key_writer)
boolwrite (const array_map< K, V > & map, Stream & out)
boolread (pair< K, V > & p, Stream & stream)
boolwrite (const pair< K, V > & p, Stream & stream)

struct is_readable

template<typename T>

This type trait is true_type if and only if the function size_t fread(void*, integral, integral, T) is defined where integral is any integral type.

struct is_writeable

template<typename T>

This type trait is true_type if and only if the function size_t fwrite(void*, integral, integral, T) is defined where integral is any integral type.

struct is_printable

template<typename T>

This type trait is true_type if and only if the function int fprintf(T, const char*) is defined.

template<typename T>
bool read(
T &value,
FILE *in)

Reads sizeof(T) bytes from in and writes them to the memory referenced by value. This function does not perform endianness transformations.

Parameters
in

the stream given by a FILE pointer.

Template parameters
T

satisfies is_fundamental.

template<typename T>
bool read(
T *values,
FILE *in,
unsigned intlength)

Reads length elements from in and writes them to the native array values. This function does not perform endianness transformations.

Parameters
in

the stream given by a FILE pointer.

Template parameters
T

satisfies is_fundamental.

template<typename T>
bool write(
const T &value,
FILE *out)

Writes sizeof(T) bytes to out from the memory referenced by value. This function does not perform endianness transformations.

Parameters
out

the stream given by a FILE pointer.

Template parameters
T

satisfies is_fundamental.

template<typename T>
bool write(
const T *values,
FILE *out,
unsigned intlength)

Writes length elements to out from the native array values. This function does not perform endianness transformations.

Parameters
out

the stream given by a FILE pointer.

Template parameters
T

satisfies is_fundamental.

bool print(
const char &value,
FILE *out)

Prints the character value to the stream given by the FILE pointer out.

bool print(
const int &value,
FILE *out)

Prints the int value to the stream given by the FILE pointer out.

bool print(
const unsigned int &value,
FILE *out)

Prints the unsigned int value to the stream given by the FILE pointer out.

bool print(
const unsigned long &value,
FILE *out)

Prints the unsigned long value to the stream given by the FILE pointer out.

bool print(
const unsigned long long &value,
FILE *out)

Prints the unsigned long long value to the stream given by the FILE pointer out.

bool print(
const float &value,
FILE *out)

Prints the float value to the stream given by the FILE pointer out.

bool print(
const double &value,
FILE *out)

Prints the double value to the stream given by the FILE pointer out.

bool print(
const float &value,
FILE *out,
unsigned intprecision)

Prints the float value to the stream given by the FILE pointer out with the given precision.

bool print(
const double &value,
FILE *out,
unsigned intprecision)

Prints the double value to the stream given by the FILE pointer out with the given precision.

bool print(
const char *values,
FILE *out)

Prints the null-terminated C string value to the stream given by the FILE pointer out.

struct memory_stream

Represents a stream to read/write from an in-memory buffer.

Public members
unsigned intlength
unsigned intposition
char *buffer
memory_stream ()
memory_stream (unsigned int initial_capacity)
memory_stream (const char * buf, unsigned int length)
boolread (void * dst, unsigned int bytes)
boolensure_capacity (unsigned int bytes)
boolwrite (const void * src, unsigned int bytes)
unsigned int memory_stream::length

The size of the stream.

unsigned int memory_stream::position

The current position of the stream in the buffer.

char * memory_stream::buffer

The underlying buffer.

memory_stream::memory_stream()

The default constructor does not initialize any fields.

memory_stream::memory_stream(
unsigned intinitial_capacity)

Initializes the stream with memory_stream::length given by initial_capacity and memory_stream::position set to 0. memory_stream::buffer is allocated but not initialized to any value.

memory_stream::memory_stream(
const char *buf,
unsigned intlength)

Initializes the stream with the memory_stream::buffer given by buf, memory_stream::length given by length, and memory_stream::position set to 0.

bool memory_stream::read(
void *dst,
unsigned intbytes)

Reads a number of bytes given by bytes from the memory_stream and writes them to dst. This function assumes dst has sufficient capacity.

bool memory_stream::ensure_capacity(
unsigned intbytes)

Checks whether the stream has sufficient size for an additional number of bytes given by bytes at its current memory_stream::position. If not, this function attempts to expand the buffer to a new size computed as memory_stream::position + bytes.

bool memory_stream::write(
const void *src,
unsigned intbytes)

Writes a number of bytes given by bytes from the given native array src to the current position in this stream. memory_stream::ensure_capacity is called to ensure the underlying buffer has sufficient size.

template<typename T>
bool read(
T &value,
memory_stream &in)

Reads sizeof(T) bytes from in and writes them to the memory referenced by value. This function does not perform endianness transformations.

Parameters
in

a memory_stream.

Template parameters
T

satisfies is_fundamental.

template<typename T>
bool read(
T *values,
memory_stream &in,
unsigned intlength)

Reads length elements from in and writes them to the native array values. This function does not perform endianness transformations.

Parameters
in

a memory_stream.

Template parameters
T

satisfies is_fundamental.

template<typename T>
bool write(
const T &value,
memory_stream &out)

Writes sizeof(T) bytes to out from the memory referenced by value. This function does not perform endianness transformations.

Parameters
out

a memory_stream.

Template parameters
T

satisfies is_fundamental.

template<typename T>
bool write(
const T *values,
memory_stream &out,
unsigned intlength)

Writes length elements to out from the native array values. This function does not perform endianness transformations.

Parameters
out

a memory_stream.

Template parameters
T

satisfies is_fundamental.

size_t fwrite(
const void *src,
size_tsize,
size_tn,
memory_stream &out)

Writes the array of n elements, each with a size of size bytes, from the memory address referenced by src to the memory_stream out.

See

This function mirrors the equivalent fwrite for FILE pointer streams.

Returns

either n if the write is successful, or 0 upon failure.

wint_t fgetwc(
memory_stream &out)

Reads and returns a wide character from the given memory_stream.

See

This function mirrors the equivalent fgetwc for FILE pointer streams.

Returns

on success, the next wide character from the stream.

WEOF on failure. If the next bytes in the stream cannot be interpreted as a wide character, errno is set to EILSEQ.

int fputc(
intc,
memory_stream &out)

Writes the given character c to the memory_stream out.

See

This function mirrors the equivalent fputc for FILE pointer streams.

int fputs(
const char *s,
memory_stream &out)

Writes the given null-terminated C string s to the memory_stream out.

See

This function mirrors the equivalent fputs for FILE pointer streams.

int fprintf(
memory_stream &out,
const char *format,
...)

Writes the given arguments according to the format string format to the memory_stream out.

See

This function mirrors the equivalent fprintf for FILE pointer streams.

Returns

the number of bytes written to the stream, or -1 upon error.

template<typename Stream>
bool write(
const char *values,
Stream &out)

Writes the given null-terminated C string values to the stream out.

Template parameters
Stream

satisfies is_writeable.

struct default_scribe

The default scribe implementation that provides the default behavior for read/write/print functions.

template<typename T, typename Stream>
bool read(
T &value,
Stream &in,
default_scribe &scribe)

Calls and returns read(value, in), dropping the default_scribe argument.

Template parameters
Stream

satisfies is_readable.

template<typename T, typename Stream>
bool write(
const T &value,
Stream &out,
default_scribe &scribe)

Calls and returns write(value, out), dropping the default_scribe argument.

Template parameters
Stream

satisfies is_writeable.

template<typename T, typename Stream>
auto print(
const T &value,
Stream &out,
default_scribe &scribe)

Calls and returns print(value, out), dropping the default_scribe argument.

Template parameters
Stream

satisfies is_printable.

template<typename T, char LeftBracket = '[', char RightBracket = ']', typename SizeType, typename Stream, typename Printer>
bool print(
const T *values,
SizeTypelength,
Stream &out,
Printer &printer)

Prints the given native array of values each of type T, where length is the number of elements in the array. The output stream is out.

Parameters
printer

a scribe for which the function bool print(const T&, Stream&, Printer&) is defined.

Template parameters
Stream

satisfies is_printable.

template<typename T, char LeftBracket = '[', char RightBracket = ']', typename Stream>
bool print(
const T *values,
unsigned intlength,
Stream &out)

Prints the given native array of values each of type T, where length is the number of elements in the array. The output stream is out.

Template parameters
Stream

satisfies is_printable.

template<typename T, size_t N, char LeftBracket = '[', char RightBracket = ']', typename Stream, typename... Printer>
bool print(
const T(&values)[N],
Stream &out,
Printer &&...printer)

Prints the given native static array of values each of type T, where N is the number of elements in the array. The output stream is out.

Parameters
printer

a scribe for which the function bool print(const T&, Stream&, Printer&) is defined. Note that since this is a variadic argument, it may be empty.

Template parameters
Stream

satisfies is_printable.

template<typename T, size_t N, char LeftBracket = '[', char RightBracket = ']', typename Stream>
bool print(
const T(&values)[N],
Stream &out)

Prints the given native static array of values each of type T, where N is the number of elements in the array. The output stream is out.

Template parameters
Stream

satisfies is_printable.

template<typename T, typename Stream, typename... Reader>
bool read(
T *a,
Stream &in,
unsigned intlength,
Reader &&...reader)

Reads an array of length elements from in and stores the result in the given native array a. This function assumes a has sufficient capacity.

Parameters
reader

a scribe for which the function bool read(T&, Stream&, Reader&&...) is defined. Note that since this is a variadic argument, it may be empty.

Template parameters
Stream

satisfies is_readable.

template<typename T, typename Stream, typename... Reader>
bool read(
array< T > &a,
Stream &in,
Reader &&...reader)

Reads a core::array structure from in and stores the result in a.

Parameters
a

an uninitialized core::array structure. This function initializes a, and the caller is responsible for its memory and must call free to release its memory resources.

reader

a scribe for which the function bool read(T&, Stream&, Reader&&...) is defined. Note that since this is a variadic argument, it may be empty.

Template parameters
Stream

satisfies is_readable.

template<typename T, typename Stream, typename... Writer>
bool write(
const T *a,
Stream &out,
unsigned intlength,
Writer &&...writer)

Writes the given native array a of elements to out, each of type T, where the number of elements is given by length.

Parameters
writer

a scribe for which the function bool write(const T&, Stream&, Writer&&...) is defined. Note that since this is a variadic argument, it may be empty.

Template parameters
Stream

satisfies is_writeable.

template<typename T, typename Stream, typename... Writer>
bool write(
const array< T > &a,
Stream &out,
Writer &&...writer)

Writes the given core::array structure a of elements to out, each of type T.

Parameters
writer

a scribe for which the function bool write(const T&, Stream&, Writer&&...) is defined. Note that since this is a variadic argument, it may be empty.

Template parameters
Stream

satisfies is_writeable.

template<typename T, typename Stream, typename... Printer>
bool print(
const array< T > &a,
Stream &out,
Printer &&...printer)

Prints the given core::array structure a of elements to out, each of type T.

Parameters
printer

a scribe for which the function bool print(const T&, Stream&, Printer&&...) is defined. Note that since this is a variadic argument, it may be empty.

Template parameters
Stream

satisfies is_printable.

template<typename T, typename Stream, typename... Reader>
bool read(
hash_set< T > &set,
Stream &in,
alloc_keys_funcalloc_keys,
Reader &&...reader)

Reads a core::hash_set structure set from in.

Parameters
set

an uninitialized core::hash_set structure. This function initializes set, and the caller is responsible for its memory and must call free to release its memory resources.

alloc_keys

a memory allocation function with prototype void* alloc_keys(size_t count, size_t size) that allocates space for count items, each with size size, and initializes them such that core::is_empty() returns true for each element.

reader

a scribe for which the function bool read(T&, Stream&, Reader&&...) is defined. Note that since this is a variadic argument, it may be empty.

Template parameters
Stream

satisfies is_readable.

template<typename T, typename Stream, typename... Reader>
bool read(
hash_set< T > &set,
Stream &in,
Reader &&...reader)

Reads a core::hash_set structure set from in. The keys in the hash_set are allocated using calloc.

Parameters
set

an uninitialized core::hash_set structure. This function initializes set, and the caller is responsible for its memory and must call free to release its memory resources.

reader

a scribe for which the function bool read(T&, Stream&, Reader&&...) is defined. Note that since this is a variadic argument, it may be empty.

Template parameters
Stream

satisfies is_readable.

template<typename T, typename Stream, typename... Writer>
bool write(
const hash_set< T > &set,
Stream &out,
Writer &&...writer)

Writes the given core::hash_set structure set to out.

Parameters
writer

a scribe for which the function bool write(const T&, Stream&, Writer&&...) is defined. Note that since this is a variadic argument, it may be empty.

Template parameters
Stream

satisfies is_writeable.

template<typename K, typename V, typename Stream, typename KeyReader, typename ValueReader>
bool read(
hash_map< K, V > &map,
Stream &in,
alloc_keys_funcalloc_keys,
KeyReader &key_reader,
ValueReader &value_reader)

Reads a core::hash_map structure map from in.

Parameters
map

an uninitialized core::hash_map structure. This function initializes map, and the caller is responsible for its memory and must call free to release its memory resources.

alloc_keys

a memory allocation function with prototype void* alloc_keys(size_t count, size_t size) that allocates space for count items, each with size size, and initializes them such that core::is_empty() returns true for each element of type K.

key_reader

a scribe for which the function bool read(K&, Stream&, KeyReader&) is defined.

value_reader

a scribe for which the function bool read(V&, Stream&, ValueReader&) is defined.

Template parameters
Stream

satisfies is_readable.

template<typename K, typename V, typename Stream, typename KeyReader>
bool read(
hash_map< K, V > &map,
Stream &in,
KeyReader &key_reader,
alloc_keys_funcalloc_keys = calloc)

Reads a core::hash_map structure map from in.

Parameters
map

an uninitialized core::hash_map structure. This function initializes map, and the caller is responsible for its memory and must call free to release its memory resources.

alloc_keys

a memory allocation function with prototype void* alloc_keys(size_t count, size_t size) that allocates space for count items, each with size size, and initializes them such that core::is_empty() returns true for each element of type K.

key_reader

a scribe for which the function bool read(K&, Stream&, KeyReader&) is defined.

Template parameters
Stream

satisfies is_readable.

template<typename K, typename V, typename Stream>
bool read(
hash_map< K, V > &map,
Stream &in,
alloc_keys_funcalloc_keys = calloc)

Reads a core::hash_map structure map from in.

Parameters
map

an uninitialized core::hash_map structure. This function initializes map, and the caller is responsible for its memory and must call free to release its memory resources.

alloc_keys

a memory allocation function with prototype void* alloc_keys(size_t count, size_t size) that allocates space for count items, each with size size, and initializes them such that core::is_empty() returns true for each element of type K.

Template parameters
Stream

satisfies is_readable.

template<typename K, typename V, typename Stream, typename KeyWriter, typename ValueWriter>
bool write(
const hash_map< K, V > &map,
Stream &out,
KeyWriter &key_writer,
ValueWriter &value_writer)

Writes the core::hash_map structure map to out.

Parameters
key_writer

a scribe for which the function bool write(const K&, Stream&, KeyWriter&) is defined.

value_writer

a scribe for which the function bool write(const V&, Stream&, ValueWriter&) is defined.

Template parameters
Stream

satisfies is_writeable.

template<typename K, typename V, typename Stream, typename KeyWriter>
bool write(
const hash_map< K, V > &map,
Stream &out,
KeyWriter &key_writer)

Writes the core::hash_map structure map to out.

Parameters
key_writer

a scribe for which the function bool write(const K&, Stream&, KeyWriter&) is defined.

Template parameters
Stream

satisfies is_writeable.

template<typename K, typename V, typename Stream>
bool write(
const hash_map< K, V > &map,
Stream &out)

Writes the core::hash_map structure map to out.

Template parameters
Stream

satisfies is_writeable.

template<typename K, typename V, typename Stream, typename KeyReader, typename ValueReader>
bool read(
array_map< K, V > &map,
Stream &in,
KeyReader &key_reader,
ValueReader &value_reader)

Reads a core::array_map structure map from in.

Parameters
map

an uninitialized core::array_map structure. This function initializes map, and the caller is responsible for its memory and must call free to release its memory resources.

key_reader

a scribe for which the function bool read(K&, Stream&, KeyReader&) is defined.

value_reader

a scribe for which the function bool read(V&, Stream&, ValueReader&) is defined.

Template parameters
Stream

satisfies is_readable.

template<typename K, typename V, typename Stream, typename KeyReader>
bool read(
array_map< K, V > &map,
Stream &in,
KeyReader &key_reader)

Reads a core::array_map structure map from in.

Parameters
map

an uninitialized core::array_map structure. This function initializes map, and the caller is responsible for its memory and must call free to release its memory resources.

key_reader

a scribe for which the function bool read(K&, Stream&, KeyReader&) is defined.

Template parameters
Stream

satisfies is_readable.

template<typename K, typename V, typename Stream>
bool read(
array_map< K, V > &map,
Stream &in)

Reads a core::array_map structure map from in.

Parameters
map

an uninitialized core::array_map structure. This function initializes map, and the caller is responsible for its memory and must call free to release its memory resources.

Template parameters
Stream

satisfies is_readable.

template<typename K, typename V, typename Stream, typename KeyWriter, typename ValueWriter>
bool write(
const array_map< K, V > &map,
Stream &out,
KeyWriter &key_writer,
ValueWriter &value_writer)

Writes the given core::array_map structure map to out.

Parameters
key_writer

a scribe for which the function bool write(const K&, Stream&, KeyWriter&) is defined.

value_writer

a scribe for which the function bool write(const V&, Stream&, ValueWriter&) is defined.

Template parameters
Stream

satisfies is_writeable.

template<typename K, typename V, typename Stream, typename KeyWriter>
bool write(
const array_map< K, V > &map,
Stream &out,
KeyWriter &key_writer)

Writes the given core::array_map structure map to out.

Parameters
key_writer

a scribe for which the function bool write(const K&, Stream&, KeyWriter&) is defined.

Template parameters
Stream

satisfies is_writeable.

template<typename K, typename V, typename Stream>
bool write(
const array_map< K, V > &map,
Stream &out)

Writes the given core::array_map structure map to out.

Template parameters
Stream

satisfies is_writeable.

template<typename K, typename V, typename Stream>
bool read(
pair< K, V > &p,
Stream &stream)

Reads a core::pair structure p from stream by calling read(p.key, stream) and read(p.value, stream).

Template parameters
Stream

satisfies is_readable.

template<typename K, typename V, typename Stream>
bool write(
const pair< K, V > &p,
Stream &stream)

Writes the given core::pair structure p to stream by calling write(p.key, stream) and write(p.value, stream).

Template parameters
Stream

satisfies is_writeable.