Line data Source code
1 : #include "Module/Stateful/Source/User/Source_user_binary.hpp" 2 : #include "Tools/Algo/Bit_packer/Bit_packer.hpp" 3 : #include "Tools/Exception/exception.hpp" 4 : 5 : using namespace spu; 6 : using namespace spu::module; 7 : 8 : template<typename B> 9 51 : Source_user_binary<B>::Source_user_binary(const int max_data_size, 10 : const std::string& filename, 11 : const bool auto_reset, 12 : const bool fifo_mode) 13 : : Source<B>(max_data_size) 14 51 : , source_file(filename.c_str(), std::ios::in | std::ios::binary) 15 51 : , auto_reset(fifo_mode ? true : auto_reset) 16 51 : , fifo_mode(fifo_mode) 17 51 : , done(false) 18 51 : , n_left(0) 19 51 : , memblk(max_data_size) 20 102 : , left_bits(CHAR_BIT) 21 : { 22 51 : const std::string name = "Source_user_binary"; 23 51 : this->set_name(name); 24 : 25 51 : if (source_file.fail()) 26 : { 27 0 : std::stringstream message; 28 0 : message << "'filename' file name is not valid: sink file failbit is set."; 29 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str()); 30 0 : } 31 51 : } 32 : 33 : template<typename B> 34 : void 35 0 : Source_user_binary<B>::reset() 36 : { 37 0 : source_file.clear(); 38 0 : if (!this->fifo_mode) source_file.seekg(0, std::ios::beg); 39 0 : if (source_file.fail()) 40 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, "Could not go back to the beginning of the file."); 41 0 : this->done = false; 42 0 : this->n_left = 0; 43 0 : } 44 : 45 : template<typename B> 46 : bool 47 23476 : Source_user_binary<B>::is_done() const 48 : { 49 23476 : return this->done; 50 : } 51 : 52 : template<typename B> 53 : void 54 11768 : Source_user_binary<B>::_generate(B* out_data, uint32_t* out_count, const size_t frame_id) 55 : { 56 11768 : if (this->is_done()) 57 : { 58 14 : std::fill(out_data, out_data + this->max_data_size, (B)0); 59 14 : *out_count = 0; 60 : } 61 : else 62 : { 63 11754 : size_t n_bytes_read = 0; 64 11754 : const size_t n_bytes_needed = 65 11754 : (size_t)(this->max_data_size - this->n_left + CHAR_BIT - 1) / CHAR_BIT; // number of bytes needed 66 : 67 11754 : for (size_t i = 0; i < this->n_left; i++) 68 0 : out_data[i] = this->left_bits[i]; 69 : 70 23457 : while (n_bytes_read < n_bytes_needed) 71 : { 72 11754 : source_file.read(this->memblk.data() + n_bytes_read, n_bytes_needed - n_bytes_read); 73 11754 : n_bytes_read += source_file.gcount(); 74 : 75 11754 : if (source_file.fail()) 76 : { 77 51 : if (source_file.eof()) 78 : { 79 51 : if (this->auto_reset) 80 0 : this->reset(); 81 : else 82 51 : break; 83 : } 84 : else 85 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, "Unknown error during file reading."); 86 : } 87 : } 88 : 89 11754 : if (this->n_left + n_bytes_read * CHAR_BIT <= (size_t)this->max_data_size) 90 : { 91 11754 : *out_count = this->n_left + n_bytes_read * CHAR_BIT; 92 : 93 11754 : if (!this->auto_reset && source_file.eof()) 94 : { 95 51 : this->done = true; 96 51 : if (this->n_left + n_bytes_read * CHAR_BIT == 0) 97 : { 98 5 : if (frame_id == 0) 99 5 : throw tools::processing_aborted(__FILE__, __LINE__, __func__); 100 : else 101 : { 102 0 : std::fill(out_data, out_data + this->max_data_size, (B)0); 103 0 : *out_count = 0; 104 0 : return; 105 : } 106 : } 107 : } 108 : 109 11749 : tools::Bit_packer::unpack(this->memblk.data(), out_data + this->n_left, n_bytes_read * CHAR_BIT); 110 11749 : std::fill(out_data + this->n_left + n_bytes_read * CHAR_BIT, out_data + this->max_data_size, (B)0); 111 : 112 11749 : int tmp_n_left = ((int)n_bytes_read * (int)CHAR_BIT) - (this->max_data_size - (int)this->n_left); 113 11749 : this->n_left = tmp_n_left < 0 ? (size_t)0 : (size_t)tmp_n_left; 114 : } 115 : else 116 : { 117 0 : *out_count = this->max_data_size; 118 : 119 0 : tools::Bit_packer::unpack(this->memblk.data(), out_data + this->n_left, this->max_data_size - this->n_left); 120 : 121 0 : int tmp_n_left = ((int)n_bytes_read * (int)CHAR_BIT) - (this->max_data_size - (int)this->n_left); 122 0 : this->n_left = tmp_n_left < 0 ? (size_t)0 : (size_t)tmp_n_left; 123 : 124 0 : if (this->n_left) 125 : { 126 : // re-unpack last byte && store into left_bits 127 0 : tools::Bit_packer::unpack(this->memblk.data() + n_bytes_needed - 1, this->left_bits.data(), 8); 128 : 129 : // shift the left bits to the beginning of the array 130 0 : for (size_t i = 0; i < this->n_left; i++) 131 0 : this->left_bits[i] = this->left_bits[i + CHAR_BIT - this->n_left]; 132 : } 133 : } 134 : } 135 : } 136 : 137 : // ==================================================================================== explicit template instantiation 138 : template class spu::module::Source_user_binary<int8_t>; 139 : template class spu::module::Source_user_binary<uint8_t>; 140 : template class spu::module::Source_user_binary<int16_t>; 141 : template class spu::module::Source_user_binary<uint16_t>; 142 : template class spu::module::Source_user_binary<int32_t>; 143 : template class spu::module::Source_user_binary<uint32_t>; 144 : template class spu::module::Source_user_binary<int64_t>; 145 : template class spu::module::Source_user_binary<uint64_t>; 146 : template class spu::module::Source_user_binary<float>; 147 : template class spu::module::Source_user_binary<double>; 148 : // ==================================================================================== explicit template instantiation