Skip to content

Basic Streaming

This tutorial covers the usage of the default stream components provided by Codex.
To use the default components you have to include Codex\Default.hpp:

#include <Codex/Default.hpp>

The Stream class

This is how it works: Information is produced by some source, can be transformed by some filters, and is finally consumed by some sink. This architecture is known as a pipeline.

Pipeline architecture

Pipeline architecture

E.g. Information can be produced by a file reader, processed by a parser and consumed by a database.

The constructor of the class cx::Stream receives a producer, a variable number of filters (may be none) and a consumer. Optionally, the constructor can also receive an extra flag telling if the stream should be executed in single thread or multi-thread mode. By default it is single thread. Once constructed, the stream process starts immediately.
Example – copy one file into another:

cx::File inputFile("original.txt");
cx::File outputFile("copy.txt");
// stream from inputFile to outputFile
cx::Stream stream(inputFile, outputFile);

On this example the stream executes and finishes at the constructor itself, because it’s single-threaded.

What if something goes wrong (e.g. write permission denied)? Because everything can happen during a streaming process, errors are thrown from the stream as exceptions (more specifically, instances of the cx::DataException class or it’s subclasses). So it’s always good idea to have a try-catch block somewhere for any eventuality.

Data Streams

Data streams are streams to input/output structured data, such as strings, floats, signed 16bit integers, etc.
E.g. writing some information through a DataOutputStream:

cx::DataOutputStream stream(someFilter, someOtherFilter, myConsumer);
stream << "A string" << 3.1415;
stream.writeUint32(56789);

Note that no producer is required because we’re writing data directly on the stream.
For commodity there are two specialized classes to read/write structured data from/to a file: cx::FileInputStream and cx::FileOutputStream.
E.g. reading structured data from the file “dataFile.dat”.

cx::FileInputStream stream("dataFile.dat");
std::string myString;
float myFloat;
stream >> myString >> myFloat;
unsigned int myUint;
myUint = stream.readUint32();

Data streams are particularly useful to serialize data structures, specially when deriving our classes from cx::Resource. This is covered on the ############# tutorial.

Compression

There are two built-in filters for compression/decompression respectively:

cx::Compressor compressor;
cx::Stream stream(someProducer, compressor, someConsumer);
cx::Decompressor decompressor;
cx::Stream stream(someProducer, decompressor, someConsumer);

The compressor constructor can receive an integer value for the compression rate, ranging from 0 to 9. 0 means no compression at all, and 9 is the best but slowest compression. The default is 6, which is a good balance between size and speed.

Encryption

Codex provides a default block cipher. It requires a secret key of a fixed size. The same key must be used to encrypt and decrypt the same information. The key must be a char array of 16, 24 or 32 bytes.
E.g.:

char SECRET_KEY[16] = {
    158, 217, 196, 188, 117,  52, 141, 155,
     89, 219, 138, 214,  62, 216, 232,  70
};
...
cx::Encrypter encrypter(SECRET_KEY);
cx::FileOutputStream stream(encrypter, "output.cph", cx::Stream::multiThreaded);

Note that because this cipher works with fixed sized blocks, it may add some padding in the end to fit the size of the last block. So if you try to read the ciphered information with direct streaming (a normal Stream object)  you’ll get a few junk bytes in the end. For this reason it is recommended to use data streams to read/write ciphered information.
Padding on direct streaming isn’t automatically dealt on the current version because it doesn’t seem to be very necessary.

A default one-way hash function may be added on a future release for better passwords support .

Conclusion

The most common Codex classes were explained on this page. I suggest you to make a few streaming experiences to become comfortable with it. Don’t forget to use a try catch block around your streams.
On the next page we’ll see how to use Codex to serialize classes with complex data structures.


Index ||  Basic Streaming  >>  Resource Classes