OPeNDAP Hyrax Back End Server (BES)
Updated for version 3.8.3
|
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