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 : } 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 : } 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 : } 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 : } 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