/* (**************************************************************************) (* *) (* Schifra *) (* Reed-Solomon Error Correcting Code Library *) (* *) (* Release Version 0.0.1 *) (* http://www.schifra.com *) (* Copyright (c) 2000-2020 Arash Partow, All Rights Reserved. *) (* *) (* The Schifra Reed-Solomon error correcting code library and all its *) (* components are supplied under the terms of the General Schifra License *) (* agreement. The contents of the Schifra Reed-Solomon error correcting *) (* code library and all its components may not be copied or disclosed *) (* except in accordance with the terms of that agreement. *) (* *) (* URL: http://www.schifra.com/license.html *) (* *) (**************************************************************************) */ #ifndef INCLUDE_SCHIFRA_REED_SOLOMON_FILE_INTERLEAVER_HPP #define INCLUDE_SCHIFRA_REED_SOLOMON_FILE_INTERLEAVER_HPP #include #include #include "schifra_reed_solomon_interleaving.hpp" #include "schifra_fileio.hpp" namespace schifra { namespace reed_solomon { template class file_interleaver { public: file_interleaver(const std::string& input_file_name, const std::string& output_file_name) { std::size_t remaining_bytes = schifra::fileio::file_size(input_file_name); if (0 == remaining_bytes) { std::cout << "reed_solomon::file_interleaver() - Error: input file has ZERO size." << std::endl; return; } std::ifstream in_stream(input_file_name.c_str(),std::ios::binary); if (!in_stream) { std::cout << "reed_solomon::file_interleaver() - Error: input file could not be opened." << std::endl; return; } std::ofstream out_stream(output_file_name.c_str(),std::ios::binary); if (!out_stream) { std::cout << "reed_solomon::file_interleaver() - Error: output file could not be created." << std::endl; return; } while (remaining_bytes >= (block_length * stack_size)) { process_block(in_stream,out_stream); remaining_bytes -= (block_length * stack_size); } if (remaining_bytes > 0) { process_incomplete_block(in_stream,out_stream,remaining_bytes); } in_stream.close(); out_stream.close(); } private: inline void process_block(std::ifstream& in_stream, std::ofstream& out_stream) { for (std::size_t i = 0; i < stack_size; ++i) { in_stream.read(&block_stack_[i][0],static_cast(block_length)); } interleave(block_stack_); for (std::size_t i = 0; i < stack_size; ++i) { out_stream.write(&block_stack_[i][0],static_cast(block_length)); } } inline void process_incomplete_block(std::ifstream& in_stream, std::ofstream& out_stream, const std::size_t amount) { std::size_t complete_row_count = amount / block_length; std::size_t remainder = amount % block_length; for (std::size_t i = 0; i < complete_row_count; ++i) { in_stream.read(&block_stack_[i][0],static_cast(block_length)); } if (remainder != 0) { in_stream.read(&block_stack_[complete_row_count][0],static_cast(remainder)); } if (remainder == 0) interleave(block_stack_,complete_row_count); else interleave(block_stack_,complete_row_count + 1,remainder); for (std::size_t i = 0; i < complete_row_count; ++i) { out_stream.write(&block_stack_[i][0],static_cast(block_length)); } if (remainder != 0) { out_stream.write(&block_stack_[complete_row_count][0],static_cast(remainder)); } } data_block block_stack_[stack_size]; }; template class file_deinterleaver { public: file_deinterleaver(const std::string& input_file_name, const std::string& output_file_name) { std::size_t input_file_size = schifra::fileio::file_size(input_file_name); if (input_file_size == 0) { std::cout << "reed_solomon::file_deinterleaver() - Error: input file has ZERO size." << std::endl; return; } std::ifstream in_stream(input_file_name.c_str(),std::ios::binary); if (!in_stream) { std::cout << "reed_solomon::file_deinterleaver() - Error: input file could not be opened." << std::endl; return; } std::ofstream out_stream(output_file_name.c_str(),std::ios::binary); if (!out_stream) { std::cout << "reed_solomon::file_deinterleaver() - Error: output file could not be created." << std::endl; return; } for (std::size_t i = 0; i < (input_file_size / (block_length * stack_size)); ++i) { process_block(in_stream,out_stream); } if ((input_file_size % (block_length * stack_size)) != 0) { process_incomplete_block(in_stream,out_stream,(input_file_size % (block_length * stack_size))); } in_stream.close(); out_stream.close(); } private: inline void process_block(std::ifstream& in_stream, std::ofstream& out_stream) { for (std::size_t i = 0; i < stack_size; ++i) { in_stream.read(&block_stack_[i][0],static_cast(block_length)); } deinterleave(block_stack_); for (std::size_t i = 0; i < stack_size; ++i) { out_stream.write(&block_stack_[i][0],static_cast(block_length)); } } inline void process_incomplete_block(std::ifstream& in_stream, std::ofstream& out_stream, const std::size_t amount) { std::size_t complete_row_count = amount / block_length; std::size_t remainder = amount % block_length; for (std::size_t i = 0; i < complete_row_count; ++i) { in_stream.read(&block_stack_[i][0],static_cast(block_length)); } if (remainder != 0) { in_stream.read(&block_stack_[complete_row_count][0],static_cast(remainder)); } if (remainder == 0) deinterleave(block_stack_,complete_row_count); else deinterleave(block_stack_,complete_row_count + 1,remainder); for (std::size_t i = 0; i < complete_row_count; ++i) { out_stream.write(&block_stack_[i][0],static_cast(block_length)); } if (remainder != 0) { out_stream.write(&block_stack_[complete_row_count][0],static_cast(remainder)); } } data_block block_stack_[stack_size]; }; } // namespace reed_solomon } // namespace schifra #endif