BESTokenizer.cc

Go to the documentation of this file.
00001 // BESTokenizer.cc
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025 
00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      pwest       Patrick West <pwest@ucar.edu>
00031 //      jgarcia     Jose Garcia <jgarcia@ucar.edu>
00032 
00033 #include <cstring>
00034 #include <iostream>
00035 
00036 using std::cout ;
00037 using std::endl ;
00038 
00039 #include "BESTokenizer.h"
00040 #include "BESSyntaxUserError.h"
00041 
00042 BESTokenizer::BESTokenizer( )
00043 : _counter( -1 ) {}
00044 
00045 BESTokenizer::~BESTokenizer() {}
00046 
00059 void
00060 BESTokenizer::parse_error( const string &s ) {
00061     string error = "Parse error." ;
00062     string where = "" ;
00063     if( _counter >= 0 ) {
00064         for( int w = 0; w < _counter+1; w++ )
00065             where += tokens[w] + " " ;
00066         where += "<----HERE IS THE ERROR" ;
00067         error += "\n" + where ;
00068     }
00069     if( s != "" )
00070         error += "\n" + s ;
00071     throw BESSyntaxUserError( error, __FILE__, __LINE__ ) ;
00072 }
00073 
00082 string &
00083 BESTokenizer::get_first_token() {
00084     _counter = 0 ;
00085     return tokens[_counter] ;
00086 }
00087 
00097 string &
00098 BESTokenizer::get_current_token() {
00099     if( _counter == -1 ) {
00100         parse_error( "incomplete expression!" ) ;
00101     }
00102 
00103     if( _counter > _number_tokens-1 ) {
00104         parse_error( "incomplete expression!" ) ;
00105     }
00106 
00107     return tokens[_counter] ;
00108 }
00109 
00119 string &
00120 BESTokenizer::get_next_token() {
00121     if( _counter == -1 ) {
00122         parse_error( "incomplete expression!" ) ;
00123     }
00124 
00125     if( _counter >= _number_tokens-1 ) {
00126         parse_error( "incomplete expression!" ) ;
00127     }
00128 
00129     return tokens[++_counter] ;
00130 }
00131 
00158 void
00159 BESTokenizer::tokenize( const char *p ) {
00160     size_t len = strlen( p ) ;
00161     string s = "" ;
00162     bool passing_raw = false ;
00163     bool escaped = false ;
00164     
00165 
00166     
00167     for( unsigned int j = 0; j < len; j++ ) {
00168         
00169         
00170         if( !escaped && p[j] == '\"') {
00171 
00172             if( s != "" ) {
00173                 if( passing_raw ) {
00174                     s += "\"" ;
00175                     tokens.push_back( s ) ;
00176                     s = "" ;
00177                 } else {
00178                     tokens.push_back( s ) ;
00179                     s = "\"" ;
00180                 }
00181             } else {
00182                 s += "\"" ;
00183             }
00184             passing_raw =! passing_raw ;
00185             
00186         } else if( passing_raw ) {
00187              
00188                 if(!escaped && p[j] == '\\' ){
00189                     escaped = true;
00190                 } else {          
00191                 s += p[j] ;
00192                                
00193                 if(escaped)
00194                     escaped = false;     
00195                 }  
00196            
00197         } else {
00198             if( ( p[j] == ' ' ) ||
00199                     ( p[j] == '\n' ) ||
00200                     ( p[j] == 0x0D ) ||
00201                     ( p[j] == 0x0A ) ) {
00202                 if( s != "" ) {
00203                     tokens.push_back( s ) ;
00204                     s = "" ;
00205                 }
00206             } else if( ( p[j] == ',' ) || ( p[j] == ';' ) ) {
00207                 if( s!= "" ) {
00208                     tokens.push_back( s ) ;
00209                     s = "" ;
00210                 }
00211                 switch( p[j] ) {
00212                 case ',':
00213                     tokens.push_back( "," ) ;
00214                     break;
00215                 case ';':
00216                     tokens.push_back( ";" ) ;
00217                     break;
00218                 }
00219             } else
00220                 s += p[j] ;
00221         }
00222     }
00223 
00224 
00225     if( s != "" )
00226         tokens.push_back( s ) ;
00227     _number_tokens = tokens.size() ;
00228     if( passing_raw )
00229         parse_error( "Unclose quote found.(\")" ) ;
00230     if( _number_tokens < 1 )
00231         parse_error( "Unknown command: '" + (string)p + (string)"'") ;
00232     if( tokens[_number_tokens - 1] != ";" )
00233         parse_error( "The request must be terminated by a semicolon (;)" ) ;
00234 }
00235 
00256 string
00257 BESTokenizer::parse_container_name( const string &s, unsigned int &type ) {
00258     string::size_type where = s.rfind( ".constraint=", s.size() ) ;
00259     if( where == string::npos ) {
00260         where = s.rfind( ".attributes=", s.size() ) ;
00261         if( where == string::npos ) {
00262             parse_error( "Expected property declaration." ) ;
00263         } else {
00264             type = 2 ;
00265         }
00266     } else {
00267         type = 1 ;
00268     }
00269     string valid = s.substr( where, s.size() ) ;
00270     if( (valid != ".constraint=") && (valid != ".attributes=") ) {
00271         string err = (string)"Invalid container property "
00272                      + valid
00273                      + " for container "
00274                      + s.substr( 0, where )
00275                      + ". constraint expressions and attribute lists "
00276                      + "must be wrapped in quotes"  ;
00277         parse_error( err ) ;
00278     }
00279     return s.substr( 0, where ) ;
00280 }
00281 
00293 string
00294 BESTokenizer::remove_quotes( const string &s ) {
00295     if( (s[0] != '"' ) || (s[s.size() - 1] != '"' ) ) {
00296         parse_error( "item " + s + " must be enclosed by quotes" ) ;
00297     }
00298     return s.substr( 1, s.size() - 2 ) ;
00299 }
00300 
00309 void
00310 BESTokenizer::dump_tokens() {
00311     tokens_citerator i = tokens.begin() ;
00312     tokens_citerator ie = tokens.end() ;
00313     for( ; i != ie; i++ ) {
00314         cout << "\"" << (*i) << "\"" << endl ;
00315     }
00316 }
00317 
00324 void
00325 BESTokenizer::dump( ostream &strm ) const {
00326     strm << BESIndent::LMarg << "BESTokenizer::dump - ("
00327     << (void *)this << ")" << endl ;
00328     BESIndent::Indent() ;
00329     tokens_citerator i = tokens.begin() ;
00330     tokens_citerator ie = tokens.end() ;
00331     for( ; i != ie; i++ ) {
00332     strm << BESIndent::LMarg << "\"" << (*i) << "\"" << endl ;
00333     }
00334     BESIndent::UnIndent() ;
00335 }
00336 

Generated on Tue May 11 20:02:06 2010 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.4.7