TEST(TestReedSolomonCodes, test_encode_decode) { { kodo::rs_encoder<fifi::binary8>::factory encoder_factory(255, 1600); kodo::rs_decoder<fifi::binary8>::factory decoder_factory(255, 1600); uint32_t symbols = rand_symbols(255); uint32_t symbol_size = rand_symbol_size(); encoder_factory.set_symbols(symbols); encoder_factory.set_symbol_size(symbol_size); decoder_factory.set_symbols(symbols); decoder_factory.set_symbol_size(symbol_size); auto encoder = encoder_factory.build(); auto decoder = decoder_factory.build(); // Encode/decode operations EXPECT_TRUE(encoder->payload_size() == decoder->payload_size()); std::vector<uint8_t> payload(encoder->payload_size()); std::vector<uint8_t> data_in = random_vector(encoder->block_size()); encoder->set_symbols(sak::storage(data_in)); uint32_t symbol_count = 0; while( !decoder->is_complete() ) { encoder->encode( &payload[0] ); decoder->decode( &payload[0] ); ++symbol_count; } // A reed solomon code should be able to decode // with exactly k symbols EXPECT_EQ(symbol_count, symbols); std::vector<uint8_t> data_out(decoder->block_size(), '\0'); decoder->copy_symbols(sak::storage(data_out)); EXPECT_TRUE(std::equal(data_out.begin(), data_out.end(), data_in.begin())); } }
TEST(TestReedSolomonCodes, test_construct) { { kodo::rs_encoder<fifi::binary8>::factory encoder_factory(255, 1600); encoder_factory.set_symbols(128); encoder_factory.set_symbol_size(1600); auto encoder = encoder_factory.build(); kodo::rs_decoder<fifi::binary8>::factory decoder_factory(255, 1600); decoder_factory.set_symbols(128); decoder_factory.set_symbol_size(1600); auto decoder = decoder_factory.build(); } }
static void test_decoder(uint32_t max_symbols, uint32_t max_symbol_size, codec code, field field) { decoder_factory decoder_factory( code, field, max_symbols, max_symbol_size); decoder decoder = decoder_factory.build(); test_coder(decoder, max_symbols, max_symbol_size, code); // Decoder methods // Some codecs do not provide write_payload, i.e. recoding if (code == codec::seed || code == codec::sparse_seed || code == codec::fulcrum || code == codec::reed_solomon) { EXPECT_FALSE(decoder.has_write_payload()); } else { EXPECT_TRUE(decoder.has_write_payload()); } EXPECT_GE(0U, decoder.symbols_uncoded()); EXPECT_GE(0U, decoder.symbols_partially_decoded()); if (code == codec::on_the_fly || code == codec::sliding_window) { EXPECT_TRUE(decoder.has_partial_decoding_interface()); EXPECT_FALSE(decoder.is_partially_complete()); for (uint32_t i = 0; i < decoder.symbols(); ++i) { EXPECT_FALSE(decoder.is_symbol_pivot(i)); } } else if (code == codec::full_vector || code == codec::perpetual) { EXPECT_FALSE(decoder.has_partial_decoding_interface()); } }
int main() { // Set the number of symbols (i.e. the generation size in RLNC // terminology) and the size of a symbol in bytes uint32_t symbols = 42; uint32_t symbol_size = 100; typedef kodo::full_rlnc_encoder<fifi::binary8> rlnc_encoder; typedef kodo::full_rlnc_decoder<fifi::binary8> rlnc_decoder; // In the following we will make an encoder/decoder factory. // The factories are used to build actual encoders/decoders rlnc_encoder::factory encoder_factory(symbols, symbol_size); auto encoder = encoder_factory.build(); rlnc_decoder::factory decoder_factory(symbols, symbol_size); auto decoder = decoder_factory.build(); std::vector<uint8_t> payload(encoder->payload_size()); std::vector<uint8_t> data_in(encoder->block_size()); // Just for fun - fill the data with random data for(auto &e: data_in) e = rand() % 256; // Assign the data buffer to the encoder so that we may start // to produce encoded symbols from it encoder->set_symbols(sak::storage(data_in)); while( !decoder->is_complete() ) { // Encode a packet into the payload buffer encoder->encode( &payload[0] ); // Pass that packet to the decoder decoder->decode( &payload[0] ); } }
TEST(TestTraceLinearBlockDecoder, print) { typedef fifi::binary field_type; typedef kodo::full_rlnc_decoder<field_type, kodo::enable_trace> decoder_type; uint32_t symbols = 3; uint32_t symbol_size = 10; decoder_type::factory decoder_factory(symbols, symbol_size); auto decoder = decoder_factory.build(); // Check that this code compiles { std::stringstream out; decoder->print_decoder_state(out); std::string result = "000 ?: 0 0 0 \n" "001 ?: 0 0 0 \n" "002 ?: 0 0 0 \n"; EXPECT_EQ(result, out.str()); } // Create a empty symbol and put it in std::vector<uint8_t> coefficients( decoder->coefficient_vector_size(), '\0'); std::vector<uint8_t> symbol( decoder->symbol_size(), '\0'); decoder->decode_symbol(&symbol[0], &coefficients[0]); { std::stringstream out; decoder->print_decoder_state(out); std::string result = "000 ?: 0 0 0 \n" "001 ?: 0 0 0 \n" "002 ?: 0 0 0 \n"; EXPECT_EQ(result, out.str()); } // Create a dummy symbol and put it in std::fill(coefficients.begin(), coefficients.end(), '\0'); fifi::set_value<field_type>(&coefficients[0], 1, 1U); fifi::set_value<field_type>(&coefficients[0], 2, 1U); std::fill(symbol.begin(), symbol.end(), 'a'); decoder->decode_symbol(&symbol[0], &coefficients[0]); { std::stringstream out; decoder->print_decoder_state(out); std::string result = "000 ?: 0 0 0 \n" "001 C: 0 1 1 \n" "002 ?: 0 0 0 \n"; EXPECT_EQ(result, out.str()); } std::fill(symbol.begin(), symbol.end(), 'b'); decoder->decode_symbol(&symbol[0], 0U); { std::stringstream out; decoder->print_decoder_state(out); std::string result = "000 U: 1 0 0 \n" "001 C: 0 1 1 \n" "002 ?: 0 0 0 \n"; EXPECT_EQ(result, out.str()); } }
int main(void) { // Seed random number generator to produce different results every time srand((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 uint32_t max_symbols = 6; uint32_t max_symbol_size = 32; // Initilization of encoder and decoder kodocpp::encoder_factory encoder_factory( kodocpp::codec::full_vector, kodocpp::field::binary8, max_symbols, max_symbol_size); kodocpp::encoder encoder = encoder_factory.build(); kodocpp::decoder_factory decoder_factory( kodocpp::codec::full_vector, kodocpp::field::binary8, max_symbols, max_symbol_size); kodocpp::decoder decoder = decoder_factory.build(); // 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 input and output data buffers std::vector<uint8_t> data_in(encoder.block_size()); std::vector<uint8_t> data_out(decoder.block_size()); // Fill the input buffer with random data std::generate(data_in.begin(), data_in.end(), rand); // Set the symbol storage for the encoder and decoder encoder.set_const_symbols(data_in.data(), encoder.block_size()); decoder.set_mutable_symbols(data_out.data(), decoder.block_size()); // Install the default trace function for encoder (writes to stdout) encoder.set_trace_stdout(); // Install a custom trace function for the decoder auto callback = [](const std::string& zone, const std::string& data) { std::set<std::string> filters = { "decoder_state", "symbol_coefficients_before_read_symbol", "symbol_index_before_read_uncoded_symbol" }; if (filters.count(zone)) { std::cout << zone << ":" << std::endl; std::cout << data << std::endl; } }; decoder.set_trace_callback(callback); while (!decoder.is_complete()) { encoder.write_payload(payload.data()); // Simulate a lossy channel where we are losing 50% of the packets if ((rand() % 2) == 0) { continue; } 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; } return 0; }
uint8_t *decode(uint32_t N, uint32_t max_symbols, uint32_t max_symbol_size, kodocpp::field field_size, ENCODED_DATA encoded_data_info) { kodocpp::decoder_factory decoder_factory( //kodocpp::codec::reed_solomon, kodocpp::codec::full_vector, field_size, max_symbols, max_symbol_size); //std::vector< std::vector < std::vector<uint8_t> > > *encoded_data = encoded_data_info.vdata; std::vector< std::vector < std::vector<uint8_t> > > *encoded_data = convert_from_C_to_vector(encoded_data_info); std::cout << "decode=======================" << std::endl; std::vector< uint8_t *> decoded_symbols; int num_blocks = encoded_data_info.num_blocks; int data_size =0; for(int i=0; i < num_blocks; i++) { // std::cout << "decode=======================" << std::endl; //std::cout << "encoded_dat " << encoded_data_info.num_blocks << std::endl; //std::cout << "encoded_dat " << encoded_data_info.encoded_symbol_size << std::endl; kodocpp::decoder decoder = decoder_factory.build(); std::vector<uint8_t> data_out(decoder.block_size()); decoder.set_mutable_symbols(data_out.data(), decoder.block_size()); // std::cout << "=========== " << std::endl; for(int j=0; j < max_symbols; j++) { decoder.read_payload( (*encoded_data)[j][i].data()); } uint8_t *decoded_symbol = new uint8_t[max_symbol_size*max_symbols + 1]; if( decoder.is_complete() ) { memcpy(decoded_symbol, data_out.data(), data_out.size()); } decoded_symbol[max_symbol_size*max_symbols + 1]='\0'; data_size += data_out.size(); decoded_symbols.push_back(decoded_symbol); } uint8_t *decoded_data = (uint8_t *)malloc( sizeof(uint8_t)*(data_size + 1) ); uint8_t *p = decoded_data; for(int i=0; i < decoded_symbols.size(); i++) { memcpy(p, decoded_symbols[i], strlen((char *)decoded_symbols[i])); p = p + strlen((char *)decoded_symbols[i]); free( decoded_symbols[i]); } decoded_data[data_size] = '\0'; decoded_symbols.clear(); return decoded_data; }
int main() { // Set the number of symbols (i.e. the generation size in RLNC // terminology) and the size of a symbol in bytes uint32_t max_symbols = 42; uint32_t max_symbol_size = 64; std::string encode_filename = "encode-file.bin"; // Create a test file for encoding. std::ofstream encode_file; encode_file.open (encode_filename, std::ios::binary); uint32_t file_size = 50000; std::vector<char> encode_data(file_size); std::vector<char> decode_data; // Just write some bytes to the file for(uint32_t i = 0; i < file_size; ++i) { encode_data[i] = rand() % 255; } encode_file.write(&encode_data[0], file_size); encode_file.close(); // Select the encoding and decoding algorithms typedef kodo::full_rlnc_encoder<fifi::binary> encoder_t; typedef kodo::full_rlnc_decoder<fifi::binary> decoder_t; // Now for the encoder we use a file_encoder with the chosen // encoding algorithm typedef kodo::file_encoder<encoder_t> file_encoder_t; // For decoding we use an object_decoder with the chosen // decoding algorithm typedef kodo::object_decoder<decoder_t> object_decoder_t; // Create the encoder factory - builds the individual encoders used file_encoder_t::factory encoder_factory(max_symbols, max_symbol_size); // Create the actual file encoder using the encoder factory and // the filename of the file to be encoded file_encoder_t file_encoder(encoder_factory, encode_filename); // Create the decoder factory - build the individual decoders used object_decoder_t::factory decoder_factory(max_symbols, max_symbol_size); // Create the object decoder using the decoder factory and the // size of the file to be decoded object_decoder_t object_decoder(decoder_factory, file_size); // Now in the following loop we go through all the encoders // needed to encode the entire file. We the build the corresponding // decoder and decode the chunk immediately. In practice where // encoders and decoders are on different devices e.g. connected // over a network, we would have to pass also the encoder and decoder // index between the source and sink to allow the correct data would // passed from encoder to corresponding decoder. for(uint32_t i = 0; i < file_encoder.encoders(); ++i) { auto encoder = file_encoder.build(i); auto decoder = object_decoder.build(i); // Set the encoder non-systematic if(kodo::has_systematic_encoder<encoder_t>::value) kodo::set_systematic_off(encoder); std::vector<uint8_t> payload(encoder->payload_size()); while( !decoder->is_complete() ) { // Encode a packet into the payload buffer encoder->encode( &payload[0] ); // In practice send the payload over a network, save it to // a file etc. Then when needed build and pass it to the decoder // Pass that packet to the decoder decoder->decode( &payload[0] ); } std::vector<uint8_t> data_out(decoder->block_size()); decoder->copy_symbols(sak::storage(data_out)); data_out.resize(decoder->bytes_used()); decode_data.insert(decode_data.end(), data_out.begin(), data_out.end()); } // Check we properly decoded the data if (std::equal(decode_data.begin(), decode_data.end(), encode_data.begin())) { std::cout << "Data decoded correctly" << std::endl; } else { std::cout << "Unexpected failure to decode " << "please file a bug report :)" << std::endl; } }
int main() { //! [2] // Set the number of symbols (i.e. the generation size in RLNC // terminology) and the size of a symbol in bytes uint32_t max_symbols = 40; uint32_t max_symbol_size = 64; uint32_t object_size = 6400; //! [3] //! [4] using storage_encoder = kodo::object::storage_encoder< kodo::shallow_full_rlnc_encoder<fifi::binary>, kodo::fixed_partitioning_scheme>; using storage_decoder = kodo::object::storage_decoder< kodo::shallow_full_rlnc_decoder<fifi::binary>, kodo::fixed_partitioning_scheme>; //! [5] storage_encoder::factory encoder_factory(max_symbols, max_symbol_size); storage_decoder::factory decoder_factory(max_symbols, max_symbol_size); std::vector<uint8_t> data_out(object_size, '\0'); std::vector<uint8_t> data_in(object_size, 'x'); encoder_factory.set_storage(sak::storage(data_in)); decoder_factory.set_storage(sak::storage(data_out)); auto object_encoder = encoder_factory.build(); auto object_decoder = decoder_factory.build(); std::cout << "Object size = " << object_size << std::endl; std::cout << "Encoder blocks = " << object_encoder->blocks() << std::endl; std::cout << "Decoder blocks = " << object_decoder->blocks() << std::endl; //! [6] for (uint32_t i = 0; i < object_encoder->blocks(); ++i) { std::cout << "Block = " << i << " symbols = " << object_encoder->symbols(i) << " symbol size = " << object_encoder->symbol_size(i) << std::endl; } //! [7] for (uint32_t i = 0; i < object_encoder->blocks(); ++i) { auto e = object_encoder->build(i); auto d = object_decoder->build(i); std::vector<uint8_t> payload(e->payload_size()); while (!d->is_complete()) { e->encode( payload.data() ); // Here we would send and receive the payload over a // network. Lets throw away some packet to simulate. if (rand() % 2) { continue; } d->decode( payload.data() ); } } // Check we properly decoded the data if (data_in == data_out) { std::cout << "Data decoded correctly" << std::endl; } else { std::cout << "Unexpected failure to decode " << "please file a bug report :)" << std::endl; } }
int main() { // Seed the random number generator to produce different data every time srand((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 uint32_t max_symbols = 16; uint32_t max_symbol_size = 1400; //! [0] // In the following we will make an encoder/decoder factory. // The factories are used to build actual encoders/decoders kodocpp::encoder_factory encoder_factory( kodocpp::codec::full_vector, kodocpp::field::binary8, max_symbols, max_symbol_size); kodocpp::encoder encoder = encoder_factory.build(); kodocpp::decoder_factory decoder_factory( kodocpp::codec::full_vector, kodocpp::field::binary8, max_symbols, max_symbol_size); kodocpp::decoder decoder1 = decoder_factory.build(); kodocpp::decoder decoder2 = decoder_factory.build(); //! [1] std::vector<uint8_t> payload(encoder.payload_size()); 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 from it encoder.set_const_symbols(data_in.data(), encoder.block_size()); // Create a buffer which will contain the decoded data, and we assign // that buffer to the decoder std::vector<uint8_t> data_out1(decoder1.block_size()); std::vector<uint8_t> data_out2(decoder2.block_size()); decoder1.set_mutable_symbols(data_out1.data(), decoder1.block_size()); decoder2.set_mutable_symbols(data_out2.data(), decoder2.block_size()); uint32_t encoded_count = 0; uint32_t dropped_count = 0; // We switch any systematic operations off so the encoder produces // coded symbols from the beginning if (encoder.is_systematic_on()) encoder.set_systematic_off(); //! [2] while (!decoder2.is_complete()) { // Encode a packet into the payload buffer encoder.write_payload(payload.data()); ++encoded_count; if (rand() % 2) { ++dropped_count; } else { // Pass that packet to the decoder1 decoder1.read_payload(payload.data()); } // Create a recoded packet from decoder1 decoder1.write_payload(payload.data()); if (rand() % 2) { ++dropped_count; } else { // Pass the recoded packet to decoder two decoder2.read_payload(payload.data()); } } //! [3] std::cout << "Encoded count = " << encoded_count << std::endl; std::cout << "Dropped count = " << dropped_count << std::endl; // Check if we properly decoded the data if (data_in == data_out2) { std::cout << "Data decoded correctly" << std::endl; } return 0; }
int main() { // Seed the random number generator to produce different data every time srand((uint32_t)time(0)); // Set the number of symbols and the symbol size uint32_t max_symbols = 10; uint32_t max_symbol_size = 100; // Create encoder/decoder factories that we will use to build the actual // encoder and decoder kodocpp::encoder_factory encoder_factory( kodocpp::codec::sparse_seed, kodocpp::field::binary8, max_symbols, max_symbol_size); kodocpp::encoder encoder = encoder_factory.build(); kodocpp::decoder_factory decoder_factory( kodocpp::codec::sparse_seed, kodocpp::field::binary8, max_symbols, max_symbol_size); kodocpp::decoder decoder = decoder_factory.build(); // The coding vector density on the encoder can be set with set_density(). // Note: the density can be adjusted at any time. This feature can be used // to adapt to changing network conditions. std::cout << "The density defaults to: " << encoder.density() << std::endl; encoder.set_density(0.4); std::cout << "The density was set to: " << encoder.density() << std::endl; // 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 std::vector<uint8_t> payload(encoder.payload_size()); // Allocate input and output data buffers std::vector<uint8_t> data_in(encoder.block_size()); std::vector<uint8_t> data_out(decoder.block_size()); // Fill the input buffer with random data std::generate(data_in.begin(), data_in.end(), rand); // Set the symbol storage for the encoder and decoder encoder.set_const_symbols(data_in.data(), encoder.block_size()); decoder.set_mutable_symbols(data_out.data(), decoder.block_size()); // Install a custom trace function for the decoder auto callback = [](const std::string& zone, const std::string& data) { std::set<std::string> filters = { "decoder_state", "symbol_coefficients_before_read_symbol" }; if (filters.count(zone)) { std::cout << zone << ":" << std::endl; std::cout << data << std::endl; } }; decoder.set_trace_callback(callback); uint32_t lost_payloads = 0; uint32_t received_payloads = 0; while (!decoder.is_complete()) { // The encoder will use a certain amount of bytes of the payload buffer uint32_t bytes_used = encoder.write_payload(payload.data()); std::cout << "Payload generated by encoder, bytes used = " << bytes_used << std::endl; // Simulate a channel with a 50% loss rate if ((rand() % 2) == 0) { lost_payloads++; continue; } // Pass the generated packet to the decoder received_payloads++; decoder.read_payload(payload.data()); std::cout << "Payload processed by decoder, current rank = " << decoder.rank() << std::endl << std::endl; } std::cout << "Number of lost payloads: " << lost_payloads << std::endl; std::cout << "Number of received payloads: " << received_payloads << std::endl; // Check if we properly decoded the data if (data_in == data_out) { std::cout << "Data decoded correctly" << std::endl; } else { std::cout << "Unexpected failure to decode, " << "please file a bug report :)" << std::endl; } return 0; }
/// @example use_cached_symbol_decoder.cpp /// /// This example shows how to use the cached symbol decoder to "extract" /// the symbol coding coefficients and the encoded symbol data from an /// incoming symbol. int main() { // The finite field we will use in the example. You can try // with other fields by specifying e.g. fifi::binary8 for the // extension field 2^8 typedef fifi::binary finite_field; // Set the number of symbols (i.e. the generation size in RLNC // terminology) and the size of a symbol in bytes uint32_t symbols = 8; uint32_t symbol_size = 160; // Typdefs for the encoder/decoder type we wish to use typedef kodo::full_rlnc_encoder<finite_field> rlnc_encoder; typedef kodo::full_rlnc_decoder<finite_field> rlnc_decoder; typedef kodo::symbol_info_decoder<finite_field> rlnc_info_decoder; // In the following we will make an encoder/decoder factory. // The factories are used to build actual encoders/decoders. // Each stack we use have their own factories. rlnc_encoder::factory encoder_factory(symbols, symbol_size); auto encoder = encoder_factory.build(); rlnc_decoder::factory decoder_factory(symbols, symbol_size); auto decoder = decoder_factory.build(); rlnc_info_decoder::factory info_decoder_factory(symbols, symbol_size); auto info_decoder = info_decoder_factory.build(); // 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 for(auto &e: data_in) e = rand() % 256; // Assign the data buffer to the encoder so that we may start // to produce encoded symbols from it encoder->set_symbols(sak::storage(data_in)); while( !decoder->is_complete()) { // Encode a packet into the payload buffer encoder->encode( &payload[0] ); // Here we "simulate" a packet loss of approximately 50% // by dropping half of the encoded packets. // When running this example you will notice that the initial // symbols are received systematically (i.e. uncoded). After // sending all symbols once uncoded, the encoder will switch // to full coding, in which case you will see the full encoding // vectors being sent and received. if((rand() % 2) == 0) continue; // Pass the encoded packet to the info decoder. After this // information about the coded symbol can be fetched using the // cached_symbol_decoder API info_decoder->decode( &payload[0] ); if(!info_decoder->cached_symbol_coded()) { // The symbol was uncoded so we may ask the cache which of the // original symbols we have received. std::cout << "Symbol was uncoded, index = " << info_decoder->cached_symbol_index() << std::endl; // Now we pass the data directly into our actual decoder. This is // done using the "Codec API" directly, and not through the "Payload // API" as we would typically do. decoder->decode_symbol( info_decoder->cached_symbol_data(), info_decoder->cached_symbol_index()); } else { // The symbol was coded so we may ask the cache to return // the coding coefficients used to create the encoded symbol. std::cout << "Symbol was coded, encoding vector = "; const uint8_t* c = info_decoder->cached_symbol_coefficients(); // We loop through the coefficient buffer and print the coefficients for(uint32_t i = 0; i < info_decoder->symbols(); ++i) { std::cout << (uint32_t) fifi::get_value<finite_field>(c, i) << " "; } std::cout << std::endl; // Pass that packet to the decoder, as with the uncoded symbols // above we pass it directly to the "Codec API" decoder->decode_symbol(info_decoder->cached_symbol_data(), info_decoder->cached_symbol_coefficients()); } } // The decoder is complete, now copy the symbols from the decoder std::vector<uint8_t> data_out(decoder->block_size()); decoder->copy_symbols(sak::storage(data_out)); // Check 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; } }
// Tests that encoding and decoding a file withe the file encoder // works. TEST(TestFileEncoder, test_file_encoder) { { std::string encode_filename = "encode-file"; std::string decode_filename = "decode-file"; // Write a test file std::ofstream encode_file; encode_file.open (encode_filename, std::ios::binary); uint32_t size = 500; for(uint32_t i = 0; i < size; ++i) { char c = rand() % 255; encode_file.write(&c, 1); } encode_file.close(); typedef kodo::full_rlnc_encoder<fifi::binary> encoder_t; typedef kodo::full_rlnc_decoder<fifi::binary> decoder_t; typedef kodo::file_encoder<encoder_t> file_encoder_t; typedef kodo::object_decoder<decoder_t> object_decoder_t; uint32_t max_symbols = 10; uint32_t max_symbol_size = 10; file_encoder_t::factory encoder_factory( max_symbols, max_symbol_size); file_encoder_t file_encoder(encoder_factory, encode_filename); object_decoder_t::factory decoder_factory( max_symbols, max_symbol_size); object_decoder_t object_decoder(decoder_factory, size); EXPECT_EQ(object_decoder.decoders(), file_encoder.encoders()); // Open the decode file std::ofstream decode_file; decode_file.open (decode_filename, std::ios::binary); for(uint32_t i = 0; i < file_encoder.encoders(); ++i) { auto encoder = file_encoder.build(i); auto decoder = object_decoder.build(i); EXPECT_EQ(encoder->symbols(), decoder->symbols()); EXPECT_EQ(encoder->symbol_size(), decoder->symbol_size()); EXPECT_EQ(encoder->bytes_used(), decoder->bytes_used()); // Set the encoder non-systematic if(kodo::is_systematic_encoder(encoder)) kodo::set_systematic_off(encoder); std::vector<uint8_t> payload(encoder->payload_size()); while( !decoder->is_complete() ) { // Encode a packet into the payload buffer encoder->encode( &payload[0] ); // Pass that packet to the decoder decoder->decode( &payload[0] ); } std::vector<uint8_t> data_out(decoder->block_size()); decoder->copy_symbols(sak::storage(data_out)); decode_file.write( reinterpret_cast<char*>(&data_out[0]), decoder->bytes_used()); } decode_file.close(); } }