libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
Keywords2.cc
Go to the documentation of this file.
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2011 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
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 OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24#include "config.h"
25
26#include <iostream>
27#include <vector>
28
29// #define DODS_DEBUG
30
31#include "Error.h"
32#include "Keywords2.h"
33#include "debug.h"
34#include "escaping.h"
35
36using namespace std;
37
38namespace libdap {
39
41 // Load known keywords and their allowed values
42 vector<string> v1(7);
43 v1[0] = "2";
44 v1[1] = "2.0";
45 v1[2] = "3.2";
46 v1[3] = "3.3";
47 v1[4] = "3.4";
48 v1[5] = "4";
49 v1[6] = "4.0";
50 value_set_t vs = value_set_t(v1.begin(), v1.end());
51 d_known_keywords["dap"] = vs;
52
53 vector<string> v2(4);
54 v2[0] = "md5";
55 v2[1] = "MD5";
56 v2[2] = "sha1";
57 v2[3] = "SHA1";
58 value_set_t vs2 = value_set_t(v2.begin(), v2.end());
59 d_known_keywords["checksum"] = vs2;
60}
61
63
71static bool f_parse_keyword(const string &kw, string &word, string &value) {
72 word = "";
73 value = "";
74 string::size_type i = kw.find('(');
75 if (i == string::npos)
76 return false;
77 word = kw.substr(0, i);
78 string::size_type j = kw.find(')');
79 if (j == string::npos)
80 return false;
81 ++i; // Move past the opening paren
82 value = kw.substr(i, j - i);
83
84 return (!word.empty() && !value.empty());
85}
86
93void Keywords::m_add_keyword(const keyword &word, const keyword_value &value) { d_parsed_keywords[word] = value; }
94
102bool Keywords::m_is_valid_keyword(const keyword &word, const keyword_value &value) const {
103 map<keyword, value_set_t>::const_iterator ci = d_known_keywords.find(word);
104 if (ci == d_known_keywords.end())
105 return false;
106 else {
107 value_set_t vs = ci->second;
108
109 if (vs.find(value) == vs.end())
110 throw Error("Bad value passed to the keyword/function: " + word);
111 }
112
113 return true;
114}
115
121bool Keywords::is_known_keyword(const string &word) const { return d_known_keywords.count(word) == 1; }
122
128list<Keywords::keyword> Keywords::get_keywords() const {
129 list<keyword> kws;
130 map<keyword, keyword_value>::const_iterator i;
131 for (i = d_parsed_keywords.begin(); i != d_parsed_keywords.end(); ++i)
132 kws.push_front((*i).first);
133
134 return kws;
135}
136
143bool Keywords::has_keyword(const keyword &kw) const { return d_parsed_keywords.count(kw) == 1; }
144
151 if (d_known_keywords.find(kw) == d_known_keywords.end())
152 throw Error("Keyword not known (" + kw + ")");
153
154 return d_parsed_keywords.find(kw)->second;
155}
156
162string Keywords::parse_keywords(const string &ce) {
163 // Get the whole CE
164 string projection = www2id(ce, "%", "%20");
165 string selection = "";
166
167 // Separate the selection part (which follows/includes the first '&')
168 string::size_type amp = projection.find('&');
169 if (amp != string::npos) {
170 selection = projection.substr(amp);
171 projection = projection.substr(0, amp);
172 }
173
174 // Extract keywords; add to the Keywords keywords. For this, scan for
175 // a known set of keywords and assume that anything else is part of the
176 // projection and should be left alone. Keywords must come before variables
177 // The 'projection' string will look like: '' or 'dap4.0' or 'dap4.0,u,v'
178 while (!projection.empty()) {
179 string::size_type i = projection.find(',');
180 string next_word = projection.substr(0, i);
181 string word, value;
182 if (f_parse_keyword(next_word, word, value) && m_is_valid_keyword(word, value)) {
183 m_add_keyword(word, value);
184 if (i != string::npos)
185 projection = projection.substr(i + 1);
186 else
187 projection = "";
188 } else {
189 break; // exit on first non-keyword
190 }
191 }
192
193 // The CE is whatever is left after removing the keywords
194 return projection + selection;
195}
196
197} // namespace libdap
A class for error processing.
Definition Error.h:92
virtual keyword_value get_keyword_value(const keyword &kw) const
Definition Keywords2.cc:150
virtual list< keyword > get_keywords() const
Definition Keywords2.cc:128
set< keyword_value > value_set_t
Definition Keywords2.h:57
virtual ~Keywords()
Definition Keywords2.cc:62
virtual bool has_keyword(const keyword &kw) const
Definition Keywords2.cc:143
virtual bool is_known_keyword(const string &s) const
Definition Keywords2.cc:121
string keyword_value
Definition Keywords2.h:56
virtual string parse_keywords(const string &ce)
Definition Keywords2.cc:162
top level DAP object to house generic methods
Definition AISConnect.cc:30
string www2id(const string &in, const string &escape, const string &except)
Definition escaping.cc:202