pelib  2.0.0
src/AmplOutput.cpp
Go to the documentation of this file.
00001 /*
00002  Copyright 2015 Nicolas Melot
00003 
00004  This file is part of Pelib.
00005 
00006  Pelib is free software: you can redistribute it and/or modify
00007  it under the terms of the GNU General Public License as published by
00008  the Free Software Foundation, either version 3 of the License, or
00009  (at your option) any later version.
00010 
00011  Pelib is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  GNU General Public License for more details.
00015 
00016  You should have received a copy of the GNU General Public License
00017  along with Pelib. If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 
00021 #include <iostream>
00022 #include <cstdlib>
00023 #include <fstream>
00024 #include <string>
00025 #include <boost/regex.hpp>
00026 #include <boost/algorithm/string.hpp>
00027 #include <iomanip>
00028 
00029 #include <pelib/AmplOutput.hpp>
00030 #include <pelib/AmplOutputScalar.hpp>
00031 #include <pelib/AmplOutputVector.hpp>
00032 #include <pelib/AmplOutputSet.hpp>
00033 #include <pelib/AmplOutputMatrix.hpp>
00034 #include <pelib/AmplDataParser.hpp>
00035 
00036 #include <pelib/ParseException.hpp>
00037 #include <pelib/CastException.hpp>
00038 #include <pelib/PelibException.hpp>
00039 
00040 #ifdef debug
00041 #undef debug
00042 #endif
00043 
00044 #define debug(var) cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #var << " = \"" << var << "\"" << endl;
00045 
00046 using namespace std;
00047 using namespace boost::algorithm;
00048 
00049 namespace pelib
00050 {
00051         /*
00052         AmplOutput::AmplOutput()
00053         {
00054                 // Add parsers
00055                 addParsers();
00056                                 
00057                 // Add interpreters
00058                 addOutputs();
00059         }
00060 
00061         AmplOutput::AmplOutput(std::vector<AmplOutputDataParser*> parsers,
00062                         std::vector<AmplOutputDataOutput*> outputs)
00063         {
00064                 this->parsers = parsers;
00065                 this->outputs = outputs;
00066         }
00067 */
00068         AmplOutput::AmplOutput(std::pair<std::vector<AmplOutputDataParser*>, std::vector<AmplOutputDataOutput*> > handlers)
00069         {
00070                 this->parsers = handlers.first;
00071                 this->outputs = handlers.second;
00072         }
00073 
00074         AmplOutput::~AmplOutput()
00075         {
00076                 deleteParsers();
00077                 deleteOutputs();                        
00078         }
00079 
00080         void
00081         AmplOutput::deleteParsers()
00082         {
00083                 for(std::vector<AmplOutputDataParser*>::iterator i = parsers.begin(); i != parsers.end(); i = parsers.erase(i))
00084                 {
00085                         delete *i;
00086                 }
00087         }
00088 
00089         void
00090         AmplOutput::deleteOutputs()
00091         {
00092                 for(std::vector<AmplOutputDataOutput*>::iterator i = outputs.begin(); i != outputs.end(); i = outputs.erase(i))
00093                 {
00094                         delete *i;
00095                 }
00096         }
00097 
00098         AmplOutput&
00099         AmplOutput::operator=(const AmplOutput &amplOutput)
00100         {
00101                 deleteParsers();
00102                 deleteOutputs();
00103 
00104                 for(std::vector<AmplOutputDataParser*>::const_iterator i = amplOutput.parsers.begin(); i != amplOutput.parsers.end(); i++)
00105                 {
00106                         parsers.push_back((*i)->clone());
00107                 }
00108 
00109                 for(std::vector<AmplOutputDataOutput*>::const_iterator i = amplOutput.outputs.begin(); i != amplOutput.outputs.end(); i++)
00110                 {
00111                         outputs.push_back((*i)->clone());
00112                 }
00113 
00114                 return *this;
00115         }
00116 
00117         Algebra
00118         AmplOutput::parse(std::istream &ampl_data) const
00119         {
00120                 Algebra record;
00121                 std::string line;
00122                 
00123                 while(!getline(ampl_data, line, ';').fail())
00124                 {
00125                         // Read section into string buffer stream
00126                         std::stringstream section;
00127                         section << line;
00128 
00129                         while(!getline(section, line, ';').fail())
00130                         {                       
00131                                 std::vector<AmplOutputDataParser*>::const_iterator iter;
00132                                 for(iter = parsers.begin(); iter != parsers.end(); iter++)
00133                                 {
00134                                         AmplOutputDataParser *parser = *iter;
00135                                         try {
00136                                                 // If any non-blank prefix to be discarded, it must be separated by a new line
00137                                                 std::string regex = std::string("(.*?\\n|)\\s*(")
00138                                                         .append(parser->getGlobalPattern())
00139                                                         .append(")(?:\\s*)");
00140                                                 
00141                                                 boost::cmatch match; // = AlgebraDataParser::match(regex, line);
00142                                                 if(!boost::regex_match(line.c_str(), match, boost::regex(regex)))
00143                                                 {
00144                                                         throw ParseException(std::string("String \"").append(line).append("\" doesn't match regex \"").append(regex).append("\". "));
00145                                                 }
00146 
00147                                                 std::stringstream token;
00148                                                 token.str(match[2]);
00149 
00150                                                 //std::cerr << "Discarded =\"" << match[1] << "\"." << std::endl;
00151                                                 //std::cerr << "Token =\"" << match[2] << "\"." << std::endl;
00152                                                 AlgebraData *data = parser->parse(token);
00153                                                 record.insert(data);
00154 
00155                                                 // Keep only the part we have not parsed
00156                                                 line = match[1];
00157                                                 
00158                                                 // Feed the remaining Output line to parsers Output is more useful information are available
00159                                                 section.str(line);
00160                                                 section.seekp(std::ios_base::beg);
00161                                                 section.clear();
00162 
00163                                                 // No need to try another parser; proceed with the next token in section
00164                                                 break;
00165                                         } catch (ParseException &e)
00166                                         {
00167                                                 // Try next parser
00168                                         }
00169                                 }
00170 
00171                                 // There was no parser for this section; drop it and go to next
00172                                 if(iter == parsers.end())
00173                                 {
00174                                         std::vector<AmplOutputDataParser*>::const_iterator iter;
00175                                         std::vector<AmplOutputDataParser*> parsers = stringParsers();
00176                                         for(iter = parsers.begin(); iter != parsers.end(); iter++)
00177                                         {
00178                                                 AmplOutputDataParser *parser = *iter;
00179                                                 try {
00180                                                         // If any non-blank prefix to be discarded, it must be separated by a new line
00181                                                         std::string regex = std::string("(.*?\\n|)\\s*(")
00182                                                                 .append(parser->getGlobalPattern())
00183                                                                 .append(")(?:\\s*)");
00184                                                         
00185                                                         boost::cmatch match; // = AlgebraDataParser::match(regex, line);
00186                                                         if(!boost::regex_match(line.c_str(), match, boost::regex(regex)))
00187                                                         {
00188                                                                 throw ParseException(std::string("String \"").append(line).append("\" doesn't match regex \"").append(regex).append("\". "));
00189                                                         }
00190                                 
00191 
00192                                                         std::stringstream token;
00193                                                         token.str(match[2]);
00194 
00195                                                         //std::cerr << "Discarded =\"" << match[1] << "\"." << std::endl;
00196                                                         //std::cerr << "Token =\"" << match[2] << "\"." << std::endl;
00197                                                         AlgebraData *data = parser->parse(token);
00198                                                         record.insert(data);
00199 
00200                                                         // Keep only the part we have not parsed
00201                                                         line = match[1];
00202                                                         
00203                                                         // Feed the remaining Output line to parsers Output is more useful information are available
00204                                                         section.str(line);
00205                                                         section.seekp(std::ios_base::beg);
00206                                                         section.clear();
00207 
00208                                                         // No need to try another parser; proceed with the next token in section
00209                                                         break;
00210                                                 } catch (ParseException &e)
00211                                                 {
00212                                                         // Try next parser
00213                                                 }
00214                                         }
00215                                 }
00216                         }
00217                 }
00218                 
00219                 return record;
00220         }
00221 
00222         void
00223         AmplOutput::dump(std::ostream& o, const Algebra &record) const
00224         {
00225                 std::map<std::string, const AlgebraData * const> records = record.getAllRecords();
00226                 for (std::map<std::string, const AlgebraData * const>::const_iterator rec = records.begin(); rec != records.end(); rec++)
00227                 {
00228                         dump(o, rec->second);
00229                 }
00230         }
00231 
00232         void
00233         AmplOutput::dump(std::ostream& o, const AlgebraData *data) const
00234         {
00235                 std::vector<AmplOutputDataOutput*>::const_iterator out;
00236                 for (out = outputs.begin(); out != outputs.end(); out++)
00237                 {
00238                         const AmplOutputDataOutput *output = *out;
00239                         try
00240                         {
00241                                 output->dump(o, data);
00242                                 break;
00243                         } catch(CastException &e)
00244                         {
00245                                 // No suitable element to output
00246                                 // Couldn't cast the element to record: just let that go and try again with next element
00247                         }
00248                 }
00249 
00250                 if(out == outputs.end())
00251                 {
00252                         vector<AmplOutputDataOutput*> string_outputs = stringOutputs();
00253                         for (out = string_outputs.begin(); out != string_outputs.end(); out++)
00254                         {
00255                                 const AmplOutputDataOutput *output = *out;
00256                                 try
00257                                 {
00258                                         output->dump(o, data);
00259                                         break;
00260                                 } catch(CastException &e)
00261                                 {
00262                                         // No suitable element to output
00263                                         // Couldn't cast the element to record: just let that go and try again with next element
00264                                 }
00265                         }
00266 
00267                         if(out == string_outputs.end())
00268                         {
00269                                 throw PelibException("Could not find a suitable output format for data record of name \"" + string(data->getName()) + "\".");
00270                         }
00271                 }
00272         }
00273 
00274         void
00275         AmplOutput::dump(std::ostream& o, const AlgebraData &data) const
00276         {
00277                 dump(o, &data);
00278         }
00279 
00280         std::vector<AmplOutputDataParser*> AmplOutput::floatParsers()
00281         {
00282                 std::vector<AmplOutputDataParser*> parsers;
00283                 
00284                 parsers.push_back(new AmplOutputScalar<float>(false));
00285                 parsers.push_back(new AmplOutputVector<int, float>(false));
00286                 parsers.push_back(new AmplOutputSet<float>(false));
00287                 parsers.push_back(new AmplOutputMatrix<int, int, float>(false));
00288 
00289                 return parsers;
00290         }
00291                 
00292         std::vector<AmplOutputDataOutput*> AmplOutput::floatOutputs()
00293         {
00294                 std::vector<AmplOutputDataOutput*> outputs;
00295 
00296                 outputs.push_back(new AmplOutputScalar<float>(false));
00297                 outputs.push_back(new AmplOutputVector<int, float>(false));
00298                 outputs.push_back(new AmplOutputSet<float>(false));
00299                 outputs.push_back(new AmplOutputMatrix<int, int, float>(false));
00300 
00301                 return outputs;
00302         }
00303 
00304         std::pair<std::vector<AmplOutputDataParser*>, std::vector<AmplOutputDataOutput*> > AmplOutput::floatHandlers()
00305         {
00306                 return std::pair<std::vector<AmplOutputDataParser*>, std::vector<AmplOutputDataOutput*> >(AmplOutput::floatParsers(), AmplOutput::floatOutputs());
00307         }
00308 
00309         std::vector<AmplOutputDataParser*> AmplOutput::stringParsers()
00310         {
00311                 std::vector<AmplOutputDataParser*> parsers;
00312                 
00313                 parsers.push_back(new AmplOutputScalar<string>(false));
00314                 parsers.push_back(new AmplOutputVector<int, string>(false));
00315                 parsers.push_back(new AmplOutputSet<string>(false));
00316                 parsers.push_back(new AmplOutputMatrix<int, int, string>(false));
00317 
00318                 return parsers;
00319         }
00320                 
00321         std::vector<AmplOutputDataOutput*> AmplOutput::stringOutputs()
00322         {
00323                 std::vector<AmplOutputDataOutput*> outputs;
00324 
00325                 outputs.push_back(new AmplOutputScalar<string>(false));
00326                 outputs.push_back(new AmplOutputVector<int, string>(false));
00327                 outputs.push_back(new AmplOutputSet<string>(false));
00328                 outputs.push_back(new AmplOutputMatrix<int, int, string>(false));
00329 
00330                 return outputs;
00331         }
00332 
00333         std::pair<std::vector<AmplOutputDataParser*>, std::vector<AmplOutputDataOutput*> > AmplOutput::stringHandlers()
00334         {
00335                 return std::pair<std::vector<AmplOutputDataParser*>, std::vector<AmplOutputDataOutput*> >(AmplOutput::stringParsers(), AmplOutput::stringOutputs());
00336         }
00337 
00338         std::vector<AmplOutputDataParser*> AmplOutput::intFloatParsers()
00339         {
00340                 std::vector<AmplOutputDataParser*> parsers;
00341                 parsers.push_back(new AmplOutputScalar<int>());
00342                 parsers.push_back(new AmplOutputScalar<float>());
00343                 parsers.push_back(new AmplOutputVector<int, int>(true));
00344                 parsers.push_back(new AmplOutputVector<int, float>(true));
00345                 parsers.push_back(new AmplOutputSet<int>(true));
00346                 parsers.push_back(new AmplOutputSet<float>(true));
00347                 parsers.push_back(new AmplOutputMatrix<int, int, int>(true));
00348                 parsers.push_back(new AmplOutputMatrix<int, int, float>(true));
00349 
00350                 return parsers;
00351         }
00352                 
00353         std::vector<AmplOutputDataOutput*> AmplOutput::intFloatOutputs()
00354         {
00355                 std::vector<AmplOutputDataOutput*> outputs;
00356 
00357                 outputs.push_back(new AmplOutputScalar<int>());
00358                 outputs.push_back(new AmplOutputScalar<float>());
00359                 outputs.push_back(new AmplOutputVector<int, int>(true));
00360                 outputs.push_back(new AmplOutputVector<int, float>(true));
00361                 outputs.push_back(new AmplOutputSet<int>(true));
00362                 outputs.push_back(new AmplOutputSet<float>(true));
00363                 outputs.push_back(new AmplOutputMatrix<int, int, int>(true));
00364                 outputs.push_back(new AmplOutputMatrix<int, int, float>(true));
00365 
00366                 return outputs;
00367         }
00368 
00369         std::pair<std::vector<AmplOutputDataParser*>, std::vector<AmplOutputDataOutput*> > AmplOutput::intFloatHandlers()
00370         {
00371                 return std::pair<std::vector<AmplOutputDataParser*>, std::vector<AmplOutputDataOutput*> >(AmplOutput::intFloatParsers(), AmplOutput::intFloatOutputs());
00372         }
00373 
00374         /*
00375         // Protected
00376         void
00377         AmplOutput::addParsers()
00378         {               
00379                 parsers.push_back(new AmplOutputScalar<int>());
00380                 parsers.push_back(new AmplOutputScalar<float>());
00381                 parsers.push_back(new AmplOutputVector<int, int>());
00382                 parsers.push_back(new AmplOutputVector<int, float>());
00383                 parsers.push_back(new AmplOutputSet<int>());
00384                 parsers.push_back(new AmplOutputSet<float>());
00385                 parsers.push_back(new AmplOutputMatrix<int, int, int>());
00386                 parsers.push_back(new AmplOutputMatrix<int, int, float>());
00387         }
00388 
00389         void                    
00390         AmplOutput::addOutputs()
00391         {               
00392                 outputs.push_back(new AmplOutputScalar<int>());
00393                 outputs.push_back(new AmplOutputScalar<float>());
00394                 outputs.push_back(new AmplOutputVector<int, int>());
00395                 outputs.push_back(new AmplOutputVector<int, float>());
00396                 outputs.push_back(new AmplOutputSet<int>());
00397                 outputs.push_back(new AmplOutputSet<float>());
00398                 outputs.push_back(new AmplOutputMatrix<int, int, int>());
00399                 outputs.push_back(new AmplOutputMatrix<int, int, float>());
00400         }
00401         */
00402 }