Encode Decode FulcrumΒΆ

This example shows how to encode and decode a block of data using the Fulcrum codec.

The complete example code is shown below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Copyright Steinwurf ApS 2015.
// Distributed under the "STEINWURF EVALUATION LICENSE 1.0".
// See accompanying file LICENSE.rst or
// http://www.steinwurf.com/licensing

#include <algorithm>
#include <cstdint>
#include <ctime>
#include <iostream>
#include <vector>

#include <storage/storage.hpp>

#include <kodo_fulcrum/coders.hpp>

/// @example encode_decode_fulcrum.cpp
///
/// Simple example showing how to encode and decode a block of data using
/// the Fulcrum codec.
/// For a detailed description of the Fulcrum codec see the following paper
/// on arxiv: http://arxiv.org/abs/1404.6620 by Lucani et. al.

int main()
{
    // Seed the random number generator to get different random data
    srand(static_cast<uint32_t>(time(0)));

    // Set the number of symbols (i.e. the generation size in RLNC
    // terminology) and the size of a symbol in bytes
    fifi::api::field field = fifi::api::field::binary8;
    uint32_t symbols = 42;
    uint32_t symbol_size = 160;

    // Define the fulcrum encoder/decoder types that we will use
    using encoder_type = kodo_fulcrum::encoder;
    using decoder_type = kodo_fulcrum::decoder;

    // In the following we will make an encoder/decoder factory.
    // The factories are used to build actual encoders/decoders
    encoder_type::factory encoder_factory(field, symbols, symbol_size);

    // We query the maximum number of expansion symbols for the fulcrum factory
    std::cout << "Default expansion of the encoder factory: "
              << encoder_factory.expansion() << std::endl;

    // Before building the encoder, you can change the number of expansion
    // symbols like this:
    //
    // encoder_factory.set_expansion(2);

    auto encoder = encoder_factory.build();

    // Get the number of expansion symbols on the fulcrum encoder
    std::cout << "Expansion symbols on the fulcrum encoder : "
              << encoder->expansion() << std::endl;

    decoder_type::factory decoder_factory(field, symbols, symbol_size);

    // We query the maximum number of expansion symbols for the fulcrum factory
    std::cout << "Default expansion of the decoder factory: "
              << decoder_factory.expansion() << std::endl;

    // Before building the decoder, you can change the number of expansion
    // symbols like this:
    //
    // decoder_factory.set_expansion(2);

    auto decoder = decoder_factory.build();

    // Get the number of expansion symbols on the fulcrum decoder
    std::cout << "Expansion symbols on the fulcrum decoder : "
              << decoder->expansion() << std::endl;

    // Allocate some storage for a "payload" the payload is what we would
    // eventually send over a network
    std::vector<uint8_t> payload(encoder->payload_size());

    // Allocate some data to encode. In this case we make a buffer
    // with the same size as the encoder's block size (the max.
    // amount a single encoder can encode)
    std::vector<uint8_t> data_in(encoder->block_size());

    // Just for fun - fill the data with random data
    std::generate(data_in.begin(), data_in.end(), rand);

    // Assign the data buffer to the encoder so that we may start
    // to produce encoded symbols
    encoder->set_const_symbols(storage::storage(data_in));

    // Define a data buffer where the symbols should be decoded
    std::vector<uint8_t> data_out(decoder->block_size());
    decoder->set_mutable_symbols(storage::storage(data_out));

    // Generate packets until the decoder is complete
    while (!decoder->is_complete())
    {
        // Encode a packet into the payload buffer
        encoder->write_payload(payload.data());

        // Pass that packet to the decoder
        decoder->read_payload(payload.data());
    }

    // Check if we properly decoded the data
    if (std::equal(data_out.begin(), data_out.end(), data_in.begin()))
    {
        std::cout << "Data decoded correctly" << std::endl;
    }
    else
    {
        std::cout << "Unexpected failure to decode, "
                  << "please file a bug report :)" << std::endl;
    }
}