bes  Updated for version 3.17.0
grid_utils.cc
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) 2002,2003 OPeNDAP, Inc.
7 // Author: Nathan Potter <npotter@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 
25 #include "config.h"
26 
27 #include <BaseType.h>
28 #include <Structure.h>
29 #include <Grid.h>
30 #include <util.h>
31 
32 #include <BESDebug.h>
33 
34 #include "grid_utils.h"
35 #include "gse_parser.h"
36 #include "GSEClause.h"
37 #include "GridGeoConstraint.h"
38 
39 using namespace libdap;
40 
41 int gse_parse(functions::gse_arg *arg);
42 void gse_restart(FILE * in);
43 
44 // Glue routines declared in gse.lex
45 void gse_delete_buffer(void *buffer);
46 void *gse_string(const char *yy_str);
47 
48 namespace functions {
49 
56 void getGrids(BaseType *bt, vector<Grid *> *grids)
57 {
58  switch (bt->type()) {
59 
60  case dods_grid_c: {
61  // Yay! It's a Grid!
62  //Grid &grid = static_cast<Grid&>(*bt);
63  grids->push_back(static_cast<Grid*>(bt));
64  break;
65  }
66  case dods_structure_c: {
67  // It's an Structure - but of what? Check each variable in the Structure.
68  Structure &s = static_cast<Structure&>(*bt);
69  for (Structure::Vars_iter i = s.var_begin(); i != s.var_begin(); i++) {
70  //BaseType *sbt = *i;
71  getGrids(*i, grids);
72  }
73  break;
74  }
75  // Grids cannot be members of Array or Sequence in DAP2. jhrg 6/10/13
76  case dods_array_c:
77  case dods_sequence_c:
78  default:
79  break;
80  }
81 }
82 
89 void getGrids(DDS &dds, vector<Grid *> *grids)
90 {
91  for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++) {
92  //BaseType *bt = *i;
93  getGrids(*i, grids);
94  }
95 }
96 
106 bool isGeoGrid(Grid *grid)
107 {
108  try {
109  GridGeoConstraint gc(grid);
110  }
111  catch (Error *e) {
112  return false;
113  }
114 
115  return true;
116 }
117 
118 void parse_gse_expression(gse_arg *arg, BaseType *expr)
119 {
120  gse_restart(0); // Restart the scanner.
121  void *cls = gse_string(extract_string_argument(expr).c_str());
122  // gse_switch_to_buffer(cls); // Get set to scan the string.
123  bool status = gse_parse(arg) == 0;
124  gse_delete_buffer(cls);
125  if (!status)
126  throw Error(malformed_expr, "Error parsing grid selection.");
127 }
128 
129 static void apply_grid_selection_expr(Grid *grid, GSEClause *clause)
130 {
131  // Basic plan: For each map, look at each clause and set start and stop
132  // to be the intersection of the ranges in those clauses.
133  Grid::Map_iter map_i = grid->map_begin();
134  while (map_i != grid->map_end() && (*map_i)->name() != clause->get_map_name())
135  ++map_i;
136 
137  if (map_i == grid->map_end())
138  throw Error(malformed_expr,"The map vector '" + clause->get_map_name()
139  + "' is not in the grid '" + grid->name() + "'.");
140 
141  // Use pointer arith & the rule that map order must match array dim order
142  Array::Dim_iter grid_dim = (grid->get_array()->dim_begin() + (map_i - grid->map_begin()));
143 
144  Array *map = dynamic_cast < Array * >((*map_i));
145  if (!map)
146  throw InternalErr(__FILE__, __LINE__, "Expected an Array");
147  int start = max(map->dimension_start(map->dim_begin()), clause->get_start());
148  int stop = min(map->dimension_stop(map->dim_begin()), clause->get_stop());
149 
150  if (start > stop) {
151  ostringstream msg;
152  msg
153  << "The expressions passed to grid() do not result in an inclusive \n"
154  << "subset of '" << clause->get_map_name()
155  << "'. The map's values range " << "from "
156  << clause->get_map_min_value() << " to "
157  << clause->get_map_max_value() << ".";
158  throw Error(malformed_expr,msg.str());
159  }
160 
161  BESDEBUG("GeoGrid", "Setting constraint on " << map->name() << "[" << start << ":" << stop << "]" << endl);
162 
163  // Stride is always one.
164  map->add_constraint(map->dim_begin(), start, 1, stop);
165  grid->get_array()->add_constraint(grid_dim, start, 1, stop);
166 }
167 
168 void apply_grid_selection_expressions(Grid * grid, vector < GSEClause * >clauses)
169 {
170  vector < GSEClause * >::iterator clause_i = clauses.begin();
171  while (clause_i != clauses.end())
172  apply_grid_selection_expr(grid, *clause_i++);
173 
174  grid->set_read_p(false);
175 }
176 
177 } //namespace libdap