Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2013 George Tzanetakis <gtzan@cs.uvic.ca> 00003 ** 00004 ** This program is free software; you can redistribute it and/or modify 00005 ** it under the terms of the GNU General Public License as published by 00006 ** the Free Software Foundation; either version 2 of the License, or 00007 ** (at your option) any later version. 00008 ** 00009 ** This program is distributed in the hope that it will be useful, 00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 ** GNU General Public License for more details. 00013 ** 00014 ** You should have received a copy of the GNU General Public License 00015 ** along with this program; if not, write to the Free Software 00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include <marsyas/debug/file_io.h> 00020 00021 static const char magic_id[] = "#marsystemrecording"; 00022 00023 namespace Marsyas { namespace Debug { 00024 00025 void copy_swap_bytes(char *destination, const char * source, int size ) 00026 { 00027 #ifdef MARSYAS_BIGENDIAN 00028 for (size_t i = 0; i < size; ++i) 00029 destination[i] = source[size - i - 1]; 00030 #else 00031 std::memcpy(destination, source, size); 00032 #endif 00033 } 00034 00035 00036 FileWriter::FileWriter( const std::string & filename, MarSystem * system ) 00037 { 00038 recursive_store_descriptor(system); 00039 00040 m_file.open(filename.c_str(), 00041 std::ios_base::out | std::ios_base::binary); 00042 // TODO: check for error. 00043 00044 write_magic(); 00045 write_header(); 00046 } 00047 00048 FileWriter::~FileWriter() 00049 { 00050 m_file.close(); 00051 } 00052 00053 void FileWriter::recursive_store_descriptor( MarSystem * system ) 00054 { 00055 MarControlPtr out_samples_ctl = system->getControl("mrs_natural/onSamples"); 00056 MarControlPtr out_observations_ctl = system->getControl("mrs_natural/onObservations"); 00057 assert(!out_samples_ctl.isInvalid()); 00058 assert(!out_observations_ctl.isInvalid()); 00059 00060 SystemDescriptor descriptor; 00061 descriptor.path = system->getAbsPath(); 00062 descriptor.out_columns = out_samples_ctl->to<mrs_natural>(); 00063 descriptor.out_rows = out_observations_ctl->to<mrs_natural>(); 00064 00065 m_descriptors.push_back(descriptor); 00066 00067 std::vector<MarSystem*> children = system->getChildren(); 00068 for (MarSystem *child : children) 00069 recursive_store_descriptor(child); 00070 } 00071 00072 void FileWriter::write_magic() 00073 { 00074 m_file << magic_id << std::endl; 00075 } 00076 00077 void FileWriter::write_header() 00078 { 00079 std::ostringstream header; 00080 for (const auto & descriptor : m_descriptors) 00081 { 00082 header << descriptor.path 00083 << ' ' << descriptor.out_columns 00084 << ' ' << descriptor.out_rows 00085 << std::endl; 00086 } 00087 00088 m_file << header.str() << "." << std::endl; 00089 } 00090 00091 bool FileWriter::write_record( const Record & record ) 00092 { 00093 std::vector<const realvec*> data; 00094 00095 for (const auto & descriptor : m_descriptors) 00096 { 00097 const realvec * output; 00098 00099 try 00100 { 00101 const Record::Entry & record_entry = record.entries().at(descriptor.path); 00102 output = &record_entry.output; 00103 } 00104 catch (const std::out_of_range &) 00105 { 00106 std::cerr << "Marsyas::Debug::FileWriter: Record has no entry for path: " 00107 << descriptor.path << std::endl; 00108 return false; 00109 } 00110 00111 if (output->getRows() != descriptor.out_rows || 00112 output->getCols() != descriptor.out_columns) 00113 { 00114 std::cerr << "Marsyas::Debug::FileWriter: Record entry format mismatch for path: " 00115 << descriptor.path << std::endl; 00116 return false; 00117 } 00118 00119 data.push_back(output); 00120 } 00121 00122 for (const realvec * d : data) 00123 { 00124 const realvec & vector = *d; 00125 for (int i = 0; i < vector.getSize(); ++i) 00126 { 00127 char bytes[sizeof(mrs_real)]; 00128 to_bytes<mrs_real>( vector(i), bytes ); 00129 m_file.write( bytes, sizeof(mrs_real) ); 00130 } 00131 } 00132 00133 return true; 00134 } 00135 00136 00137 FileReader::FileReader( const std::string & filename ): 00138 m_record_size(0) 00139 { 00140 m_file.open(filename, 00141 std::ios_base::in | std::ios_base::binary); 00142 00143 if (!read_magic()) { 00144 std::cerr << "Marsyas::Debug::FileReader: Wrong file type!" << std::endl; 00145 m_file.close(); 00146 return; 00147 } 00148 00149 if (!read_header()) { 00150 std::cerr << "Marsyas::Debug::FileReader: Error reading header!" << std::endl; 00151 m_file.close(); 00152 return; 00153 } 00154 } 00155 00156 FileReader::~FileReader() 00157 { 00158 m_file.close(); 00159 } 00160 00161 void FileReader::rewind() 00162 { 00163 if (m_start_pos == (pos_t)-1) 00164 return; 00165 00166 // Before C++11, and always in GCC, 00167 // seekg() will not clear error flags (e.g. eof) on success. 00168 m_file.clear(); 00169 m_file.seekg(m_start_pos); 00170 00171 if (m_file.fail()) 00172 std::cerr << "Marsyas::Debug::FileReader: Error rewinding!" << std::endl; 00173 } 00174 00175 00176 bool FileReader::read_magic() 00177 { 00178 char id[sizeof magic_id]; 00179 m_file.read(id, sizeof magic_id); 00180 if (m_file.fail()) 00181 return false; 00182 id[m_file.gcount()] = 0; 00183 bool ok = strcmp(id, magic_id) == 0; 00184 return ok; 00185 } 00186 00187 bool FileReader::read_header() 00188 { 00189 while (!m_file.eof()) 00190 { 00191 SystemDescriptor descriptor; 00192 00193 m_file >> descriptor.path; 00194 if (descriptor.path == ".") 00195 break; 00196 00197 m_file >> descriptor.out_columns; 00198 if (m_file.fail()) 00199 return false; 00200 00201 m_file >> descriptor.out_rows; 00202 if (m_file.fail()) 00203 return false; 00204 00205 m_descriptors.push_back(descriptor); 00206 00207 m_record_size += descriptor.out_columns * descriptor.out_rows; 00208 } 00209 00210 if (!m_descriptors.size()) 00211 { 00212 std::cerr << "Marsyas::Debug::FileReader: No header entries!" << std::endl; 00213 return false; 00214 } 00215 00216 m_file.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ); 00217 00218 m_start_pos = m_file.tellg(); 00219 00220 return true; 00221 } 00222 00223 bool FileReader::read_record( Record & record ) 00224 { 00225 if (!m_record_size || m_start_pos == (pos_t)-1 || m_file.eof()) 00226 { 00227 std::cerr << "Marsyas::Debug::FileReader: Nothing to read." << std::endl; 00228 return false; 00229 } 00230 00231 for (const auto & descriptor : m_descriptors) 00232 { 00233 realvec data(descriptor.out_rows, descriptor.out_columns); 00234 00235 for (int i = 0; i < data.getSize(); ++i) 00236 { 00237 char bytes[sizeof(mrs_real)]; 00238 m_file.read( bytes, sizeof(mrs_real) ); 00239 from_bytes<mrs_real>( data.getData()[i], bytes ); 00240 } 00241 if (m_file.fail()) 00242 return false; 00243 00244 Record::Entry entry; 00245 entry.output = data; 00246 record.insert(descriptor.path, entry); 00247 } 00248 00249 return true; 00250 } 00251 00252 }}