libdap
Updated for version 3.17.0
|
00001 // -*- mode: c++; c-basic-offset:4 -*- 00002 00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00004 // Access Protocol. 00005 00006 // Copyright (c) 2002,2003 OPeNDAP, Inc. 00007 // Author: James Gallagher <jgallagher@opendap.org> 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 // 00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00024 00025 #include <string> 00026 #include <sstream> 00027 #include <iterator> 00028 00029 //#define DODS_DEBUG 00030 00031 #include "D4CEScanner.h" 00032 #include "D4ConstraintEvaluator.h" 00033 #include "d4_ce_parser.tab.hh" 00034 #include "DMR.h" 00035 #include "D4Group.h" 00036 #include "D4Dimensions.h" 00037 #include "BaseType.h" 00038 #include "Array.h" 00039 #include "Constructor.h" 00040 00041 #include "parser.h" // for get_ull() 00042 #include "debug.h" 00043 00044 namespace libdap { 00045 00046 bool D4ConstraintEvaluator::parse(const std::string &expr) 00047 { 00048 d_expr = expr; // set for error messages. See the %initial-action section of .yy 00049 00050 std::istringstream iss(expr); 00051 D4CEScanner scanner(iss); 00052 D4CEParser parser(scanner, *this /* driver */); 00053 00054 if (trace_parsing()) { 00055 parser.set_debug_level(1); 00056 parser.set_debug_stream(std::cerr); 00057 } 00058 00059 return parser.parse() == 0; 00060 } 00061 00062 #if 0 00063 void 00064 D4ConstraintEvaluator::set_array_slices(const std::string &id, Array *a) 00065 { 00066 // Test that the indexes and dimensions match in number 00067 if (d_indexes.size() != a->dimensions()) 00068 throw Error(malformed_expr, "The index constraint for '" + id + "' does not match its rank."); 00069 00070 Array::Dim_iter d = a->dim_begin(); 00071 for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) { 00072 if ((*i).stride > (unsigned long long)a->dimension_stop(d, false)) 00073 throw Error(malformed_expr, "For '" + id + "', the index stride value is greater than the number of elements in the Array"); 00074 if (!(*i).rest && ((*i).stop) > (unsigned long long)a->dimension_stop(d, false)) 00075 throw Error(malformed_expr, "For '" + id + "', the index stop value is greater than the number of elements in the Array"); 00076 00077 D4Dimension *dim = a->dimension_D4dim(d); 00078 00079 // In a DAP4 CE, specifying '[]' as an array dimension slice has two meanings. 00080 // It can mean 'all the elements' of the dimension or 'apply the slicing inherited 00081 // from the shared dimension'. The latter might be provide 'all the elements' 00082 // but regardless, the Array object must record the CE correctly. 00083 00084 if (dim && (*i).empty) { 00085 a->add_constraint(d, dim); 00086 } 00087 else { 00088 a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop); 00089 } 00090 00091 ++d; 00092 } 00093 00094 d_indexes.clear(); 00095 } 00096 #endif 00097 00098 void 00099 D4ConstraintEvaluator::throw_not_found(const string &id, const string &ident) 00100 { 00101 throw Error(no_such_variable, d_expr + ": The variable " + id + " was not found in the dataset (" + ident + ")."); 00102 } 00103 00104 void 00105 D4ConstraintEvaluator::throw_not_array(const string &id, const string &ident) 00106 { 00107 throw Error(no_such_variable, d_expr + ": The variable '" + id + "' is not an Array variable (" + ident + ")."); 00108 } 00109 00110 void 00111 D4ConstraintEvaluator::search_for_and_mark_arrays(BaseType *btp) 00112 { 00113 DBG(cerr << "Entering D4ConstraintEvaluator::search_for_and_mark_arrays...(" << btp->name() << ")" << endl); 00114 00115 assert(btp->is_constructor_type()); 00116 00117 Constructor *ctor = static_cast<Constructor*>(btp); 00118 for (Constructor::Vars_iter i = ctor->var_begin(), e = ctor->var_end(); i != e; ++i) { 00119 switch ((*i)->type()) { 00120 case dods_array_c: 00121 DBG(cerr << "Found an array: " << (*i)->name() << endl); 00122 mark_array_variable(*i); 00123 break; 00124 case dods_structure_c: 00125 case dods_sequence_c: 00126 DBG(cerr << "Found a ctor: " << (*i)->name() << endl); 00127 search_for_and_mark_arrays(*i); 00128 break; 00129 default: 00130 break; 00131 } 00132 } 00133 } 00134 00144 BaseType * 00145 D4ConstraintEvaluator::mark_variable(BaseType *btp) 00146 { 00147 assert(btp); 00148 00149 DBG(cerr << "In D4ConstraintEvaluator::mark_variable... (" << btp->name() << "; " << btp->type_name() << ")" << endl); 00150 00151 btp->set_send_p(true); 00152 00153 if (btp->type() == dods_array_c ) { 00154 mark_array_variable(btp); 00155 } 00156 00157 // Test for Constructors and marks arrays they contain 00158 if (btp->is_constructor_type()) { 00159 search_for_and_mark_arrays(btp); 00160 } 00161 else if (btp->type() == dods_array_c && btp->var() && btp->var()->is_constructor_type()) { 00162 search_for_and_mark_arrays(btp->var()); 00163 } 00164 00165 // Now set the parent variables 00166 BaseType *parent = btp->get_parent(); 00167 while (parent) { 00168 parent->BaseType::set_send_p(true); // Just set the parent using BaseType's impl. 00169 parent = parent->get_parent(); 00170 } 00171 00172 return btp; 00173 } 00174 00187 BaseType * 00188 D4ConstraintEvaluator::mark_array_variable(BaseType *btp) 00189 { 00190 assert(btp->type() == dods_array_c); 00191 00192 Array *a = static_cast<Array*>(btp); 00193 00194 // If an array appears in a CE without the slicing operators ([]) we still have to 00195 // call set_user_by_projected_var(true) for all of it's sdims for them to appear in 00196 // the CDMR. 00197 if (d_indexes.empty()) { 00198 for (Array::Dim_iter d = a->dim_begin(), de = a->dim_end(); d != de; ++d) { 00199 D4Dimension *dim = a->dimension_D4dim(d); 00200 if (dim) { 00201 a->add_constraint(d, dim); 00202 } 00203 } 00204 } 00205 else { 00206 // Test that the indexes and dimensions match in number 00207 if (d_indexes.size() != a->dimensions()) 00208 throw Error(malformed_expr, "The index constraint for '" + btp->name() + "' does not match its rank."); 00209 00210 Array::Dim_iter d = a->dim_begin(); 00211 for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) { 00212 if ((*i).stride > (unsigned long long) (a->dimension_stop(d, false) - a->dimension_start(d, false)) + 1) 00213 throw Error(malformed_expr, "For '" + btp->name() + "', the index stride value is greater than the number of elements in the Array"); 00214 if (!(*i).rest && ((*i).stop) > (unsigned long long) (a->dimension_stop(d, false) - a->dimension_start(d, false)) + 1) 00215 throw Error(malformed_expr, "For '" + btp->name() + "', the index stop value is greater than the number of elements in the Array"); 00216 00217 D4Dimension *dim = a->dimension_D4dim(d); 00218 00219 // In a DAP4 CE, specifying '[]' as an array dimension slice has two meanings. 00220 // It can mean 'all the elements' of the dimension or 'apply the slicing inherited 00221 // from the shared dimension'. The latter might be provide 'all the elements' 00222 // but regardless, the Array object must record the CE correctly. 00223 00224 if (dim && (*i).empty) { 00225 a->add_constraint(d, dim); // calls set_used_by_projected_var(true) + more 00226 } 00227 else { 00228 a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop); 00229 } 00230 00231 ++d; 00232 } 00233 00234 d_indexes.clear(); 00235 } 00236 00237 return btp; 00238 } 00239 00247 D4Dimension * 00248 D4ConstraintEvaluator::slice_dimension(const std::string &id, const index &i) 00249 { 00250 D4Dimension *dim = dmr()->root()->find_dim(id); 00251 00252 if (i.stride > dim->size()) 00253 throw Error(malformed_expr, "For '" + id + "', the index stride value is greater than the size of the dimension"); 00254 if (!i.rest && (i.stop > dim->size() - 1)) 00255 throw Error(malformed_expr, "For '" + id + "', the index stop value is greater than the size of the dimension"); 00256 00257 dim->set_constraint(i.start, i.stride, i.rest ? dim->size() - 1: i.stop); 00258 00259 return dim; 00260 } 00261 00262 D4ConstraintEvaluator::index 00263 D4ConstraintEvaluator::make_index(const std::string &i) 00264 { 00265 unsigned long long v = get_ull(i.c_str()); 00266 return index(v, 1, v, false, false /*empty*/); 00267 } 00268 00269 D4ConstraintEvaluator::index 00270 D4ConstraintEvaluator::make_index(const std::string &i, const std::string &s, const std::string &e) 00271 { 00272 return index(get_ull(i.c_str()), get_ull(s.c_str()), get_ull(e.c_str()), false, false /*empty*/); 00273 } 00274 00275 D4ConstraintEvaluator::index 00276 D4ConstraintEvaluator::make_index(const std::string &i, unsigned long long s, const std::string &e) 00277 { 00278 return index(get_ull(i.c_str()), s, get_ull(e.c_str()), false, false /*empty*/); 00279 } 00280 00281 D4ConstraintEvaluator::index 00282 D4ConstraintEvaluator::make_index(const std::string &i, const std::string &s) 00283 { 00284 return index(get_ull(i.c_str()), get_ull(s.c_str()), 0, true, false /*empty*/); 00285 } 00286 00287 D4ConstraintEvaluator::index 00288 D4ConstraintEvaluator::make_index(const std::string &i, unsigned long long s) 00289 { 00290 return index(get_ull(i.c_str()), s, 0, true, false /*empty*/); 00291 } 00292 00293 // This method is called from the parser (see d4_ce_parser.yy, down in the code 00294 // section). This will be called during the call to D4CEParser::parse(), that 00295 // is inside D4ConstraintEvaluator::parse(...) 00296 void 00297 D4ConstraintEvaluator::error(const libdap::location &l, const std::string &m) 00298 { 00299 ostringstream oss; 00300 oss << l << ": " << m << ends; 00301 throw Error(malformed_expr, oss.str()); 00302 } 00303 00304 } /* namespace libdap */