inline void run_test_basic_api(int32_t encoder_type, int32_t decoder_type, int32_t finite_field, uint32_t symbols, uint32_t symbol_size) { kodoc_factory_t encoder_factory = kodoc_new_encoder_factory( encoder_type, finite_field, symbols, symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory( decoder_type, finite_field, symbols, symbol_size); kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); EXPECT_EQ(symbols, kodoc_factory_max_symbols(encoder_factory)); EXPECT_EQ(symbol_size, kodoc_factory_max_symbol_size(encoder_factory)); EXPECT_EQ(symbols, kodoc_symbols(encoder)); EXPECT_EQ(symbol_size, kodoc_symbol_size(encoder)); EXPECT_EQ(symbols, kodoc_factory_max_symbols(decoder_factory)); EXPECT_EQ(symbol_size, kodoc_factory_max_symbol_size(decoder_factory)); EXPECT_EQ(symbols, kodoc_symbols(decoder)); EXPECT_EQ(symbol_size, kodoc_symbol_size(decoder)); EXPECT_EQ(symbols * symbol_size, kodoc_block_size(encoder)); EXPECT_EQ(symbols * symbol_size, kodoc_block_size(decoder)); EXPECT_TRUE(kodoc_factory_max_payload_size(encoder_factory) >= kodoc_payload_size(encoder)); EXPECT_TRUE(kodoc_factory_max_payload_size(decoder_factory) >= kodoc_payload_size(decoder)); EXPECT_EQ(kodoc_factory_max_payload_size(encoder_factory), kodoc_factory_max_payload_size(decoder_factory)); if (encoder_type == kodoc_sparse_full_vector || encoder_type == kodoc_sparse_seed) { // Set the coding vector density on the encoder kodoc_set_density(encoder, 0.2); EXPECT_EQ(0.2, kodoc_density(encoder)); } uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); uint8_t** input_symbols = NULL; uint8_t** output_symbols = NULL; // Allocate symbols in non-contiguous buffers input_symbols = (uint8_t**) malloc(symbols * sizeof(uint8_t*)); output_symbols = (uint8_t**) malloc(symbols * sizeof(uint8_t*)); for (uint32_t i = 0; i < symbols; ++i) { // Create the individual symbols for the encoder input_symbols[i] = (uint8_t*) malloc(symbol_size); // Randomize input data for (uint32_t j = 0; j < symbol_size; ++j) input_symbols[i][j] = rand() % 256; // Store the symbol pointer in the encoder kodoc_set_const_symbol(encoder, i, input_symbols[i], symbol_size); // Create the output symbol buffers for the decoder output_symbols[i] = (uint8_t*) malloc(symbol_size); // Specify the output buffers used for decoding kodoc_set_mutable_symbol(decoder, i, output_symbols[i], symbol_size); } if (kodoc_has_symbol_decoding_status_updater_interface(decoder)) { EXPECT_FALSE(kodoc_is_status_updater_enabled(decoder)); kodoc_set_status_updater_on(decoder); EXPECT_TRUE(kodoc_is_status_updater_enabled(decoder)); kodoc_set_status_updater_off(decoder); EXPECT_FALSE(kodoc_is_status_updater_enabled(decoder)); } else { EXPECT_TRUE( decoder_type == kodoc_fulcrum || decoder_type == kodoc_reed_solomon ); } EXPECT_TRUE(kodoc_is_complete(decoder) == 0); while (!kodoc_is_complete(decoder)) { kodoc_write_payload(encoder, payload); kodoc_read_payload(decoder, payload); } EXPECT_TRUE(kodoc_is_complete(decoder) != 0); EXPECT_EQ(symbols, kodoc_rank(decoder)); EXPECT_EQ(symbols, kodoc_symbols_uncoded(decoder)); EXPECT_EQ(0U, kodoc_symbols_partially_decoded(decoder)); EXPECT_EQ(0U, kodoc_symbols_missing(decoder)); assert(input_symbols); assert(output_symbols); // Compare the input and output symbols one-by-one for (uint32_t i = 0; i < symbols; ++i) { EXPECT_EQ(memcmp(input_symbols[i], output_symbols[i], symbol_size), 0); free(input_symbols[i]); free(output_symbols[i]); } free(input_symbols); free(output_symbols); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); }
int main() { // Seed the random number generator to produce different data every time srand(time(NULL)); // Set the number of symbols and the symbol size uint32_t max_symbols = 10; uint32_t max_symbol_size = 100; // Here we select the codec we wish to use int32_t codec = kodoc_sparse_seed; // Here we select the finite field to use. // For the sparse seed codec, we can choose kodoc_binary, kodoc_binary4 or // kodoc_binary8 (kodoc_binary is recommended for high performance) int32_t finite_field = kodoc_binary8; kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); // The coding vector density on the encoder is set with // kodoc_set_density(). // Note: the density can be adjusted at any time. This feature can be used // to adapt to changing network conditions. printf("The density defaults to: %0.2f\n", kodoc_density(encoder)); kodoc_set_density(encoder, 0.4); printf("The density was set to: %0.2f\n", kodoc_density(encoder)); // A low density setting can lead to a large number of redundant symbols. // In practice, the value should be tuned to the specific scenario. // Allocate some storage for a "payload". The payload is what we would // eventually send over a network. uint32_t bytes_used; uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); // Allocate input and output data buffers uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); // Fill the input buffer with random data uint32_t i = 0; for(; i < block_size; ++i) data_in[i] = rand() % 256; // Assign the data buffers to the encoder and decoder kodoc_set_const_symbols(encoder, data_in, block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); // Install a custom trace function for the decoder kodoc_set_trace_callback(decoder, trace_callback, NULL); uint32_t lost_payloads = 0; uint32_t received_payloads = 0; while (!kodoc_is_complete(decoder)) { // The encoder will use a certain amount of bytes of the payload buffer bytes_used = kodoc_write_payload(encoder, payload); printf("Payload generated by encoder, bytes used = %d\n", bytes_used); // Simulate a channel with a 50% loss rate if (rand() % 2) { lost_payloads++; printf("Symbol lost on channel\n\n"); continue; } // Pass the generated packet to the decoder received_payloads++; kodoc_read_payload(decoder, payload); printf("Payload processed by decoder, current rank = %d\n\n", kodoc_rank(decoder)); } printf("Number of lost payloads: %d\n", lost_payloads); printf("Number of received payloads: %d\n", received_payloads); // Check that we properly decoded the data if (memcmp(data_in, data_out, block_size) == 0) { printf("Data decoded correctly\n"); } else { printf("Unexpected failure to decode, please file a bug report :)\n"); } // Free the allocated buffers and the kodo objects free(data_in); free(data_out); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); return 0; }