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

Generated by: LCOV version 1.16