pelib  2.0.0
src/pelib-convert.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 <vector>
00024 #include <map>
00025 
00026 #include <pelib/Record.hpp>
00027 
00028 #include <pelib/argument_parsing.hpp>
00029 #include <pelib/dl.h>
00030 
00031 #ifdef debug
00032 #undef debug
00033 #endif
00034 
00035 #define debug(expr) cerr << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #expr << " = \"" << expr << "\"." << endl;
00036 
00037 using namespace std;
00038 using namespace pelib;
00039 
00040 struct conversion
00041 {
00042         vector<pelib_argument_stream_t> inputs;
00043         vector<pelib_argument_stream_t> process;
00044         vector<pelib_argument_stream_t> outputs;
00045 };
00046 typedef struct conversion conversion_t;
00047 
00048 static conversion_t
00049 parse_args(char** argv)
00050 {
00051         conversion_t conversion;
00052         string self(argv[0]);
00053         //conversion.process.library = NULL;
00054 
00055         for(argv++; *argv != NULL; argv++)
00056         {
00057                 if(string(*argv).compare("--input") == 0)
00058                 {
00059                         pelib_argument_stream_t input;
00060                         pelib_argument_stream_init(&input);
00061                         argv++;
00062                         size_t num = pelib_argument_stream_parse(argv, &input);
00063                         argv = argv + num - 1;
00064                         conversion.inputs.push_back(input);
00065                         continue;
00066                 }
00067 
00068                 if(string(*argv).compare("--process") == 0)
00069                 {
00070                         pelib_argument_stream_t process;
00071                         pelib_argument_stream_init(&process);
00072                         argv++;
00073                         size_t num = pelib_argument_stream_parse(argv, &process);
00074                         argv = argv + num - 1;
00075                         conversion.process.push_back(process);
00076                         continue;
00077                 }
00078 
00079                 if(string(*argv).compare("--output") == 0)
00080                 {
00081                         pelib_argument_stream_t output;
00082                         pelib_argument_stream_init(&output);
00083                         argv++;
00084                         size_t num = pelib_argument_stream_parse(argv, &output);
00085                         argv = argv + num - 1;
00086                         conversion.outputs.push_back(output);
00087                         continue;
00088                 }
00089 
00090                 if(string(*argv).compare("--sources") == 0)
00091                 {
00092                         string cmd = string("ls $(dirname $(realpath $(which ").append(self).append(")))/../share/pelib/pelib-*.tar.gz | sort -rV | head -1 | xargs realpath");
00093                         exit(system(cmd.c_str()));
00094                 }
00095 
00096                 if(string(*argv).compare("--seed") == 0)
00097                 {
00098                         argv++;
00099                         size_t seed;
00100                         if(string(*argv).compare("--random") == 0)
00101                         {
00102                                 seed = (size_t)time(NULL);
00103                         }
00104                         else
00105                         {
00106                                 stringstream str(argv[0]);
00107                                 str >> seed;
00108                         }
00109                         srand(seed);
00110                 }
00111 
00112         }
00113 
00114         return conversion;
00115 }
00116 
00117 int
00118 main(int argc, char **argv)
00119 {
00120         vector<void*> process;
00121         map<const char*, Record*> inputs;
00122         map<const char*, void (*)(Record*)> freelist;
00123         map<const char*, void*> parserList;
00124 
00125         conversion_t conversion = parse_args(argv);
00126 
00127         size_t counter = 1;
00128         for(vector<pelib_argument_stream_t>::const_iterator i = conversion.inputs.begin(); i != conversion.inputs.end(); i++, counter++)
00129         {
00130                 /* Load functions from shared libraries */
00131                 void *libParser;
00132                 if(i->library != NULL)
00133                 {
00134                         libParser = load_lib(i->library);
00135                 }
00136                 else
00137                 {
00138                         cerr << "[WARNING] No parser library specified for input #" << counter << ". Skipping." << endl;
00139                         continue;
00140                 }
00141 
00142                 /* Link function handles to function pointers */
00143                 Record* (*parse)(istream&, size_t, char**) = (Record* (*)(istream&, size_t, char**))load_function(libParser, "pelib_parse");
00144                 void (*del)(Record*) = (void (*)(Record*))load_function(libParser, "pelib_delete");
00145 
00146                 switch(i->stream)
00147                 {
00148                         case STREAM_STDIN:
00149                                 {
00150                                         Record* rec = parse(cin, i->argc, i->argv);
00151                                         if(rec != NULL)
00152                                         {
00153                                                 if(i->name != NULL)
00154                                                 {
00155                                                         inputs.insert(pair<const char*, Record*>(i->name, rec));
00156                                                         freelist.insert(pair<const char*, void (*)(Record*)>(i->name, del));
00157                                                         parserList.insert(pair<const char*, void*>(pair<const char*, void*>(i->name, libParser)));
00158                                                 }
00159                                                 else
00160                                                 {
00161                                                         inputs.insert(pair<const char*, Record*>(typeid(*rec).name(), rec));
00162                                                         freelist.insert(pair<const char*, void (*)(Record*)>(typeid(*rec).name(), del));
00163                                                         parserList.insert(pair<const char*, void*>(pair<const char*, void*>(typeid(*rec).name(), libParser)));
00164                                                 }
00165                                         }
00166                                         else
00167                                         {
00168                                                 cerr << "[WARNING] Parser \"" << i->library << "\" failed to parse input on stdin for input #" << counter << ". Skipping." << endl;
00169                                         }
00170                                 }
00171                         break;
00172                         case STREAM_STDOUT:
00173                         case STREAM_STDERR:
00174                                 cerr << "[WARNING] Cannot read data from an output stream for input #" << counter << ". Skipping." << endl;
00175                         break;
00176                         case STREAM_FILE:
00177                                 {
00178                                         ifstream myfile(i->filename);
00179                                         Record *rec = parse(myfile, i->argc, i->argv);
00180                                         
00181                                         if(rec != NULL)
00182                                         {
00183                                                 if(i->name != NULL)
00184                                                 {
00185                                                         inputs.insert(pair<const char*, Record*>(i->name, rec));
00186                                                         freelist.insert(pair<const char*, void (*)(Record*)>(i->name, del));
00187                                                 }
00188                                                 else
00189                                                 {
00190                                                         inputs.insert(pair<const char*, Record*>(typeid(*rec).name(), rec));
00191                                                         freelist.insert(pair<const char*, void (*)(Record*)>(typeid(*rec).name(), del));
00192                                                 }
00193                                                 myfile.close();
00194                                         }
00195                                         else
00196                                         {
00197                                                 cerr << "[WARNING] Parser \"" << i->library << "\" failed to parse input on stdin for input #" << counter << ". Skipping." << endl;
00198                                         }
00199                                 }
00200                         break;
00201                         case STREAM_NOTHING:
00202                         default:
00203                                 cerr << "[WARNING] No input stream specified for input #" << counter << ". Skipping." << endl;
00204                         break;
00205                 }
00206 
00207                 // Don't destroy the libparser yet, as we need to destroy data elements parsed
00208                 // Don't destroy the pelib_argument_stream descriptor yet as we still need input names
00209         }
00210 
00211         for(vector<pelib_argument_stream_t>::const_iterator i = conversion.process.begin(); i != conversion.process.end(); i++)
00212         {
00213                 void *libProcess = load_lib(i->library);
00214                 process.push_back(libProcess);
00215 
00216                 /* Link function handles to function pointers */
00217                 std::map<const char*, Record*> (*process)(std::map<const char*, Record*> records, size_t, char**) = (std::map<const char*, Record*> (*)(std::map<const char*, Record*> records, size_t, char**))load_function(libProcess, "pelib_process");
00218                 std::map<const char*, Record*> transform = process(inputs, i->argc, i->argv);
00219 
00220                 // Free data structure parsed
00221                 for(map<const char*, void (*)(Record*)>::iterator i = freelist.begin(); i != freelist.end(); i++)
00222                 {
00223                         void (*del)(Record*) = i->second;
00224                         del(inputs.find(i->first)->second);
00225                 }
00226 
00227                 // Replace inputs with transformation outcome
00228                 inputs = transform;
00229 
00230                 // Replace function pointers
00231                 freelist.clear();
00232                 void (*del)(Record*) = (void (*)(Record*))load_function(libProcess, "pelib_delete");
00233                 for(map<const char*, Record*>::iterator i = inputs.begin(); i != inputs.end(); i++)
00234                 {
00235                         freelist.insert(pair<const char*, void (*)(Record*)>(i->first, del));
00236                 }
00237         }
00238 
00239         counter = 1;
00240         for(vector<pelib_argument_stream_t>::const_iterator i = conversion.outputs.begin(); i != conversion.outputs.end() && inputs.size() > 0; i++, counter++)
00241         {
00242                 /* Load functions from shared libraries */
00243                 void *libOutput;
00244                 if(i->library != NULL)
00245                 {
00246                         libOutput = load_lib(i->library);
00247                 }
00248                 else
00249                 {
00250                         cerr << "[WARNING] No output library specified for output #" << counter << ". Skipping." << endl;
00251                         continue;
00252                 }
00253 
00254                 /* Link function handles to function pointers */
00255                 void (*dump)(ostream&, std::map<const char*, Record*> records, size_t, char**) = (void (*)(ostream&, std::map<const char*, Record*> records, size_t, char**))load_function(libOutput, "pelib_dump");
00256 
00257                 switch(i->stream)
00258                 {
00259                         case STREAM_STDIN:
00260                                 cerr << "[WARNING] Cannot dump data to an input stream for output #" << counter << ". Skipping." << endl;
00261                         case STREAM_STDOUT:
00262                                 dump(cout, inputs, i->argc, i->argv);
00263                         break;
00264                         case STREAM_STDERR:
00265                                 dump(cerr, inputs, i->argc, i->argv);
00266                         break;
00267                         case STREAM_FILE:
00268                                 {
00269                                         ofstream myfile(i->filename, ios::out | ios::trunc | ios::binary);
00270                                         dump(myfile, inputs, i->argc, i->argv);
00271                                         myfile.close();
00272                                 }
00273                         break;
00274                         case STREAM_NOTHING:
00275                         default:
00276                                 cerr << "[WARNING] No output stream specified for output #" << counter << ". Skipping." << endl;
00277                         break;
00278                 }
00279 
00280                 // Destroy dynamic libraries
00281                 destroy_lib(libOutput);
00282 
00283                 // Destroy the stream descriptor
00284                 pelib_argument_stream_destroy(*i);
00285         }
00286 
00287         // Destroy input structures
00288         for(map<const char*, Record*>::iterator i = inputs.begin(); i != inputs.end(); i++)
00289         {
00290                 void (*del)(Record*) = freelist.find(i->first)->second;
00291                 del(i->second);
00292         }
00293 
00294         // Destroy input library handlers
00295         for(map<const char*, void*>::iterator i = parserList.begin(); i != parserList.end(); i++)
00296         {
00297                 destroy_lib(i->second);
00298         }
00299 
00300         // Delete processing dynamic library
00301         for(vector<void*>::const_iterator i = process.begin(); i != process.end(); i++)
00302         {
00303                 destroy_lib(*i);
00304         }
00305 
00306         // Destroy input arguments
00307         for(vector<pelib_argument_stream_t>::const_iterator i = conversion.inputs.begin(); i != conversion.inputs.end(); i++)
00308         {
00309                 pelib_argument_stream_destroy(*i);
00310         }
00311 }
00312