bes  Updated for version 3.20.5
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 
39 #include "BESTokenizer.h"
40 #include "BESSyntaxUserError.h"
41 
42 BESTokenizer::BESTokenizer() :
43  _counter(-1), _number_tokens(0)
44 {
45 }
46 
47 BESTokenizer::~BESTokenizer()
48 {
49 }
50 
63 void BESTokenizer::parse_error(const string &s)
64 {
65  string error = "Parse error.";
66  string where = "";
67  if (_counter >= 0) {
68  for (int w = 0; w < _counter + 1; w++)
69  where += tokens[w] + " ";
70  where += "<----HERE IS THE ERROR";
71  error += "\n" + where;
72  }
73  if (s != "") error += "\n" + s;
74  throw BESSyntaxUserError(error, __FILE__, __LINE__);
75 }
76 
85 string &
87 {
88  _counter = 0;
89  return tokens[_counter];
90 }
91 
101 string &
103 {
104  if (_counter < 0 || _counter > (int)_number_tokens - 1) {
105  parse_error("incomplete expression!");
106  }
107 
108  return tokens[_counter];
109 }
110 
120 string &
122 {
123  if (_counter == -1) {
124  parse_error("incomplete expression!");
125  }
126 
127  if (_counter >= (int) (_number_tokens - 1)) {
128  parse_error("incomplete expression!");
129  }
130 
131  return tokens[++_counter];
132 }
133 
160 void BESTokenizer::tokenize(const char *p)
161 {
162  size_t len = strlen(p);
163  string s = "";
164  bool passing_raw = false;
165  bool escaped = false;
166 
167  for (unsigned int j = 0; j < len; j++) {
168 
169  if (!escaped && p[j] == '\"') {
170 
171  if (s != "") {
172  if (passing_raw) {
173  s += "\"";
174  tokens.push_back(s);
175  s = "";
176  }
177  else {
178  tokens.push_back(s);
179  s = "\"";
180  }
181  }
182  else {
183  s += "\"";
184  }
185  passing_raw = !passing_raw;
186 
187  }
188  else if (passing_raw) {
189 
190  if (!escaped && p[j] == '\\') {
191  escaped = true;
192  }
193  else {
194  s += p[j];
195 
196  if (escaped) escaped = false;
197  }
198 
199  }
200  else {
201  if ((p[j] == ' ') || (p[j] == '\n') || (p[j] == 0x0D) || (p[j] == 0x0A)) {
202  if (s != "") {
203  tokens.push_back(s);
204  s = "";
205  }
206  }
207  else if ((p[j] == ',') || (p[j] == ';')) {
208  if (s != "") {
209  tokens.push_back(s);
210  s = "";
211  }
212  switch (p[j]) {
213  case ',':
214  tokens.push_back(",");
215  break;
216  case ';':
217  tokens.push_back(";");
218  break;
219  }
220  }
221  else
222  s += p[j];
223  }
224  }
225 
226  if (s != "") tokens.push_back(s);
227  _number_tokens = tokens.size();
228  if (passing_raw) parse_error("Unclose quote found.(\")");
229  if (_number_tokens < 1) parse_error("Unknown command: '" + (string) p + (string) "'");
230  if (tokens[_number_tokens - 1] != ";") parse_error("The request must be terminated by a semicolon (;)");
231 }
232 
253 string BESTokenizer::parse_container_name(const string &s, unsigned int &type)
254 {
255  string::size_type where = s.rfind(".constraint=", s.size());
256  if (where == string::npos) {
257  where = s.rfind(".attributes=", s.size());
258  if (where == string::npos) {
259  parse_error("Expected property declaration.");
260  }
261  else {
262  type = 2;
263  }
264  }
265  else {
266  type = 1;
267  }
268  string valid = s.substr(where, s.size());
269  if ((valid != ".constraint=") && (valid != ".attributes=")) {
270  string err = (string) "Invalid container property " + valid + " for container " + s.substr(0, where)
271  + ". constraint expressions and attribute lists " + "must be wrapped in quotes";
272  parse_error(err);
273  }
274  return s.substr(0, where);
275 }
276 
288 string BESTokenizer::remove_quotes(const string &s)
289 {
290  if ((s[0] != '"') || (s[s.size() - 1] != '"')) {
291  parse_error("item " + s + " must be enclosed by quotes");
292  }
293  return s.substr(1, s.size() - 2);
294 }
295 
305 {
306  tokens_citerator i = tokens.begin();
307  tokens_citerator ie = tokens.end();
308  for (; i != ie; i++) {
309  cout << "\"" << (*i) << "\"" << endl;
310  }
311 }
312 
319 void BESTokenizer::dump(ostream &strm) const
320 {
321  strm << BESIndent::LMarg << "BESTokenizer::dump - (" << (void *) this << ")" << endl;
322  BESIndent::Indent();
323  tokens_citerator i = tokens.begin();
324  tokens_citerator ie = tokens.end();
325  for (; i != ie; i++) {
326  strm << BESIndent::LMarg << "\"" << (*i) << "\"" << endl;
327  }
328  BESIndent::UnIndent();
329 }
330 
string & get_next_token()
returns the next token from the token list
error thrown if there is a user syntax error in the request or any other user error
string & get_first_token()
returns the first token from the token list
Definition: BESTokenizer.cc:86
string remove_quotes(const string &s)
removes quotes from a quoted token
virtual void dump(ostream &strm) const
dumps information about this object
string parse_container_name(const string &s, unsigned int &type)
parses a container name for constraint and attributes
void parse_error(const string &s="")
throws an exception giving the tokens up to the point of the problem
Definition: BESTokenizer.cc:63
void tokenize(const char *p)
tokenize the BES request/command string
string & get_current_token()
returns the current token from the token list
void dump_tokens()
dump the tokens that have been tokenized in the order in which they are parsed.