Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/debug/file_io.cpp
Go to the documentation of this file.
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 }}