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