Skip to content

Installation and Usage

Felix Gündling edited this page Jan 26, 2023 · 8 revisions

How to Add Cista to Your Project

There are now two ways to use Cista:

Single Header

The cista.h single-header file can be downloaded in a release version or generated via CMake using the cista-test-single-header target.

CMake Sub-Directory

For larger projects, it is recommended to use Cista as a CMake library:

add_subdirectory(cista)
# ...
target_link_libraries(my_target cista)

And in your project source code:

#include "cista/containers/vector.h"
#include "cista/reflection/to_tuple.h"
// ...

You can extract the ZIP file to your project or add cista as a Git submodule:

git submodule add https://github.com/felixguendling/cista.git cista

This way, you can include only the headers you need which could improve compilation times.

Basic Usage

  • Declare the data structures you want to serialize as regular C++ structs (using scalar types, cista::raw/offset::string, cista::raw/offset::unique_ptr<T&>, and cista::raw/offset::vector<T&>, etc.). To be precise, they need to be standard layout, non-polymorphic aggregate types.
  • Do NOT declare any constructors (reflection will not work otherwise).
  • Always use data types with known sizes such as int32_t, uint8_t for compatibility across platforms (with the same architecture).
  • To use pointers: store the object you want to reference as cista::raw/offset::unique_ptr<T&> and use a raw pointer T* to reference it.
  • Optional: if you need deterministic buffer contents, you need to fill spare bytes in your structs (see the advanced example below).

Hint: using pointers in hashed keys of hash_map or hash_set will not work because pointer values change at serialization.

Cista++ supports two serialization formats:

Offset Based Data Structures

  • + can be read without any deserialization step (i.e. reinterpret_cast<T> is sufficient).
  • + suitable for shared memory applications
  • - slower at runtime (pointers need to be resolved using one more add)

Raw Data Structures

  • - deserialize step takes time (but still very fast also for GBs of data)
  • - the buffer containing the serialized data needs to be modified
  • + fast runtime access (raw access)

Note on using cista::mmap

(copied from #92)

Note that using MODIFY mode on an mmap is a really bad idea if you want to read and modify serialized data. Using push_back in your example will allocate memory from the heap and replace the pointer in the pointer of the vector serialized in the memory mapped file with the heap pointer. However, the data the pointer points to (the contents of the vector) won't be written to the file. This way, you get a dangling pointer in your serialized data. This can't be fixed.

The only modifications that are possible are changing scalar values in-place. Allocations will allocate from the heap and will lead to dangling pointers in the data serialized in the file.

Developer Setup

If you want to compile the cista-test or other targets:

git clone https://github.com/felixguendling/cista.git
cd cista
mkdir build
cd build
cmake ..
cmake --build . --target cista-test