bes  Updated for version 3.20.6
BESTokenizer.cc
1 // BESTokenizer.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include <cstring>
34 #include <iostream>
35 
36 using std::cout;
37 using std::endl;
38 using std::ostream;
39 using std::string;
40 
41 #include "BESTokenizer.h"
42 #include "BESSyntaxUserError.h"
43 
44 BESTokenizer::BESTokenizer() :
45  _counter(-1), _number_tokens(0)
46 {
47 }
48 
49 BESTokenizer::~BESTokenizer()
50 {
51 }
52 
65 void BESTokenizer::parse_error(const string &s)
66 {
67  string error = "Parse error.";
68  string where = "";
69  if (_counter >= 0) {
70  for (int w = 0; w < _counter + 1; w++)
71  where += tokens[w] + " ";
72  where += "<----HERE IS THE ERROR";
73  error += "\n" + where;
74  }
75  if (s != "") error += "\n" + s;
76  throw BESSyntaxUserError(error, __FILE__, __LINE__);
77 }
78 
87 string &
89 {
90  _counter = 0;
91  return tokens[_counter];
92 }
93 
103 string &
105 {
106  if (_counter < 0 || _counter > (int)_number_tokens - 1) {
107  parse_error("incomplete expression!");
108  }
109 
110  return tokens[_counter];
111 }
112 
122 string &
124 {
125  if (_counter == -1) {
126  parse_error("incomplete expression!");
127  }
128 
129  if (_counter >= (int) (_number_tokens - 1)) {
130  parse_error("incomplete expression!");
131  }
132 
133  return tokens[++_counter];
134 }
135 
162 void BESTokenizer::tokenize(const char *p)
163 {
164  size_t len = strlen(p);
165  string s = "";
166  bool passing_raw = false;
167  bool escaped = false;
168 
169  for (unsigned int j = 0; j < len; j++) {
170 
171  if (!escaped && p[j] == '\"') {
172 
173  if (s != "") {
174  if (passing_raw) {
175  s += "\"";
176  tokens.push_back(s);
177  s = "";
178  }
179  else {
180  tokens.push_back(s);
181  s = "\"";
182  }
183  }
184  else {
185  s += "\"";
186  }
187  passing_raw = !passing_raw;
188 
189  }
190  else if (passing_raw) {
191 
192  if (!escaped && p[j] == '\\') {
193  escaped = true;
194  }
195  else {
196  s += p[j];
197 
198  if (escaped) escaped = false;
199  }
200 
201  }
202  else {
203  if ((p[j] == ' ') || (p[j] == '\n') || (p[j] == 0x0D) || (p[j] == 0x0A)) {
204  if (s != "") {
205  tokens.push_back(s);
206  s = "";
207  }
208  }
209  else if ((p[j] == ',') || (p[j] == ';')) {
210  if (s != "") {
211  tokens.push_back(s);
212  s = "";
213  }
214  switch (p[j]) {
215  case ',':
216  tokens.push_back(",");
217  break;
218  case ';':
219  tokens.push_back(";");
220  break;
221  }
222  }
223  else
224  s += p[j];
225  }
226  }
227 
228  if (s != "") tokens.push_back(s);
229  _number_tokens = tokens.size();
230  if (passing_raw) parse_error("Unclose quote found.(\")");
231  if (_number_tokens < 1) parse_error("Unknown command: '" + (string) p + (string) "'");
232  if (tokens[_number_tokens - 1] != ";") parse_error("The request must be terminated by a semicolon (;)");
233 }
234 
255 string BESTokenizer::parse_container_name(const string &s, unsigned int &type)
256 {
257  string::size_type where = s.rfind(".constraint=", s.size());
258  if (where == string::npos) {
259  where = s.rfind(".attributes=", s.size());
260  if (where == string::npos) {
261  parse_error("Expected property declaration.");
262  }
263  else {
264  type = 2;
265  }
266  }
267  else {
268  type = 1;
269  }
270  string valid = s.substr(where, s.size());
271  if ((valid != ".constraint=") && (valid != ".attributes=")) {
272  string err = (string) "Invalid container property " + valid + " for container " + s.substr(0, where)
273  + ". constraint expressions and attribute lists " + "must be wrapped in quotes";
274  parse_error(err);
275  }
276  return s.substr(0, where);
277 }
278 
290 string BESTokenizer::remove_quotes(const string &s)
291 {
292  if ((s[0] != '"') || (s[s.size() - 1] != '"')) {
293  parse_error("item " + s + " must be enclosed by quotes");
294  }
295  return s.substr(1, s.size() - 2);
296 }
297 
307 {
308  tokens_citerator i = tokens.begin();
309  tokens_citerator ie = tokens.end();
310  for (; i != ie; i++) {
311  cout << "\"" << (*i) << "\"" << endl;
312  }
313 }
314 
321 void BESTokenizer::dump(ostream &strm) const
322 {
323  strm << BESIndent::LMarg << "BESTokenizer::dump - (" << (void *) this << ")" << endl;
324  BESIndent::Indent();
325  tokens_citerator i = tokens.begin();
326  tokens_citerator ie = tokens.end();
327  for (; i != ie; i++) {
328  strm << BESIndent::LMarg << "\"" << (*i) << "\"" << endl;
329  }
330  BESIndent::UnIndent();
331 }
332 
BESTokenizer::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESTokenizer.cc:321
BESTokenizer::parse_container_name
std::string parse_container_name(const std::string &s, unsigned int &type)
parses a container name for constraint and attributes
Definition: BESTokenizer.cc:255
BESTokenizer::tokenize
void tokenize(const char *p)
tokenize the BES request/command string
Definition: BESTokenizer.cc:162
BESTokenizer::dump_tokens
void dump_tokens()
dump the tokens that have been tokenized in the order in which they are parsed.
Definition: BESTokenizer.cc:306
BESSyntaxUserError
error thrown if there is a user syntax error in the request or any other user error
Definition: BESSyntaxUserError.h:41
BESTokenizer::get_next_token
std::string & get_next_token()
returns the next token from the token list
Definition: BESTokenizer.cc:123
BESTokenizer::get_current_token
std::string & get_current_token()
returns the current token from the token list
Definition: BESTokenizer.cc:104
BESTokenizer::get_first_token
std::string & get_first_token()
returns the first token from the token list
Definition: BESTokenizer.cc:88
BESTokenizer::parse_error
void parse_error(const std::string &s="")
throws an exception giving the tokens up to the point of the problem
Definition: BESTokenizer.cc:65
BESTokenizer::remove_quotes
std::string remove_quotes(const std::string &s)
removes quotes from a quoted token
Definition: BESTokenizer.cc:290