Skip to content
Marc edited this page Aug 13, 2018 · 4 revisions

Buffers only store data. They have a limited amount of bytes to store any data you want. Also, buffers have functions to serialize and deserialize basic data types.

Buffers basically contain a pointer that points to the data it holds and an offset. This offset is just a number that tells the buffer the amount of bytes written or read. After each read/write operation, the offset is incremented by the amount of bytes read. For example, reading an int will add 4 to the offset, while reading a char will only add one.

This is important when we serialize fields, arrays, objects or databases to a buffer and then we deserialize again from the same buffer (as done in the source examples). In that case, the offset is at the end of the serialized data and therefore needs to be reset to the beginning. This can easily be accomplished using the setOffset(int) function.

Using buffers

You can find buffers inside src/Buffer.h, but you may consider including Cereal.h instead, as it will automatically include all the necessary files aswell as all the files from the library.

To begin with, we will create a buffer with one kilobyte of storage (1024 bytes):

Cereal::Buffer myBuffer(1024);

Simple, right? Now we can serialize anything we want into it using Buffer::writeBytes<dataType>(data):

myBuffer.writeBytes<unsigned int>(17726);

As stated before, once we write bytes into a buffer, the offset gets incremented by the amount of bytes written, so we will never overwrite anything. This is specially important when we want to read, because now the offset of our buffer is 4, and the data has been written from byte 0 to 3, so how do we get that int back? Easy:

myBuffer.setOffset(0); // Set the offset to the first byte
unsigned int value = buffer.readBytes<unsigned int>();

Now, value should be equal to 17726, and the buffer's offset is back to 4 because we have read four bytes (the size of an unsigned int is always 4 bytes).

Buffers also have some other pretty cool features. For example, we can check if it has enough space to store any amount of bytes:

if(myBuffer.hasSpace(32))
{
    // The buffer has 32 or more free bytes, we can write without a problem
}
else
{
    // The buffer has 31 or less free bytes, we can't write to it
}

This function is internally used by fields, arrays, objects and databases to check if data can be serialized into the specified buffer or not. If not, the call to the Write funcion will return false.

Another cool feature of buffers is that they can be used to write or read files, like so:

myBuffer.readFile("database.db"); // Now myBuffer has all the data from "database.db", we can deserialize now
// ...
myBuffer.writeFile("database.db"); // We write the contents of the buffer to "database.db". NOTE: If the file exists, it will be overwritten

One last useful thing about buffers is that they can free unused space. This is incredibly useful if we want to serialize a big database, because we can create a buffer with 4 or 5 megabytes of memory and then free all the unused space:

myBuffer.shrink();

You should keep in mind that now the buffer cannot be written, because its offset is equal to its size (it doesn't have more space), but it can be read if you set the offset back to zero.