bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
BindShapeFunction.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) 2013 OPeNDAP, Inc.
7// Authors: 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
25#include "config.h"
26
27#include <cassert>
28
29#include <sstream>
30#include <vector>
31
32#include <libdap/BaseType.h>
33#include <libdap/Array.h>
34#include <libdap/Str.h>
35
36#include <libdap/Error.h>
37#include <libdap/DDS.h>
38#include <libdap/DMR.h>
39#include <libdap/D4RValue.h>
40#include <libdap/D4Dimensions.h>
41#include <libdap/debug.h>
42#include <libdap/util.h>
43
44#include <BESDebug.h>
45
46#include "BindNameFunction.h"
47
48using namespace std;
49using namespace libdap;
50
51namespace functions {
52
53string bind_shape_info =
54 string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
55 + "<function name=\"make_array\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#bind_shape\">\n"
56 + "</function>";
57
58vector<int> parse_dims(const string &shape); // defined in MakeArrayFunction.cc
59
60BaseType *bind_shape_worker(string shape, BaseType *btp)
61{
62 // string shape = extract_string_argument(argv[0]);
63 vector<int> dims = parse_dims(shape);
64
65 Array *array = dynamic_cast<Array*>(btp);
66 if (!array) throw Error(malformed_expr, "bind_shape() requires an Array as its second argument.");
67
68 unsigned long vector_size = array->length();
69 DBG(cerr << "bind_shape_worker() - vector_size: " << long_to_string(vector_size) << endl);
70
71 array->clear_all_dims();
72
73 unsigned long number_of_elements = 1;
74 vector<int>::iterator i = dims.begin();
75 while (i != dims.end()) {
76 int dimSize = *i;
77 number_of_elements *= dimSize;
78 if (array->is_dap4()) {
79 DBG(cerr << "bind_shape_worker() - Adding DAP4 dimension." << endl);
80
81 // FIXME - I think this creates a memory leak because
82 // the D4Dimension will never be deleted by the
83 // current implementation of Array which only has a
84 // weak pointer to the D4Dimension.
85 //
86 // NB: The likely fix is to find the Group that holds
87 // this variable and add the new D4Dimension to its
88 // D4Dimensions object. That will enure it is
89 // deleted. jhrg 8/26/14
90 D4Dimension *this_dim = new D4Dimension("", dimSize);
91 array->append_dim(this_dim);
92 }
93 else {
94 DBG(cerr << "bind_shape_worker() - Adding DAP2 dimension." << endl);
95 array->append_dim(dimSize);
96 }
97 i++;
98 } DBG(cerr << "bind_shape_worker() - number_of_elements: " << long_to_string(number_of_elements) << endl);
99
100 if (number_of_elements != vector_size)
101 throw Error(malformed_expr,
102 "bind_shape(): The product of the new dimensions must match the size of the Array's internal storage vector.");
103
104 return array;
105}
106
121void function_bind_shape_dap2(int argc, BaseType * argv[], DDS &, BaseType **btpp)
122{
123 if (argc == 0) {
124 Str *response = new Str("info");
125 response->set_value(bind_shape_info);
126 *btpp = response;
127 return;
128 }
129
130 // Check for two args or more. The first two must be strings.
131 if (argc != 2) throw Error(malformed_expr, "bind_shape(shape,variable) requires two arguments.");
132
133 string shape = extract_string_argument(argv[0]);
134
135 BaseType *btp = argv[1];
136
137 *btpp = bind_shape_worker(shape, btp);
138
139 return;
140}
141
155
156BaseType *function_bind_shape_dap4(D4RValueList *args, DMR &dmr)
157{
158 // DAP4 function porting information: in place of 'argc' use 'args.size()'
159 if (args == 0 || args->size() == 0) {
160 Str *response = new Str("info");
161 response->set_value(bind_shape_info);
162 // DAP4 function porting: return a BaseType* instead of using the value-result parameter
163 return response;
164 }
165
166 // Check for 2 arguments
167 DBG(cerr << "args.size() = " << args.size() << endl);
168 if (args->size() != 2) throw Error(malformed_expr, "bind_shape(shape,variable) requires two arguments.");
169
170 string shape = extract_string_argument(args->get_rvalue(0)->value(dmr));
171
172 BaseType *btp = args->get_rvalue(1)->value(dmr);
173
174 return bind_shape_worker(shape, btp);
175}
176
177} // namesspace functions