LCOV - code coverage report
Current view: top level - alma/ASDM - ASDMValuesParser.h (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 100 0.0 %
Date: 2024-10-29 13:38:20 Functions: 0 192 0.0 %

          Line data    Source code
       1             : #ifndef ASDMVALUESPARSER_H
       2             : #define ASDMVALUESPARSER_H
       3             : /*
       4             :  * ALMA - Atacama Large Millimeter Array
       5             :  * (c) European Southern Observatory, 2002
       6             :  * (c) Associated Universities Inc., 2002
       7             :  * Copyright by ESO (in the framework of the ALMA collaboration),
       8             :  * Copyright by AUI (in the framework of the ALMA collaboration),
       9             :  * All rights reserved.
      10             :  * 
      11             :  * This library is free software; you can redistribute it and/or
      12             :  * modify it under the terms of the GNU Lesser General Public
      13             :  * License as published by the Free software Foundation; either
      14             :  * version 2.1 of the License, or (at your option) any later version.
      15             :  * 
      16             :  * This library is distributed in the hope that it will be useful,
      17             :  * but WITHOUT ANY WARRANTY, without even the implied warranty of
      18             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      19             :  * Lesser General Public License for more details.
      20             :  * 
      21             :  * You should have received a copy of the GNU Lesser General Public
      22             :  * License along with this library; if not, write to the Free Software
      23             :  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      24             :  * MA 02111-1307  USA
      25             :  *
      26             :  * File ASDMValuesParser.h
      27             :  */
      28             : #include <iostream>
      29             : #include <vector>
      30             : #include <sstream>
      31             : 
      32             : #ifndef WITHOUT_BOOST
      33             : // regex not currently used here, in commented out code
      34             : //#include <boost/regex.hpp>
      35             : #include <boost/algorithm/string/trim.hpp>
      36             : #include <boost/tokenizer.hpp>
      37             : #else
      38             : //#include <regex>
      39             : #include <alma/ASDM/Misc.h>
      40             : #endif
      41             : 
      42             : 
      43             : namespace asdm {
      44             :   /**
      45             :    * A class to represent an exception thrown during the parsing of the representation 
      46             :    * of a basic type value , scalar or array, in the XML representation of an ASDM table.
      47             :    */ 
      48             :   class ASDMValuesParserException {
      49             :     
      50             :   public:
      51             :     /**
      52             :      * An empty contructor.
      53             :      */
      54             :     ASDMValuesParserException();
      55             : 
      56             :     /**
      57             :      * A constructor with a message associated with the exception.
      58             :      * @param m a string containing the message.
      59             :      */
      60             :     ASDMValuesParserException(const std::string& m);
      61             :     
      62             :     /**
      63             :      * The destructor.
      64             :      */
      65             :     virtual ~ASDMValuesParserException();
      66             :     
      67             :     /**
      68             :      * Returns the message associated to this exception.
      69             :      * @return a string.
      70             :      */
      71             :     std::string getMessage() const;
      72             :     
      73             :   protected:
      74             :     std::string message;
      75             :     
      76             :   };
      77             :   
      78             :   inline ASDMValuesParserException::ASDMValuesParserException() : message ("ASDMValuesParserException") {}
      79           0 :   inline ASDMValuesParserException::ASDMValuesParserException(const std::string& m) : message(m) {}
      80           0 :   inline ASDMValuesParserException::~ASDMValuesParserException() {}
      81             :   inline std::string ASDMValuesParserException::getMessage() const {
      82             :     return "ASDMValuesParserException : " + message;
      83             :   }
      84             :   
      85             :   class ASDMValuesParser {
      86             :   private:
      87             :     static std::istringstream iss;
      88             :     static std::ostringstream oss;
      89             : 
      90             :   public:
      91             :     template<class T> 
      92           0 :       static void READ(T& v) {
      93             :       char c;
      94           0 :       iss >> v; if (iss.fail() || (iss.get(c) && c != ' ')) {  
      95           0 :         oss.str("");                                          
      96           0 :         oss << "Error while reading the string to be parsed : '" << iss.str() << "'.";
      97           0 :         throw ASDMValuesParserException(oss.str());
      98             :       }
      99           0 :       iss.putback(c);
     100           0 :     }
     101             : 
     102             :     template<class T>
     103           0 :       static T parse(const std::string& s) {
     104           0 :       T result;
     105           0 :       iss.clear();
     106           0 :       iss.str(s);
     107           0 :       READ(result);
     108           0 :       return result;
     109           0 :     }
     110             : 
     111             :     template<class T>
     112           0 :       static std::vector<T> parse1D(const std::string& s) {
     113             :       int ndim;
     114             :       int nvalue;
     115             : 
     116           0 :       iss.clear();
     117           0 :       iss.str(s);
     118           0 :       READ(ndim);
     119           0 :       if (ndim != 1) {
     120           0 :         oss.str("");
     121           0 :         oss << "The first field of a 1D array representation should be '1', I found '" << ndim << "' in '" << s << "'.";
     122           0 :         throw ASDMValuesParserException(oss.str());
     123             :       }
     124             :       
     125           0 :       READ(nvalue);
     126           0 :       if (nvalue <= 0) {
     127           0 :         oss.str("");
     128           0 :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue << "'.";
     129           0 :         throw ASDMValuesParserException(oss.str());
     130             :       }
     131             : 
     132           0 :       std::vector<T> result(nvalue);
     133           0 :       T value;
     134           0 :       for ( int i = 0; i < nvalue; i++) {
     135           0 :         READ(value);
     136           0 :         result[i]=value;
     137             :       }
     138             :       
     139           0 :       return result;
     140           0 :     }
     141             : 
     142             :     template<class T>  
     143           0 :       static std::vector<std::vector<T> > parse2D(const std::string& s) {
     144             :       int ndim;
     145             :       int nvalue1;
     146             :       int nvalue2;
     147             : 
     148           0 :       iss.clear();
     149           0 :       iss.str(s);
     150           0 :       READ(ndim);
     151           0 :       if (ndim != 2) {
     152           0 :         oss.str("");
     153           0 :         oss << "The first field of a 2D array representation should be '2', I found '" << ndim << "' in '" << s << "'.";
     154           0 :         throw ASDMValuesParserException(oss.str());
     155             :       }
     156             :       
     157           0 :       READ(nvalue1);
     158           0 :       if (nvalue1 <= 0) {
     159           0 :         oss.str("");
     160           0 :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
     161           0 :         throw ASDMValuesParserException(oss.str());
     162             :       }
     163             : 
     164           0 :       READ(nvalue2);
     165           0 :       if (nvalue2 <= 0) {
     166           0 :         oss.str("");
     167           0 :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
     168           0 :         throw ASDMValuesParserException(oss.str());
     169             :       }
     170             : 
     171           0 :       std::vector<std::vector<T> > result(nvalue1);
     172           0 :       T value;
     173           0 :       for ( int i = 0; i < nvalue1; i++) {
     174           0 :         std::vector<T> v(nvalue2);
     175           0 :         for ( int j = 0; j < nvalue2; j++) {
     176           0 :           READ(value);
     177           0 :           v[j] = value;
     178             :         }
     179           0 :         result[i] = v;
     180             :       }
     181           0 :       return result;
     182           0 :     }
     183             :  
     184             :     template<class T>
     185           0 :       static std::vector<std::vector<std::vector<T> > > parse3D(const std::string& s) {
     186             :       int ndim;
     187             :       int nvalue1;
     188             :       int nvalue2;
     189             :       int nvalue3;
     190             : 
     191           0 :       iss.clear();
     192           0 :       iss.str(s);
     193             : 
     194           0 :       READ(ndim);
     195           0 :       if (ndim != 3) {
     196           0 :         oss.str("");
     197           0 :         oss << "The first field of a 3D array representation should be '3', I found '" << ndim << "' in '" << s << "'.";
     198           0 :         throw ASDMValuesParserException(oss.str());
     199             :       }
     200             :       
     201           0 :       READ(nvalue1);
     202           0 :       if (nvalue1 <= 0) {
     203           0 :         oss.str("");
     204           0 :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
     205           0 :         throw ASDMValuesParserException(oss.str());
     206             :       }
     207             : 
     208           0 :       READ(nvalue2);
     209           0 :       if (nvalue2 <= 0) {
     210           0 :         oss.str("");
     211           0 :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
     212           0 :         throw ASDMValuesParserException(oss.str());
     213             :       }
     214             : 
     215           0 :       READ(nvalue3);
     216           0 :       if (nvalue3 <= 0) {
     217           0 :         oss.str("");
     218           0 :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue3 << "'.";
     219           0 :         throw ASDMValuesParserException(oss.str());
     220             :       }
     221             : 
     222           0 :       std::vector<std::vector<std::vector<T> > > result(nvalue1);
     223           0 :       T value;
     224           0 :       for ( int i = 0; i < nvalue1; i++) {
     225           0 :         std::vector<std::vector<T> >vv(nvalue2);
     226           0 :         for ( int j = 0; j < nvalue2; j++) {
     227           0 :           std::vector<T> v(nvalue3);
     228           0 :           for ( int k = 0; k < nvalue3; k++) {
     229           0 :             READ(value);
     230           0 :             v[k] = value;
     231             :           }
     232           0 :           vv[j] = v;
     233             :         }
     234           0 :         result[i] = vv;
     235             :       }
     236           0 :       return result;
     237           0 :     }  
     238             : 
     239             :     template<class T>
     240             :       static std::vector<std::vector<std::vector<std::vector<T> > > > parse4D(const std::string& s) {
     241             :       int ndim;
     242             :       int nvalue1;
     243             :       int nvalue2;
     244             :       int nvalue3;
     245             :       int nvalue4;
     246             :       
     247             :       iss.clear();
     248             :       iss.str(s);
     249             :       READ(ndim);
     250             :       if (ndim != 4) {
     251             :         oss.str("");
     252             :         oss << "The first field of a 3D array representation should be '4', I found '" << ndim << "' in '" << s << "'.";
     253             :         throw ASDMValuesParserException(oss.str());
     254             :       }
     255             :       
     256             :       READ(nvalue1);
     257             :       if (nvalue1 <= 0) {
     258             :         oss.str("");
     259             :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
     260             :         throw ASDMValuesParserException(oss.str());
     261             :       }
     262             :       
     263             :       READ(nvalue2);
     264             :       if (nvalue2 <= 0) {
     265             :         oss.str("");
     266             :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
     267             :         throw ASDMValuesParserException(oss.str());
     268             :       }
     269             :       
     270             :       READ(nvalue3);
     271             :       if (nvalue3 <= 0) {
     272             :         oss.str("");
     273             :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue3 << "'.";
     274             :         throw ASDMValuesParserException(oss.str());
     275             :       }
     276             :       
     277             :       READ(nvalue4);
     278             :       if (nvalue4 <= 0) {
     279             :         oss.str("");
     280             :         oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue4 << "'.";
     281             :         throw ASDMValuesParserException(oss.str());
     282             :       }
     283             :       
     284             :       std::vector<std::vector<std::vector<std::vector<T> > > > result(nvalue1);
     285             :       T value;
     286             :       for ( int i = 0; i < nvalue1; i++) {
     287             :         std::vector<std::vector<std::vector<T> > > vvv(nvalue2);
     288             :         for ( int j = 0; j < nvalue2; j++) {
     289             :           std::vector<std::vector<T> > vv(nvalue3);
     290             :           for ( int k = 0; k < nvalue3; k++) {
     291             :             std::vector<T> v(nvalue4);
     292             :             for ( int l = 0; l < nvalue4; l++) {
     293             :               READ(value);
     294             :               v[l] = value;
     295             :             }
     296             :             vv[k] = v;
     297             :           }
     298             :           vvv[j] = vv;
     299             :         }
     300             :         result[i] = vvv;
     301             :       }  
     302             :       return result;
     303             :     }
     304             : 
     305             :     static std::string parse(const std::string& s);
     306             :     static std::vector<std::string> parse1D(const std::string& s);
     307             :     static std::vector<std::vector<std::string > > parse2D(const std::string& s);
     308             :     static std::vector<std::vector<std::vector<std::string > > > parse3D(const std::string& s);
     309             : 
     310             :     static std::vector<std::string> parseQuoted(const std::string& s);
     311             : 
     312             :   private:
     313             :     // this value is not currently used anywhere
     314             :     //#ifndef WITHOUT_BOOST
     315             :     //    static boost::regex quotedStringRegex;
     316             :     //#else
     317             :     //    static std::regex quotedStringRegex;
     318             :     //#endif
     319             : 
     320             :   };
     321             : 
     322             :   inline std::string ASDMValuesParser::parse(const  std::string& s) { return s; }
     323             :   inline std::vector<std::string> ASDMValuesParser::parse1D( const std::string& s) {
     324             :     int ndim;
     325             :     int nvalue;
     326             : 
     327             :     iss.clear();
     328             :     iss.str(s);
     329             :     READ(ndim);
     330             :     if (ndim != 1) {
     331             :       oss.str("");
     332             :       oss << "The first field of a 1D array representation should be '1', I found '" << ndim << "' in '" << s << "'.";
     333             :       throw ASDMValuesParserException(oss.str());
     334             :     }
     335             : 
     336             :     READ(nvalue);
     337             :     if (nvalue <= 0) {
     338             :       oss.str("");
     339             :       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue << "'.";
     340             :       throw ASDMValuesParserException(oss.str());
     341             :     }
     342             :      
     343             :     std::string remains; getline(iss,remains); 
     344             : #ifndef WITHOUT_BOOST
     345             :     std::vector<std::string> result = parseQuoted(boost::trim_left_copy(remains));
     346             : #else
     347             :     std::vector<std::string> result = parseQuoted(asdm::ltrim_copy(remains));
     348             : #endif
     349             :     if (nvalue > (int) result.size()) {
     350             :       oss.str("");
     351             :       oss << "Error while reading the string to be parsed : '" << iss.str() << "'.";
     352             :       throw ASDMValuesParserException(oss.str());
     353             :     }
     354             :     return result;
     355             :   }
     356             : 
     357             :   inline std::vector<std::vector<std::string > > ASDMValuesParser::parse2D(const std::string& s) {
     358             :     int ndim;
     359             :     int nvalue1;
     360             :     int nvalue2;
     361             : 
     362             :     iss.clear();
     363             :     iss.str(s);
     364             :     READ(ndim);
     365             :     if (ndim != 2) {
     366             :       oss.str("");
     367             :       oss << "The first field of a 2D array representation should be '2', I found '" << ndim << "' in '" << s << "'.";
     368             :       throw ASDMValuesParserException(oss.str());
     369             :     }
     370             :       
     371             :     READ(nvalue1);
     372             :     if (nvalue1 <= 0) {
     373             :       oss.str("");
     374             :       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
     375             :       throw ASDMValuesParserException(oss.str());
     376             :     }
     377             : 
     378             :     READ(nvalue2);
     379             :     if (nvalue2 <= 0) {
     380             :       oss.str("");
     381             :       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
     382             :       throw ASDMValuesParserException(oss.str());
     383             :     }
     384             : 
     385             :     std::string remains; getline(iss,remains); 
     386             : #ifndef WITHOUT_BOOST
     387             :     std::vector<std::string> v_s = parseQuoted(boost::trim_left_copy(remains));
     388             : #else
     389             :     std::vector<std::string> v_s = parseQuoted(asdm::ltrim_copy(remains));
     390             : #endif
     391             :     if (nvalue1 * nvalue2 > (int) v_s.size()) {
     392             :       oss.str("");
     393             :       oss << "Error while reading the string to be parsed : '" << iss.str() << "'.";
     394             :       throw ASDMValuesParserException(oss.str());
     395             :     }
     396             :       
     397             :     std::vector<std::vector<std::string> > result(nvalue1);
     398             :     int start = 0;
     399             :     for (unsigned int i = 0; i < result.size(); i++) {
     400             :       start = i*nvalue2;
     401             :       result[i].assign(v_s.begin()+start, v_s.begin()+start+nvalue2);
     402             :     }
     403             :     return result;
     404             :   }
     405             : 
     406             :   inline std::vector<std::vector<std::vector<std::string > > > ASDMValuesParser::parse3D(const std::string& s) {
     407             :     int ndim;
     408             :     int nvalue1;
     409             :     int nvalue2;
     410             :     int nvalue3;
     411             : 
     412             :     iss.clear();
     413             :     iss.str(s);
     414             :     READ(ndim);
     415             :     if (ndim != 3) {
     416             :       oss.str("");
     417             :       oss << "The first field of a 2D array representation should be '2', I found '" << ndim << "' in '" << s << "'.";
     418             :       throw ASDMValuesParserException(oss.str());
     419             :     }
     420             :       
     421             :     READ(nvalue1);
     422             :     if (nvalue1 <= 0) {
     423             :       oss.str("");
     424             :       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue1 << "'.";
     425             :       throw ASDMValuesParserException(oss.str());
     426             :     }
     427             : 
     428             :     READ(nvalue2);
     429             :     if (nvalue2 <= 0) {
     430             :       oss.str("");
     431             :       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue2 << "'.";
     432             :       throw ASDMValuesParserException(oss.str());
     433             :     }
     434             : 
     435             :     READ(nvalue3);
     436             :     if (nvalue3 <= 0) {
     437             :       oss.str("");
     438             :       oss << "The number of values along one dimension of an array must be expressed by a strictly positive integer.I found '" << nvalue3 << "'.";
     439             :       throw ASDMValuesParserException(oss.str());
     440             :     }
     441             : 
     442             :     std::string remains; getline(iss,remains); 
     443             : #ifndef WITHOUT_BOOST
     444             :     std::vector<std::string> v_s = parseQuoted(boost::trim_left_copy(remains));
     445             : #else
     446             :     std::vector<std::string> v_s = parseQuoted(asdm::ltrim_copy(remains));
     447             : #endif
     448             :     if (nvalue1 * nvalue2 * nvalue3 > (int) v_s.size()) {
     449             :       oss.str("");
     450             :       oss << "Error while reading the string to be parsed : '" << iss.str() << "'.";
     451             :       throw ASDMValuesParserException(oss.str());
     452             :     }
     453             :       
     454             :     std::vector<std::vector<std::string> > plane(nvalue2);
     455             :     std::vector<std::vector<std::vector<std::string> > > result(nvalue1, plane);
     456             :     int start = 0;
     457             :     for (unsigned int i = 0; i < (unsigned int) nvalue1; i++) {
     458             :       for (unsigned int j = 0; j < (unsigned int) nvalue2; j++) {
     459             :         result[i][j].assign(v_s.begin()+start, v_s.begin()+start+nvalue3);
     460             :         start += nvalue3; 
     461             :       }
     462             :     }
     463             :     return result;
     464             :   }
     465             :   
     466             :   inline std::vector<std::string> ASDMValuesParser::parseQuoted(const std::string& s) {
     467             : #ifndef WITHOUT_BOOST
     468             :     std::string separator1("\\");// let quoted arguments escape themselves
     469             :     std::string separator2(" "); // split on spaces
     470             :     std::string separator3("\"");// let it have quoted arguments
     471             :     
     472             :     boost::escaped_list_separator<char> els(separator1,separator2,separator3);
     473             :     boost::tokenizer<boost::escaped_list_separator<char> > tok(s, els);
     474             :     std::vector<std::string> result(tok.begin(), tok.end());
     475             : #else
     476             :     // there is no c++ equivalent to the boost tokenizer, parse the start by character
     477             :     std::vector<std::string> result;
     478             : 
     479             :     // an empty string has no tokens
     480             :     if (s.empty()) {
     481             :       return result;
     482             :     }
     483             : 
     484             :     std::string token;
     485             :     std::string nullString;
     486             : 
     487             :     bool quoted, escaped;
     488             :     quoted = escaped = false;
     489             : 
     490             :     for (std::string::const_iterator it=s.begin(); it!=s.end(); ++it) {
     491             :       if (escaped) {
     492             :         token += *it;
     493             :         escaped = false;
     494             :       } else {
     495             :         if (*it=='\\') {
     496             :           escaped = true;
     497             :         } else {
     498             :           if (quoted) {
     499             :             if (*it=='\"') {
     500             :               quoted = false;
     501             :             } else {
     502             :               token += *it;
     503             :             }
     504             :           } else {
     505             :             if (*it == ' ') {
     506             :               result.push_back(token);
     507             :               token = nullString;
     508             :             } else {
     509             :               if (*it=='\"') {
     510             :                 quoted = true;
     511             :               } else {
     512             :                 token += *it;
     513             :               }
     514             :             }
     515             :           }
     516             :         }
     517             :       }
     518             :     }
     519             :     result.push_back(token);
     520             : #endif
     521             :     return result;
     522             :   }  
     523             : } // End namespace asdm.
     524             :     
     525             : #endif

Generated by: LCOV version 1.16