casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ASDMValuesParser.h
Go to the documentation of this file.
00001 #ifndef ASDMVALUESPARSER_H
00002 #define ASDMVALUESPARSER_H
00003 /*
00004  * ALMA - Atacama Large Millimeter Array
00005  * (c) European Southern Observatory, 2002
00006  * (c) Associated Universities Inc., 2002
00007  * Copyright by ESO (in the framework of the ALMA collaboration),
00008  * Copyright by AUI (in the framework of the ALMA collaboration),
00009  * All rights reserved.
00010  * 
00011  * This library is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU Lesser General Public
00013  * License as published by the Free software Foundation; either
00014  * version 2.1 of the License, or (at your option) any later version.
00015  * 
00016  * This library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY, without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  * 
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with this library; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00024  * MA 02111-1307  USA
00025  *
00026  * File ASDMValuesParser.h
00027  */
00028 #include <iostream>
00029 #include <vector>
00030 #include <sstream>
00031 #include <boost/regex.hpp>
00032 #include <boost/tokenizer.hpp>
00033 #include <boost/algorithm/string/trim.hpp>
00034 
00035 namespace asdm {
00040   class ASDMValuesParserException {
00041     
00042   public:
00046     ASDMValuesParserException();
00047 
00052     ASDMValuesParserException(const std::string& m);
00053     
00057     virtual ~ASDMValuesParserException();
00058     
00063     std::string getMessage() const;
00064     
00065   protected:
00066     std::string message;
00067     
00068   };
00069   
00070   inline ASDMValuesParserException::ASDMValuesParserException() : message ("ASDMValuesParserException") {}
00071   inline ASDMValuesParserException::ASDMValuesParserException(const std::string& m) : message(m) {}
00072   inline ASDMValuesParserException::~ASDMValuesParserException() {}
00073   inline std::string ASDMValuesParserException::getMessage() const {
00074     return "ASDMValuesParserException : " + message;
00075   }
00076   
00077   class ASDMValuesParser {
00078   private:
00079     static std::istringstream iss;
00080     static std::ostringstream oss;
00081 
00082   public:
00083     template<class T> 
00084       static void READ(T& v) {
00085       char c;
00086       iss >> v; if (iss.fail() || (iss.get(c) && c != ' ')) {  
00087         oss.str("");                                            
00088         oss << "Error while reading the string to be parsed : '" << iss.str() << "'.";
00089         throw ASDMValuesParserException(oss.str());
00090       }
00091       iss.putback(c);
00092     }
00093 
00094     template<class T>
00095       static T parse(const std::string& s) {
00096       T result;
00097       iss.clear();
00098       iss.str(s);
00099       //char c;
00100       READ(result);
00101       //if ( c == ' ' ) iss.putback(c);list.tcc
00102       return result;
00103     }
00104 
00105     template<class T>
00106       static std::vector<T> parse1D(const std::string& s) {
00107       int ndim;
00108       int nvalue;
00109 
00110       iss.clear();
00111       iss.str(s);
00112       READ(ndim);
00113       if (ndim != 1) {
00114         oss.str("");
00115         oss << "The first field of a 1D array representation should be '1', I found '" << ndim << "' in '" << s << "'.";
00116         throw ASDMValuesParserException(oss.str());
00117       }
00118       
00119       READ(nvalue);
00120       if (nvalue <= 0) {
00121         oss.str("");
00122         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue << "'.";
00123         throw ASDMValuesParserException(oss.str());
00124       }
00125 
00126       std::vector<T> result(nvalue);
00127       T value;
00128       for ( int i = 0; i < nvalue; i++) {
00129         READ(value);
00130         result[i]=value;
00131       }
00132       
00133       return result;
00134     }
00135 
00136     template<class T>  
00137       static std::vector<std::vector<T> > parse2D(const std::string& s) {
00138       int ndim;
00139       int nvalue1;
00140       int nvalue2;
00141 
00142       iss.clear();
00143       iss.str(s);
00144       READ(ndim);
00145       if (ndim != 2) {
00146         oss.str("");
00147         oss << "The first field of a 2D array representation should be '2', I found '" << ndim << "' in '" << s << "'.";
00148         throw ASDMValuesParserException(oss.str());
00149       }
00150       
00151       READ(nvalue1);
00152       if (nvalue1 <= 0) {
00153         oss.str("");
00154         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
00155         throw ASDMValuesParserException(oss.str());
00156       }
00157 
00158       READ(nvalue2);
00159       if (nvalue2 <= 0) {
00160         oss.str("");
00161         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
00162         throw ASDMValuesParserException(oss.str());
00163       }
00164 
00165       std::vector<std::vector<T> > result(nvalue1);
00166       T value;
00167       for ( int i = 0; i < nvalue1; i++) {
00168         std::vector<T> v(nvalue2);
00169         for ( int j = 0; j < nvalue2; j++) {
00170           READ(value);
00171           v[j] = value;
00172         }
00173         result[i] = v;
00174       }
00175       return result;
00176     }
00177  
00178     template<class T>
00179       static std::vector<std::vector<std::vector<T> > > parse3D(const std::string& s) {
00180       int ndim;
00181       int nvalue1;
00182       int nvalue2;
00183       int nvalue3;
00184 
00185       iss.clear();
00186       iss.str(s);
00187 
00188       READ(ndim);
00189       if (ndim != 3) {
00190         oss.str("");
00191         oss << "The first field of a 3D array representation should be '3', I found '" << ndim << "' in '" << s << "'.";
00192         throw ASDMValuesParserException(oss.str());
00193       }
00194       
00195       READ(nvalue1);
00196       if (nvalue1 <= 0) {
00197         oss.str("");
00198         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
00199         throw ASDMValuesParserException(oss.str());
00200       }
00201 
00202       READ(nvalue2);
00203       if (nvalue2 <= 0) {
00204         oss.str("");
00205         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
00206         throw ASDMValuesParserException(oss.str());
00207       }
00208 
00209       READ(nvalue3);
00210       if (nvalue3 <= 0) {
00211         oss.str("");
00212         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue3 << "'.";
00213         throw ASDMValuesParserException(oss.str());
00214       }
00215 
00216       std::vector<std::vector<std::vector<T> > > result(nvalue1);
00217       T value;
00218       for ( int i = 0; i < nvalue1; i++) {
00219         std::vector<std::vector<T> >vv(nvalue2);
00220         for ( int j = 0; j < nvalue2; j++) {
00221           std::vector<T> v(nvalue3);
00222           for ( int k = 0; k < nvalue3; k++) {
00223             READ(value);
00224             v[k] = value;
00225           }
00226           vv[j] = v;
00227         }
00228         result[i] = vv;
00229       }
00230       return result;
00231     }  
00232 
00233     template<class T>
00234       static std::vector<std::vector<std::vector<std::vector<T> > > > parse4D(const std::string& s) {
00235       int ndim;
00236       int nvalue1;
00237       int nvalue2;
00238       int nvalue3;
00239       int nvalue4;
00240       
00241       iss.clear();
00242       iss.str(s);
00243       READ(ndim);
00244       if (ndim != 4) {
00245         oss.str("");
00246         oss << "The first field of a 3D array representation should be '4', I found '" << ndim << "' in '" << s << "'.";
00247         throw ASDMValuesParserException(oss.str());
00248       }
00249       
00250       READ(nvalue1);
00251       if (nvalue1 <= 0) {
00252         oss.str("");
00253         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
00254         throw ASDMValuesParserException(oss.str());
00255       }
00256       
00257       READ(nvalue2);
00258       if (nvalue2 <= 0) {
00259         oss.str("");
00260         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
00261         throw ASDMValuesParserException(oss.str());
00262       }
00263       
00264       READ(nvalue3);
00265       if (nvalue3 <= 0) {
00266         oss.str("");
00267         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue3 << "'.";
00268         throw ASDMValuesParserException(oss.str());
00269       }
00270       
00271       READ(nvalue4);
00272       if (nvalue4 <= 0) {
00273         oss.str("");
00274         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue4 << "'.";
00275         throw ASDMValuesParserException(oss.str());
00276       }
00277       
00278       std::vector<std::vector<std::vector<std::vector<T> > > > result(nvalue1);
00279       T value;
00280       for ( int i = 0; i < nvalue1; i++) {
00281         std::vector<std::vector<std::vector<T> > > vvv(nvalue2);
00282         for ( int j = 0; j < nvalue2; j++) {
00283           std::vector<std::vector<T> > vv(nvalue3);
00284           for ( int k = 0; k < nvalue3; k++) {
00285             std::vector<T> v(nvalue4);
00286             for ( int l = 0; l < nvalue4; l++) {
00287               READ(value);
00288               v[l] = value;
00289             }
00290             vv[k] = v;
00291           }
00292           vvv[j] = vv;
00293         }
00294         result[i] = vvv;
00295       }  
00296       return result;
00297     }
00298 
00299     static std::string parse(const std::string& s);
00300     static std::vector<std::string> parse1D(const std::string& s);
00301     static std::vector<std::vector<std::string > > parse2D(const std::string& s);
00302     static std::vector<std::vector<std::vector<std::string > > > parse3D(const std::string& s);
00303 
00304     static std::vector<std::string> parseQuoted(const std::string& s);
00305 
00306   private:
00307     static boost::regex quotedStringRegex;
00308 
00309   };
00310 
00311   inline std::string ASDMValuesParser::parse(const  std::string& s) { return s; }
00312   inline std::vector<std::string> ASDMValuesParser::parse1D( const std::string& s) {
00313     int ndim;
00314     int nvalue;
00315 
00316     iss.clear();
00317     iss.str(s);
00318     READ(ndim);
00319     if (ndim != 1) {
00320       oss.str("");
00321       oss << "The first field of a 1D array representation should be '1', I found '" << ndim << "' in '" << s << "'.";
00322       throw ASDMValuesParserException(oss.str());
00323     }
00324 
00325     READ(nvalue);
00326     if (nvalue <= 0) {
00327       oss.str("");
00328       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue << "'.";
00329       throw ASDMValuesParserException(oss.str());
00330     }
00331      
00332     string remains; getline(iss,remains); 
00333     std::vector<std::string> result = parseQuoted(boost::trim_left_copy(remains));
00334     if (nvalue > (int) result.size()) {
00335       oss.str("");
00336       oss << "Error while reading the string to be parsed : '" << iss.str() << "'.";
00337       throw ASDMValuesParserException(oss.str());
00338     }
00339     return result;
00340   }
00341 
00342   inline std::vector<std::vector<std::string > > ASDMValuesParser::parse2D(const std::string& s) {
00343     int ndim;
00344     int nvalue1;
00345     int nvalue2;
00346 
00347     iss.clear();
00348     iss.str(s);
00349     READ(ndim);
00350     if (ndim != 2) {
00351       oss.str("");
00352       oss << "The first field of a 2D array representation should be '2', I found '" << ndim << "' in '" << s << "'.";
00353       throw ASDMValuesParserException(oss.str());
00354     }
00355       
00356     READ(nvalue1);
00357     if (nvalue1 <= 0) {
00358       oss.str("");
00359       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
00360       throw ASDMValuesParserException(oss.str());
00361     }
00362 
00363     READ(nvalue2);
00364     if (nvalue2 <= 0) {
00365       oss.str("");
00366       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
00367       throw ASDMValuesParserException(oss.str());
00368     }
00369 
00370     string remains; getline(iss,remains); 
00371     std::vector<std::string> v_s = parseQuoted(boost::trim_left_copy(remains));
00372     if (nvalue1 * nvalue2 > (int) v_s.size()) {
00373       oss.str("");
00374       oss << "Error while reading the string to be parsed : '" << iss.str() << "'.";
00375       throw ASDMValuesParserException(oss.str());
00376     }
00377       
00378     std::vector<std::vector<std::string> > result(nvalue1);
00379     int start = 0;
00380     for (unsigned int i = 0; i < result.size(); i++) {
00381       start = i*nvalue2;
00382       result[i].assign(v_s.begin()+start, v_s.begin()+start+nvalue2);
00383     }
00384     return result;
00385   }
00386 
00387   inline std::vector<std::vector<std::vector<std::string > > > ASDMValuesParser::parse3D(const std::string& s) {
00388     int ndim;
00389     int nvalue1;
00390     int nvalue2;
00391     int nvalue3;
00392 
00393     iss.clear();
00394     iss.str(s);
00395     READ(ndim);
00396     if (ndim != 3) {
00397       oss.str("");
00398       oss << "The first field of a 2D array representation should be '2', I found '" << ndim << "' in '" << s << "'.";
00399       throw ASDMValuesParserException(oss.str());
00400     }
00401       
00402     READ(nvalue1);
00403     if (nvalue1 <= 0) {
00404       oss.str("");
00405       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
00406       throw ASDMValuesParserException(oss.str());
00407     }
00408 
00409     READ(nvalue2);
00410     if (nvalue2 <= 0) {
00411       oss.str("");
00412       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
00413       throw ASDMValuesParserException(oss.str());
00414     }
00415 
00416     READ(nvalue3);
00417     if (nvalue3 <= 0) {
00418       oss.str("");
00419       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue3 << "'.";
00420       throw ASDMValuesParserException(oss.str());
00421     }
00422 
00423     string remains; getline(iss,remains); 
00424     std::vector<std::string> v_s = parseQuoted(boost::trim_left_copy(remains));
00425     if (nvalue1 * nvalue2 * nvalue3 > (int) v_s.size()) {
00426       oss.str("");
00427       oss << "Error while reading the string to be parsed : '" << iss.str() << "'.";
00428       throw ASDMValuesParserException(oss.str());
00429     }
00430       
00431     std::vector<std::vector<std::string> > plane(nvalue2);
00432     std::vector<std::vector<std::vector<std::string> > > result(nvalue1, plane);
00433     int start = 0;
00434     for (unsigned int i = 0; i < (unsigned int) nvalue1; i++) {
00435       for (unsigned int j = 0; j < (unsigned int) nvalue2; j++) {
00436         result[i][j].assign(v_s.begin()+start, v_s.begin()+start+nvalue3);
00437         start += nvalue3; 
00438       }
00439     }
00440     return result;
00441   }
00442   
00443   inline std::vector<std::string> ASDMValuesParser::parseQuoted(const std::string& s) {
00444     string separator1("\\");// let quoted arguments escape themselves
00445     string separator2(" "); // split on spaces
00446     string separator3("\"");// let it have quoted arguments
00447     
00448     boost::escaped_list_separator<char> els(separator1,separator2,separator3);
00449     boost::tokenizer<boost::escaped_list_separator<char> > tok(s, els);
00450     std::vector<std::string> result(tok.begin(), tok.end());
00451     return result;
00452   }  
00453 } // End namespace asdm.
00454     
00455 #endif