libdap Updated for version 3.21.0
libdap4 is an implementation of OPeNDAP's DAP protocol.
Array.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: 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// (c) COPYRIGHT URI/MIT 1994-1999
26// Please read the full copyright statement in the file COPYRIGHT_URI.
27//
28// Authors:
29// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
30
31// Implementation for Array.
32//
33// jhrg 9/13/94
34
35#include "config.h"
36
37// #define DODS_DEBUG
38
39#include <algorithm>
40#include <functional>
41#include <sstream>
42
43#include "Array.h"
44#include "Grid.h"
45
46#include "D4Attributes.h"
47#include "D4Dimensions.h"
48#include "D4Enum.h"
49#include "D4EnumDefs.h"
50#include "D4Group.h"
51#include "D4Maps.h"
52#include "DMR.h"
53#include "XMLWriter.h"
54
55#include "DapIndent.h"
56#include "InternalErr.h"
57#include "debug.h"
58#include "escaping.h"
59#include "util.h"
60
61using namespace std;
62
63namespace libdap {
64
65Array::dimension::dimension(D4Dimension *d) : dim(d), use_sdim_for_slice(true) {
66 size = d->size();
67 name = d->name();
68
69 start = 0;
70 stop = size - 1;
71 stride = 1;
72 c_size = size;
73}
74
75void Array::_duplicate(const Array &a) {
76 _shape = a._shape;
77
78 // Deep copy the Maps if they are being used.
79 if (a.d_maps) {
80 d_maps = new D4Maps(*a.d_maps, this);
81 } else {
82 d_maps = nullptr;
83 }
84}
85
86// The first method of calculating length works when only one dimension is
87// constrained, and you want the others to appear in the total. This is important
88// when selecting from grids since users may not select from all dimensions
89// in which case that means they want the whole thing. Array projection
90// should probably work this way too, but it doesn't. 9/21/2001 jhrg
91
99 uint64_t length = 1;
100 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
101 length *= (*i).c_size;
102 }
103
105}
106
107void Array::update_length_ll(unsigned long long) {
108 unsigned long long length = 1;
109 for (const auto &i : _shape) {
110 length *= i.c_size;
111 }
112
113 set_length_ll(length);
114}
115
116// Construct an instance of Array. The (BaseType *) is assumed to be
117// allocated using new - The dtor for Vector will delete this object.
118
133Array::Array(const string &n, BaseType *v, bool is_dap4 /* default:false */)
134 : Vector(n, nullptr, dods_array_c, is_dap4) {
136 if (v)
137 BaseType::set_is_dap4(v->is_dap4());
138}
139
152Array::Array(const string &n, const string &d, BaseType *v, bool is_dap4 /* default:false */)
153 : Vector(n, d, nullptr, dods_array_c, is_dap4) {
155 if (v)
156 BaseType::set_is_dap4(v->is_dap4());
157}
158
160Array::Array(const Array &rhs) : Vector(rhs) { _duplicate(rhs); }
161
163Array::~Array() { delete d_maps; }
164
165BaseType *Array::ptr_duplicate() { return new Array(*this); }
166
167Array &Array::operator=(const Array &rhs) {
168 if (this == &rhs)
169 return *this;
170 Vector::operator=(rhs);
171 _duplicate(rhs);
172 return *this;
173}
174
175void Array::transform_to_dap4(D4Group *root, Constructor *container) {
176 Array *dest = static_cast<Array *>(ptr_duplicate());
177
178 // If it's already a DAP4 object then we can just return it!
179 if (is_dap4()) {
180 container->add_var_nocopy(dest);
181 }
182
183 // Process the Array's dimensions, making D4 shared dimensions for
184 // D2 dimensions that are named. If there is just a size, don't make
185 // a D4Dimension (In DAP4 you cannot share a dimension unless it has
186 // a name). jhrg 3/18/14
187
188 D4Dimensions *root_dims = root->dims();
189 for (Array::Dim_iter dap2_dim = dest->dim_begin(), e = dest->dim_end(); dap2_dim != e; ++dap2_dim) {
190 if (!(*dap2_dim).name.empty()) {
191
192 // If a D4Dimension with the name already exists, use it.
193 D4Dimension *d4_dim = root_dims->find_dim((*dap2_dim).name);
194 if (!d4_dim) {
195 d4_dim = new D4Dimension((*dap2_dim).name, (*dap2_dim).size);
196 root_dims->add_dim_nocopy(d4_dim);
197 } else {
198 DBG(cerr << __func__ << "() -" << " Using Existing D4Dimension '" << d4_dim->name() << "' ("
199 << (void *)d4_dim << ")" << endl);
200 ;
201
202 if (d4_dim->size() != (unsigned long)(*dap2_dim).size) {
203 // TODO Revisit this decision. jhrg 3/18/14
204 // ...in case the name/size are different, make a unique D4Dimension
205 // but don't fiddle with the name. Not sure I like this idea, so I'm
206 // making the case explicit (could be rolled in to the block above).
207 // jhrg 3/18/14
208 //
209 // This is causing problems in the FITS handler because there are cases
210 // where two arrays have dimensions with the same name but different
211 // sizes. The deserializing code is using the first size listed, which is
212 // wrong in some cases. I'm going to try making this new D4Dimension using
213 // the dim name along with the variable name. jhrg 8/15/14
214 d4_dim = new D4Dimension((*dap2_dim).name + "_" + name(), (*dap2_dim).size);
215 DBG(cerr << __func__ << "() -" << " Utilizing Name/Size Conflict Naming Artifice. name'"
216 << d4_dim->name() << "' (" << (void *)d4_dim << ")" << endl);
217 ;
218 root_dims->add_dim_nocopy(d4_dim);
219 }
220 }
221 // At this point d4_dim's name and size == those of (*d) so just set
222 // the D4Dimension pointer so that it matches the one in the D4Group.
223 (*dap2_dim).dim = d4_dim;
224 }
225 }
226
227 // Copy the D2 attributes to D4 Attributes
229 dest->set_is_dap4(true);
230 container->add_var_nocopy(dest);
231}
232
233bool Array::is_dap2_grid() {
234 bool is_grid = false;
235 if (this->is_dap4()) {
236 DBG(cerr << __func__ << "() - Array '" << name() << "' is DAP4 object!" << endl);
237 auto root = dynamic_cast<D4Group *>(this->get_ancestor());
238 if (!root)
239 throw InternalErr(__FILE__, __LINE__, string("Could not get the root group for ").append(this->name()));
240 D4Maps *d4_maps = this->maps();
241 is_grid = d4_maps->size(); // It can't be a grid if there are no maps...
242
243 // We also need to check if the number of maps is the same as the number of dimensions. If not, this is not a
244 // dap2 grid.
245 if (d4_maps->size() != ((int)dimensions()))
246 is_grid = false;
247 if (is_grid) {
248 DBG(cerr << __func__ << "() - Array '" << name() << "' has D4Maps." << endl);
249 // hmmm this might be a DAP2 Grid...
250 D4Maps::D4MapsIter i = d4_maps->map_begin();
251 D4Maps::D4MapsIter e = d4_maps->map_end();
252
253 while (i != e) {
254 DBG(cerr << __func__ << "() - Map '" << (*i)->array()->name() << " has " << (*i)->array()->_shape.size()
255 << " dimension(s)." << endl);
256 if ((*i)->array(root)->_shape.size() > 1) {
257 is_grid = false;
258 i = e;
259 } else {
260 i++;
261 }
262 }
263 } else {
264 DBG(cerr << __func__ << "() - Array '" << name() << "' has no D4Maps." << endl);
265 }
266 }
267
268 DBG(cerr << __func__ << "() - is_grid: " << (is_grid ? "true" : "false") << endl);
269 return is_grid;
270}
271
287std::vector<BaseType *> *Array::transform_to_dap2(AttrTable *) {
288 DBG(cerr << __func__ << "() - BEGIN Array '" << name() << "'" << endl);
289 ;
290
291 BaseType *dest;
292 if (!is_dap4()) { // Don't convert a DAP2 thing
293 dest = ptr_duplicate();
294 } else {
295 // At this point we have a DAP4 Array. It have D4Attributes and nothing
296 // in the DAP2 AttrTable (which is held as a reference, defined in BaseType).
297 // This test determines in the D4 Array qualifies as a D2 Grid.
298 if (is_dap2_grid()) {
299 // Oh yay! Grids are special.
300 DBG(cerr << __func__ << "() - Array '" << name() << "' is dap2 Grid!" << endl);
301 ;
302 Grid *g = new Grid(name());
303 dest = g;
304 Array *grid_array = static_cast<Array *>(ptr_duplicate());
305 grid_array->set_is_dap4(false);
306 g->set_array(grid_array);
307
308 // Fix for HK-403. jhrg 6/17/19
310
311 // Process the Map Arrays.
312 auto root = dynamic_cast<D4Group *>(this->get_ancestor());
313 if (!root)
314 throw InternalErr(__FILE__, __LINE__, string("Could not get the root group for ").append(this->name()));
315 D4Maps *d4_maps = this->maps();
316 vector<BaseType *> dropped_maps;
317 D4Maps::D4MapsIter miter = d4_maps->map_begin();
318 D4Maps::D4MapsIter end = d4_maps->map_end();
319 for (; miter != end; miter++) {
320 D4Map *d4_map = (*miter);
321 Array *d4_map_array = const_cast<Array *>(d4_map->array(root));
322 vector<BaseType *> *d2_result = d4_map_array->transform_to_dap2(&(g->get_attr_table()));
323 if (d2_result) {
324 if (d2_result->size() > 1)
325 throw Error(internal_error, "D4Map Array conversion resulted in multiple DAP2 objects.");
326
327 // TODO - This is probably slow and needs a better pattern. const_cast? static_cast?
328 Array *d2_map_array = dynamic_cast<Array *>((*d2_result)[0]);
329 if (d2_map_array) {
330 if (d2_map_array->dimensions() != 1)
331 throw Error(internal_error,
332 "DAP2 array from D4Map Array conversion has more than 1 dimension.");
333
334 d2_map_array->set_is_dap4(false);
335 g->add_map(d2_map_array, false);
336 AttrTable at = d2_map_array->get_attr_table();
337 DBG(cerr << __func__ << "() - " << "DAS For Grid Map '" << d2_map_array->name() << "':" << endl;
338 at.print(cerr););
339 } else {
340 throw Error(internal_error, "Unable to interpret returned DAP2 content.");
341 }
342 delete d2_result;
343 } else {
344 dropped_maps.push_back(d4_map_array);
345 }
346 }
347
348 // Did we have a transform failure?
349 if (!dropped_maps.empty()) {
350 // Yup... tell the story in the attributes.
351 AttrTable *dv_table = Constructor::make_dropped_vars_attr_table(&dropped_maps);
352 dest->get_attr_table().append_container(dv_table, dv_table->get_name());
353 }
354 } else {
355 DBG(cerr << __func__ << "() - Array '" << name() << "' is not a Grid!" << endl);
356
357 BaseType *proto = prototype();
358 switch (proto->type()) {
359 case dods_int64_c:
360 case dods_uint64_c:
361 case dods_enum_c:
362 case dods_opaque_c:
363 // For now we punt on these types as they have no easy representation in
364 // the DAP2 data model. By setting this to NULL we cause the Array to be
365 // dropped and this will be reflected in the metadata (DAS).
366 dest = NULL;
367 break;
368
369 default:
370 // ptr_duplicate() does the Attributes too.
371 dest = ptr_duplicate();
372
373 // Fix for HK-403. jhrg 6/17/19
374 // Only transform the DAP4 attributes to DAP2 ones if the DAP2 object lacks
375 // attributes. If the new DAP2 variable already has attributes, they were
376 // added by this process (driven by D4Group::transform_to_dap2() and calling
377 // attributes()->transform_to_dap2() will put a second copy of each attribute's
378 // value in the DAP2 AttrTable. This attribute transform code (here and elsewhere)
379 // depends on the AttrTable for a DAP4 variable initially being empty. Once it
380 // contains attributes, the code assumes they were put there by this transform
381 // process. jhrg 6/18/19
382 if (dest->get_attr_table().get_size() == 0) {
384 dest->get_attr_table().set_name(name());
385 }
386
387 dest->set_is_dap4(false);
388 break;
389 }
390 }
391 }
392
393 vector<BaseType *> *result;
394 if (dest) {
395 result = new vector<BaseType *>();
396 result->push_back(dest);
397 } else {
398 result = NULL;
399 }
400
401 DBG(cerr << __func__ << "() - END Array '" << name() << "'" << endl);
402 ;
403 return result;
404}
405
417void Array::update_dimension_pointers(D4Dimensions *old_dims, D4Dimensions *new_dims) {
418 std::vector<dimension>::iterator i = _shape.begin(), e = _shape.end();
419 while (i != e) {
420 D4Dimensions::D4DimensionsIter old_i = old_dims->dim_begin(), old_e = old_dims->dim_end();
421 while (old_i != old_e) {
422 if ((*i).dim == *old_i) {
423 (*i).dim = new_dims->find_dim((*old_i)->name());
424 }
425 ++old_i;
426 }
427
428 ++i;
429 }
430}
431
455
457 // If 'v' is an Array, add the template instance to this object and
458 // then copy the dimension information. Odd semantics; I wonder if this
459 // is ever used. jhrg 6/13/12
460 if (v && v->type() == dods_array_c) {
461 Array *a = static_cast<Array *>(v);
462 Vector::add_var(a->var());
463
464 Dim_iter i = a->dim_begin();
465 Dim_iter i_end = a->dim_end();
466 while (i != i_end) {
468 ++i;
469 }
470 } else {
472 }
473}
474
475void Array::add_var_nocopy(BaseType *v, Part) {
476 // If 'v' is an Array, add the template instance to this object and
477 // then copy the dimension information. Odd semantics; I wonder if this
478 // is ever used. jhrg 6/13/12
479 if (v && v->type() == dods_array_c) {
480 Array &a = dynamic_cast<Array &>(*v);
481 Vector::add_var_nocopy(a.var());
482 Dim_iter i = a.dim_begin();
483 Dim_iter i_end = a.dim_end();
484 while (i != i_end) {
486 ++i;
487 }
488 } else {
489 Vector::add_var_nocopy(v);
490 }
491}
492
504void Array::append_dim(int size, const string &name) {
505 dimension d(size, www2id(name));
506 _shape.push_back(d);
507
509}
510
511void Array::append_dim_ll(int64_t size, const string &name) {
512
513#if 0
514 dimension d(size, www2id(name));
515 _shape.push_back(d);
516#endif
517
518 _shape.emplace_back(size, www2id(name));
520}
521
522void Array::append_dim(D4Dimension *dim) {
523 dimension d(/*dim->size(), www2id(dim->name()),*/ dim);
524 _shape.push_back(d);
525
527}
528
534void Array::prepend_dim(int size, const string &name /* = "" */) {
535 dimension d(size, www2id(name));
536 // Shifts the whole array, but it's tiny in general
537 _shape.insert(_shape.begin(), d);
538
539 update_length(); // the number is ignored...
540}
541
543 dimension d(/*dim->size(), www2id(dim->name()),*/ dim);
544 // Shifts the whole array, but it's tiny in general
545 _shape.insert(_shape.begin(), d);
546
547 update_length(); // the number is ignored...
548}
549
553void Array::clear_all_dims() { _shape.clear(); }
554
559
560void Array::rename_dim(const string &oldName, const string &newName) {
561 std::vector<dimension>::iterator i = _shape.begin(), e = _shape.end();
562 while (i != e) {
563 dimension &d = *i;
564 if (d.name == oldName) {
565 DBG(cerr << "Old name = " << d.name << " newName = " << newName << endl);
566 d.name = newName;
567 }
568
569 ++i;
570 }
571}
572
579 set_length(-1);
580
581 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
582 (*i).start = 0;
583 (*i).stop = (*i).size - 1;
584 (*i).stride = 1;
585 (*i).c_size = (*i).size;
586
588 }
589}
590
601
602// Note: MS VC++ won't tolerate embedded newlines in strings, hence the \n
603// is explicit.
604static const char *array_sss = "Invalid constraint parameters: At least one of the start, stride or stop \n\
605specified do not match the array variable.";
606
627void Array::add_constraint(Dim_iter i, int start, int stride, int stop) {
628 dimension &d = *i;
629
630 DBG(cerr << "add_constraint: d_size = " << d.size << endl);
631 DBG(cerr << "add_constraint: start = " << start << endl);
632 DBG(cerr << "add_constraint: stop = " << stop << endl);
633 DBG(cerr << "add_constraint: stride = " << stride << endl);
634
635 // if stop is -1, set it to the array's max element index
636 // jhrg 12/20/12
637 // Check if d.size is greater than INT_MAX, if yes, the following block needs to be re-worked. STOP
638 if (stop == -1) {
639 if (d.size > DODS_INT_MAX) {
640 // The total size of this dimension is greater than the maximum 32-bit integer.
641 throw Error(malformed_expr, "The dimension size is too large. use add_constraint_ll()");
642 } else
643 stop = d.size - 1;
644 }
645
646 // Check for bad constraints.
647 // Jose Garcia
648 // Usually invalid data for a constraint is the user's mistake
649 // because they build a wrong URL in the client side.
650 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0)
651 throw Error(malformed_expr, array_sss);
652
653 if (((stop - start) / stride + 1) > d.size)
654 throw Error(malformed_expr, array_sss);
655
656 d.start = start;
657 d.stop = stop;
658 d.stride = stride;
659
660 d.c_size = (stop - start) / stride + 1;
661
662 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
663
665
666 d.use_sdim_for_slice = false;
667}
668
669void Array::add_constraint_ll(Dim_iter i, int64_t start, int64_t stride, int64_t stop) {
670 dimension &d = *i;
671 DBG(cerr << "add_constraint_ll: d_size = " << d.size << endl);
672 DBG(cerr << "add_constraint_ll: start = " << start << endl);
673 DBG(cerr << "add_constraint_ll: stop = " << stop << endl);
674 DBG(cerr << "add_constraint_ll: stride = " << stride << endl);
675
676 // if stop is -1, set it to the array's max element index
677 // jhrg 12/20/12
678 if (stop == -1)
679 stop = d.size - 1;
680
681 // Check for bad constraints.
682 // Jose Garcia
683 // Usually invalid data for a constraint is the user's mistake
684 // because they build a wrong URL in the client side.
685 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0)
686 throw Error(malformed_expr, array_sss);
687
688 if (((stop - start) / stride + 1) > d.size)
689 throw Error(malformed_expr, array_sss);
690
691 d.start = start;
692 d.stop = stop;
693 d.stride = stride;
694
695 d.c_size = (stop - start) / stride + 1;
696
697 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
698
700
701 d.use_sdim_for_slice = false;
702}
703void Array::add_constraint(Dim_iter i, D4Dimension *dim) {
704 dimension &d = *i;
705 DBG(cerr << "add_constraint d4dimension: stride = " << dim->c_stride() << endl);
706
707 if (dim->constrained())
708 add_constraint_ll(i, dim->c_start(), dim->c_stride(), dim->c_stop());
709
710 dim->set_used_by_projected_var(true);
711
712 // In this case the value below overrides the value for use_sdim_for_slice
713 // set in the above call. jhrg 12/20/13
714 d.use_sdim_for_slice = true;
715}
716
718Array::Dim_iter Array::dim_begin() { return _shape.begin(); }
719
721Array::Dim_iter Array::dim_end() { return _shape.end(); }
722
723// TODO Many of these methods take a bool parameter that serves no use; remove.
724
733unsigned int Array::dimensions(bool /*constrained*/) { return _shape.size(); }
734
752int Array::dimension_size(Dim_iter i, bool constrained) {
753 int size = 0;
754
755 if (!_shape.empty()) {
756 if (constrained) {
757 if ((*i).c_size > DODS_INT_MAX) {
758 throw Error(malformed_expr, "The dimension size is too large. Use dimension_size_ll()");
759 } else
760 size = (*i).c_size;
761 } else {
762 if ((*i).size > DODS_INT_MAX) {
763 throw Error(malformed_expr, "The dimension size is too large. Use dimension_size_ll()");
764 } else
765 size = (*i).size;
766 }
767 }
768
769 return size;
770}
771
790int Array::dimension_start(Dim_iter i, bool /*constrained*/) {
791 if ((*i).start > DODS_INT_MAX) {
792 throw Error(malformed_expr, "The dimension start value is too large. Use dimension_start_ll()");
793 }
794 return (!_shape.empty()) ? (*i).start : 0;
795}
796
815int Array::dimension_stop(Dim_iter i, bool /*constrained*/) {
816 if ((*i).stop > DODS_INT_MAX) {
817 throw Error(malformed_expr, "The dimension stop value is too large. Use dimension_stop_ll()");
818 }
819 return (!_shape.empty()) ? (*i).stop : 0;
820}
821
841int Array::dimension_stride(Dim_iter i, bool /*constrained*/) {
842 if ((*i).stride > DODS_INT_MAX) {
843 throw Error(malformed_expr, "The dimension stride value is too large. Use dimension_stride_ll()");
844 }
845 return (!_shape.empty()) ? (*i).stride : 0;
846}
847
848int64_t Array::dimension_size_ll(Dim_iter i, bool constrained) {
849 int64_t size = 0;
850
851 if (!_shape.empty()) {
852 if (constrained)
853 size = (*i).c_size;
854 else
855 size = (*i).size;
856 }
857 return size;
858}
859
860int64_t Array::dimension_start_ll(Dim_iter i, bool /*constrained*/) { return (!_shape.empty()) ? (*i).start : 0; }
861
862int64_t Array::dimension_stop_ll(Dim_iter i, bool /*constrained*/) { return (!_shape.empty()) ? (*i).stop : 0; }
863
864int64_t Array::dimension_stride_ll(Dim_iter i, bool /*constrained*/) { return (!_shape.empty()) ? (*i).stride : 0; }
865
877 // Jose Garcia
878 // Since this method is public, it is possible for a user
879 // to call it before the Array object has been properly set
880 // this will cause an exception which is the user's fault.
881 // (User in this context is the developer of the surrogate library.)
882 if (_shape.empty())
883 throw InternalErr(__FILE__, __LINE__, "*This* array has no dimensions.");
884 return (*i).name;
885}
886
887D4Dimension *Array::dimension_D4dim(Dim_iter i) { return (!_shape.empty()) ? (*i).dim : 0; }
888
889D4Maps *Array::maps() {
890 if (!d_maps)
891 d_maps = new D4Maps(this); // init with this as parent
892 return d_maps;
893}
894
895#if 0
902unsigned int Array::width(bool constrained) const
903{
904
905 if (constrained) {
906 // This preserves the original method's semantics when we ask for the
907 // size of the constrained array but no constraint has been applied.
908 // In this case, length will be -1. Wrong, I know...
909 return length() * var()->width(constrained);
910 }
911 else {
912 int length = 1;
913 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
914 length *= dimension_size(i, false);
915 }
916 return length * var()->width(false);
917 }
918}
919#endif
920
921class PrintD4ArrayDimXMLWriter : public unary_function<Array::dimension &, void> {
922 XMLWriter &xml;
923 // Was this variable constrained using local/direct slicing? i.e., is d_local_constraint set?
924 // If so, don't use shared dimensions; instead emit Dim elements that are anonymous.
925 bool d_constrained;
926
927public:
928 PrintD4ArrayDimXMLWriter(XMLWriter &xml, bool c) : xml(xml), d_constrained(c) {}
929
930 void operator()(Array::dimension &d) {
931 // This duplicates code in D4Dimensions (where D4Dimension::print_dap4() is defined
932 // because of the need to print the constrained size of a dimension. I think that
933 // the constraint information has to be kept here and not in the dimension (since they
934 // are shared dims). Could hack print_dap4() to take the constrained size, however.
935 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar *)"Dim") < 0)
936 throw InternalErr(__FILE__, __LINE__, "Could not write Dim element");
937
938 string name = (d.dim) ? d.dim->fully_qualified_name() : d.name;
939 // If there is a name, there must be a Dimension (named dimension) in scope
940 // so write its name but not its size.
941 if (!d_constrained && !name.empty()) {
942 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name", (const xmlChar *)name.c_str()) <
943 0)
944 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
945 } else if (d.use_sdim_for_slice) {
946 assert(!name.empty());
947 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name", (const xmlChar *)name.c_str()) <
948 0)
949 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
950 } else {
951 ostringstream size;
952 size << (d_constrained ? d.c_size : d.size);
953 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"size",
954 (const xmlChar *)size.str().c_str()) < 0)
955 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
956 }
957
958 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
959 throw InternalErr(__FILE__, __LINE__, "Could not end Dim element");
960 }
961};
962
963class PrintD4ConstructorVarXMLWriter : public unary_function<BaseType *, void> {
964 XMLWriter &xml;
965 bool d_constrained;
966
967public:
968 PrintD4ConstructorVarXMLWriter(XMLWriter &xml, bool c) : xml(xml), d_constrained(c) {}
969
970 void operator()(BaseType *btp) { btp->print_dap4(xml, d_constrained); }
971};
972
973class PrintD4MapXMLWriter : public unary_function<D4Map *, void> {
974 XMLWriter &xml;
975
976public:
977 PrintD4MapXMLWriter(XMLWriter &xml) : xml(xml) {}
978
979 void operator()(D4Map *m) { m->print_dap4(xml); }
980};
981
987void Array::print_dap4(XMLWriter &xml, bool constrained /* default: false*/) {
988 if (constrained && !send_p())
989 return;
990
991 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar *)var()->type_name().c_str()) < 0)
992 throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
993
994 if (!name().empty())
995 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name", (const xmlChar *)name().c_str()) < 0)
996 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
997
998 // Hack job... Copied from D4Enum::print_xml_writer. jhrg 11/12/13
999 if (var()->type() == dods_enum_c) {
1000 D4Enum *e = static_cast<D4Enum *>(var());
1001 string path = e->enumeration()->name();
1002 if (e->enumeration()->parent()) {
1003 // print the FQN for the enum def; D4Group::FQN() includes the trailing '/'
1004 path = static_cast<D4Group *>(e->enumeration()->parent()->parent())->FQN() + path;
1005 }
1006 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"enum", (const xmlChar *)path.c_str()) < 0)
1007 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for enum");
1008 }
1009
1010 if (prototype()->is_constructor_type()) {
1011 Constructor &c = static_cast<Constructor &>(*prototype());
1012 for_each(c.var_begin(), c.var_end(), PrintD4ConstructorVarXMLWriter(xml, constrained));
1013 // bind2nd(mem_fun_ref(&BaseType::print_dap4), xml));
1014 }
1015
1016 // Drop the local_constraint which is per-array and use a per-dimension on instead
1017 for_each(dim_begin(), dim_end(), PrintD4ArrayDimXMLWriter(xml, constrained));
1018
1019 attributes()->print_dap4(xml);
1020
1021 for_each(maps()->map_begin(), maps()->map_end(), PrintD4MapXMLWriter(xml));
1022
1023 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1024 throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
1025}
1026
1044void Array::print_decl(FILE *out, string space, bool print_semi, bool constraint_info, bool constrained) {
1045 ostringstream oss;
1046 print_decl(oss, space, print_semi, constraint_info, constrained);
1047 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1048}
1049
1067void Array::print_decl(ostream &out, string space, bool print_semi, bool constraint_info, bool constrained) {
1068 if (constrained && !send_p())
1069 return;
1070
1071 // print it, but w/o semicolon
1072 var()->print_decl(out, space, false, constraint_info, constrained);
1073
1074 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
1075 out << "[";
1076 if ((*i).name != "") {
1077 out << id2www((*i).name) << " = ";
1078 }
1079 if (constrained) {
1080 out << (*i).c_size << "]";
1081 } else {
1082 out << (*i).size << "]";
1083 }
1084 }
1085
1086 if (print_semi) {
1087 out << ";\n";
1088 }
1089}
1090
1094void Array::print_xml(FILE *out, string space, bool constrained) {
1095 XMLWriter xml(space);
1096 print_xml_writer_core(xml, constrained, "Array");
1097 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
1098}
1099
1103void Array::print_xml(ostream &out, string space, bool constrained) {
1104 XMLWriter xml(space);
1105 print_xml_writer_core(xml, constrained, "Array");
1106 out << xml.get_doc();
1107}
1108
1112void Array::print_as_map_xml(FILE *out, string space, bool constrained) {
1113 XMLWriter xml(space);
1114 print_xml_writer_core(xml, constrained, "Map");
1115 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
1116}
1117
1121void Array::print_as_map_xml(ostream &out, string space, bool constrained) {
1122 XMLWriter xml(space);
1123 print_xml_writer_core(xml, constrained, "Map");
1124 out << xml.get_doc();
1125}
1126
1130void Array::print_xml_core(FILE *out, string space, bool constrained, string tag) {
1131 XMLWriter xml(space);
1132 print_xml_writer_core(xml, constrained, tag);
1133 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
1134}
1135
1139void Array::print_xml_core(ostream &out, string space, bool constrained, string tag) {
1140 XMLWriter xml(space);
1141 print_xml_writer_core(xml, constrained, tag);
1142 out << xml.get_doc();
1143}
1144
1145void Array::print_xml_writer(XMLWriter &xml, bool constrained) { print_xml_writer_core(xml, constrained, "Array"); }
1146
1147void Array::print_as_map_xml_writer(XMLWriter &xml, bool constrained) {
1148 print_xml_writer_core(xml, constrained, "Map");
1149}
1150
1151class PrintArrayDimXMLWriter : public unary_function<Array::dimension &, void> {
1152 XMLWriter &xml;
1153 bool d_constrained;
1154
1155public:
1156 PrintArrayDimXMLWriter(XMLWriter &xml, bool c) : xml(xml), d_constrained(c) {}
1157
1158 void operator()(Array::dimension &d) {
1159 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar *)"dimension") < 0)
1160 throw InternalErr(__FILE__, __LINE__, "Could not write dimension element");
1161
1162 if (!d.name.empty())
1163 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name",
1164 (const xmlChar *)d.name.c_str()) < 0)
1165 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1166
1167 ostringstream size;
1168 size << (d_constrained ? d.c_size : d.size);
1169 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"size",
1170 (const xmlChar *)size.str().c_str()) < 0)
1171 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1172
1173 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1174 throw InternalErr(__FILE__, __LINE__, "Could not end dimension element");
1175 }
1176};
1177
1178void Array::print_xml_writer_core(XMLWriter &xml, bool constrained, string tag) {
1179 if (constrained && !send_p())
1180 return;
1181
1182 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar *)tag.c_str()) < 0)
1183 throw InternalErr(__FILE__, __LINE__, "Could not write " + tag + " element");
1184
1185 if (!name().empty())
1186 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name", (const xmlChar *)name().c_str()) < 0)
1187 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1188
1190
1191 BaseType *btp = var();
1192 string tmp_name = btp->name();
1193 btp->set_name("");
1194 btp->print_xml_writer(xml, constrained);
1195 btp->set_name(tmp_name);
1196
1197 for_each(dim_begin(), dim_end(), PrintArrayDimXMLWriter(xml, constrained));
1198
1199 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1200 throw InternalErr(__FILE__, __LINE__, "Could not end " + tag + " element");
1201}
1202
1214uint64_t Array::print_array(FILE *out, uint64_t index, unsigned int dims, uint64_t shape[]) {
1215 ostringstream oss;
1216 uint64_t i = print_array(oss, index, dims, shape);
1217 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1218
1219 return i;
1220}
1221
1233uint64_t Array::print_array(ostream &out, uint64_t index, unsigned int dims, uint64_t shape[]) {
1234 if (dims == 1) {
1235 out << "{";
1236
1237 // Added test in case this method is passed an array with no elements. jhrg 1/27/16
1238 if (shape[0] >= 1) {
1239 for (uint64_t i = 0; i < shape[0] - 1; ++i) {
1240 var_ll(index++)->print_val(out, "", false);
1241 out << ", ";
1242 }
1243 var_ll(index++)->print_val(out, "", false);
1244 }
1245
1246 out << "}";
1247
1248 return index;
1249 } else {
1250 out << "{";
1251 // Fixed an off-by-one error in the following loop. Since the array
1252 // length is shape[dims-1]-1 *and* since we want one less dimension
1253 // than that, the correct limit on this loop is shape[dims-2]-1. From
1254 // Todd Karakasian.
1255 //
1256 // The saga continues; the loop test should be `i < shape[0]-1'. jhrg
1257 // 9/12/96.
1258 //
1259 // For arrays that hold zero values but have rank > 1, the print out
1260 // may look a little odd (e.g., x[4][0] will print as { {}, {}, {}, {} })
1261 // but it's not wrong and this is really for debugging mostly. jhrg 1/28/16
1262 if (shape[0] > 0) {
1263 for (uint64_t i = 0; i < shape[0] - 1; ++i) {
1264 index = print_array(out, index, dims - 1, shape + 1);
1265 out << ",";
1266 }
1267
1268 index = print_array(out, index, dims - 1, shape + 1);
1269 }
1270
1271 out << "}";
1272
1273 return index;
1274 }
1275}
1276
1277void Array::print_val(FILE *out, string space, bool print_decl_p) {
1278 ostringstream oss;
1279 print_val(oss, space, print_decl_p);
1280 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1281}
1282
1283void Array::print_val(ostream &out, string space, bool print_decl_p) {
1284 // print the declaration if print decl is true.
1285 // for each dimension,
1286 // for each element,
1287 // print the array given its shape, number of dimensions.
1288 // Add the `;'
1289
1290 if (print_decl_p) {
1291 print_decl(out, space, false, false, false);
1292 out << " = ";
1293 }
1294
1295 auto shape = new uint64_t[dimensions(true)];
1296 unsigned int index = 0;
1297 for (Dim_iter i = _shape.begin(); i != _shape.end() && index < dimensions(true); ++i)
1298 shape[index++] = dimension_size_ll(i, true);
1299
1300 print_array(out, 0, dimensions(true), shape);
1301
1302 delete[] shape;
1303 shape = 0;
1304
1305 if (print_decl_p) {
1306 out << ";\n";
1307 }
1308}
1309
1318
1319bool Array::check_semantics(string &msg, bool) {
1320 bool sem = BaseType::check_semantics(msg) && !_shape.empty();
1321
1322 if (!sem)
1323 msg = "An array variable must have dimensions";
1324
1325 return sem;
1326}
1327
1335 stringstream sqr_brkty_stuff;
1336 for (auto itr = a.dim_begin(); itr != a.dim_end(); itr++) {
1337 sqr_brkty_stuff << "[";
1338 string dim_name = a.dimension_name(itr);
1339 if (!dim_name.empty()) {
1340 sqr_brkty_stuff << dim_name << "=";
1341 }
1342 sqr_brkty_stuff << a.dimension_size_ll(itr, true) << "]";
1343 }
1344 return sqr_brkty_stuff.str();
1345}
1346
1353bool Array::is_dap4_projected(std::vector<std::string> &inventory) {
1354 bool has_projected_dap4 = false;
1355 if (send_p()) {
1356 if (prototype()->is_constructor_type()) {
1357 has_projected_dap4 =
1358 prototype()->is_dap4_projected(inventory) || attributes()->has_dap4_types(FQN(), inventory);
1359 } else {
1360 Type type = prototype()->type();
1361 has_projected_dap4 = (type == libdap::dods_int8_c) || (type == dods_uint64_c) || (type == dods_int64_c);
1362 if (has_projected_dap4) {
1363 inventory.emplace_back(prototype()->type_name() + " " + FQN() + get_dims_decl(*this));
1364 }
1365 has_projected_dap4 |= attributes()->has_dap4_types(FQN(), inventory);
1366 }
1367 }
1368 return has_projected_dap4;
1369}
1370
1379void Array::dump(ostream &strm) const {
1380 strm << DapIndent::LMarg << "Array::dump - (" << (void *)this << ")" << endl;
1381 DapIndent::Indent();
1382 Vector::dump(strm);
1383 strm << DapIndent::LMarg << "shape:" << endl;
1384 DapIndent::Indent();
1385 Dim_citer i = _shape.begin();
1386 Dim_citer ie = _shape.end();
1387 unsigned int dim_num = 0;
1388 for (; i != ie; i++) {
1389 strm << DapIndent::LMarg << "dimension " << dim_num++ << ":" << endl;
1390 DapIndent::Indent();
1391 strm << DapIndent::LMarg << "name: " << (*i).name << endl;
1392 strm << DapIndent::LMarg << "size: " << (*i).size << endl;
1393 strm << DapIndent::LMarg << "start: " << (*i).start << endl;
1394 strm << DapIndent::LMarg << "stop: " << (*i).stop << endl;
1395 strm << DapIndent::LMarg << "stride: " << (*i).stride << endl;
1396 strm << DapIndent::LMarg << "constrained size: " << (*i).c_size << endl;
1397 DapIndent::UnIndent();
1398 }
1399 DapIndent::UnIndent();
1400 DapIndent::UnIndent();
1401}
1402
1410
1411 vs_info.filter = my_vs_info.filter;
1412
1413 for (const auto &def_lev : my_vs_info.deflate_levels)
1414 vs_info.deflate_levels.push_back(def_lev);
1415
1416 for (const auto &chunk_dim : my_vs_info.chunk_dims)
1417 vs_info.chunk_dims.push_back(chunk_dim);
1418
1419 for (const auto &vci : my_vs_info.var_chunk_info) {
1420 var_chunk_info_t vci_t;
1421 vci_t.filter_mask = vci.filter_mask;
1422 vci_t.chunk_direct_io_offset = vci.chunk_direct_io_offset;
1423 vci_t.chunk_buffer_size = vci.chunk_buffer_size;
1424 for (const auto &chunk_coord : vci.chunk_coords)
1425 vci_t.chunk_coords.push_back(chunk_coord);
1426 vs_info.var_chunk_info.push_back(vci_t);
1427 }
1428}
1429
1430} // namespace libdap
A multidimensional array of identical data types.
Definition Array.h:121
void print_dap4(XMLWriter &xml, bool constrained=false) override
Print the DAP4 representation of an array.
Definition Array.cc:987
virtual int dimension_start(Dim_iter i, bool constrained=false)
Return the start index of a dimension.
Definition Array.cc:790
virtual void clear_constraint()
Clears the projection; add each projected dimension explicitly using add_constraint.
Definition Array.cc:600
Dim_iter dim_end()
Definition Array.cc:721
virtual int dimension_stop(Dim_iter i, bool constrained=false)
Return the stop index of the constraint.
Definition Array.cc:815
void dump(ostream &strm) const override
dumps information about this object
Definition Array.cc:1379
virtual void update_length(int size=0)
Definition Array.cc:98
bool is_dap4_projected(std::vector< std::string > &projected_dap4_inventory) override
Definition Array.cc:1353
virtual void add_constraint(Dim_iter i, int start, int stride, int stop)
Adds a constraint to an Array dimension.
Definition Array.cc:627
virtual string dimension_name(Dim_iter i)
Returns the name of the specified dimension.
Definition Array.cc:876
void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false) override
Prints a DDS entry for the Array.
Definition Array.cc:1067
void print_xml(ostream &out, string space=" ", bool constrained=false) override
Definition Array.cc:1103
void print_val(ostream &out, string space="", bool print_decl_p=true) override
Prints the value of the variable.
Definition Array.cc:1283
BaseType * ptr_duplicate() override
Definition Array.cc:165
void append_dim(int size, const string &name="")
Add a dimension of a given size.
Definition Array.cc:504
std::vector< dimension >::iterator Dim_iter
Definition Array.h:235
void rename_dim(const string &oldName="", const string &newName="")
Renames dimension.
Definition Array.cc:560
std::vector< BaseType * > * transform_to_dap2(AttrTable *parent_attr_table) override
Transforms this instance of a D4Array into the corresponding DAP2 object.
Definition Array.cc:287
virtual int dimension_size(Dim_iter i, bool constrained=false)
Returns the size of the dimension.
Definition Array.cc:752
void clear_all_dims()
Definition Array.cc:553
std::vector< dimension >::const_iterator Dim_citer
Definition Array.h:227
void add_var(BaseType *v, Part p=nil) override
Add the BaseType pointer to this constructor type instance.
Definition Array.cc:456
uint64_t print_array(FILE *out, uint64_t index, unsigned int dims, uint64_t shape[])
Print the value given the current constraint.
Definition Array.cc:1214
virtual void print_as_map_xml(ostream &out, string space=" ", bool constrained=false)
Definition Array.cc:1121
void print_xml_writer(XMLWriter &xml, bool constrained=false) override
Definition Array.cc:1145
virtual void reset_constraint()
Reset constraint to select entire array.
Definition Array.cc:578
void set_var_storage_info(const var_storage_info &my_vs_info)
Set the variable storage information for direct IO optimization.
Definition Array.cc:1409
virtual ~Array()
The Array destructor.
Definition Array.cc:163
virtual void print_xml_core(FILE *out, string space, bool constrained, string tag)
Definition Array.cc:1130
void prepend_dim(int size, const string &name="")
Definition Array.cc:534
Dim_iter dim_begin()
Definition Array.cc:718
void transform_to_dap4(D4Group *root, Constructor *container) override
DAP2 to DAP4 transform.
Definition Array.cc:175
Array(const string &n, BaseType *v, bool is_dap4=false)
Array constructor.
Definition Array.cc:133
bool check_semantics(string &msg, bool all=false) override
Check semantic features of the Array.
Definition Array.cc:1319
virtual unsigned int dimensions(bool constrained=false)
Return the total number of dimensions in the array.
Definition Array.cc:733
virtual int dimension_stride(Dim_iter i, bool constrained=false)
Returns the stride value of the constraint.
Definition Array.cc:841
Contains the attributes for a dataset.
Definition AttrTable.h:150
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
Definition AttrTable.cc:517
virtual void set_name(const string &n)
Set the name of this attribute table.
Definition AttrTable.cc:247
virtual string get_name() const
Get the name of this attribute table.
Definition AttrTable.cc:243
void print_xml_writer(XMLWriter &xml)
virtual void print(FILE *out, string pad=" ", bool dereference=false)
Prints the attribute table.
virtual unsigned int get_size() const
Get the number of entries in this attribute table.
Definition AttrTable.cc:239
The basic data type for the DODS DAP types.
Definition BaseType.h:118
virtual string type_name() const
Returns the type of the class instance as a string.
Definition BaseType.cc:335
virtual AttrTable & get_attr_table()
Definition BaseType.cc:498
virtual string name() const
Returns the name of the class instance.
Definition BaseType.cc:296
virtual void print_decl(FILE *out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Print an ASCII representation of the variable structure.
Definition BaseType.cc:868
virtual unsigned int width(bool constrained=false) const
How many bytes does this variable use Return the number of bytes of storage this variable uses....
Definition BaseType.cc:1138
virtual bool is_constructor_type() const
Returns true if the instance is a constructor (i.e., Structure, Sequence or Grid) type variable.
Definition BaseType.cc:358
virtual D4Attributes * attributes()
Definition BaseType.cc:507
virtual std::string FQN() const
Definition BaseType.cc:304
virtual bool send_p()
Should this variable be sent?
Definition BaseType.cc:478
virtual int length() const
How many elements are in this variable? Uses -1 in places.
Definition BaseType.h:207
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition BaseType.cc:1056
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition BaseType.cc:124
virtual Type type() const
Returns the type of the class instance.
Definition BaseType.cc:329
void add_var_nocopy(BaseType *bt, Part part=nil) override
Vars_iter var_begin()
void transform_to_dap4(AttrTable &at)
copy attributes from DAP2 to DAP4
void transform_attrs_to_dap2(AttrTable *d2_attr_table)
Copy the attributes from this D4Attributes object to a DAP2 AttrTable.
bool has_dap4_types(const std::string &path, std::vector< std::string > &inventory) const
vector< D4Dimension * >::iterator D4DimensionsIter
Iterator used for D4Dimensions.
void add_dim_nocopy(D4Dimension *dim)
D4DimensionsIter dim_end()
Get an iterator to the end of the dimensions.
D4DimensionsIter dim_begin()
Get an iterator to the start of the dimensions.
Holds a DAP4 enumeration.
Definition D4Enum.h:53
D4Dimensions * dims()
Get the dimensions defined for this Group.
Definition D4Group.h:84
Array * array(D4Group *root)
This will always return the correct pointer for a valid data set.
Definition D4Maps.cc:36
A class for error processing.
Definition Error.h:92
Holds the Grid data type.
Definition Grid.h:121
virtual void set_array(Array *p_new_arr)
Definition Grid.cc:344
virtual Array * add_map(Array *p_new_map, bool add_copy)
Definition Grid.cc:406
A class for software fault reporting.
Definition InternalErr.h:61
void dump(ostream &strm) const override
dumps information about this object
Definition Vector.cc:2452
void add_var(BaseType *v, Part p=nil) override
Add the BaseType pointer to this constructor type instance.
Definition Vector.cc:2351
int length() const override
Returns the number of elements in the vector. Note that some child classes of Vector use the length o...
Definition Vector.h:210
void set_length_ll(int64_t l) override
Set the number of elements in this Vector/Array This version of the function deprecates set_length() ...
Definition Vector.cc:432
BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=nullptr) override
Definition Vector.cc:469
Vector(const string &n, BaseType *v, const Type &t, bool is_dap4=false)
The Vector constructor.
Definition Vector.cc:254
void set_length(int64_t l) override
Sets the length of the vector. This function does not allocate any new space.
Definition Vector.cc:423
top level DAP object to house generic methods
Definition AISConnect.cc:30
Type
Identifies the data type.
Definition Type.h:94
string get_dims_decl(Array &a)
Definition Array.cc:1334
string www2id(const string &in, const string &escape, const string &except)
Definition escaping.cc:202
Part
Names the parts of multi-section constructor data types.
Definition Type.h:48
string id2www(string in, const string &allowable)
Definition escaping.cc:143
int64_t start
The constraint start index.
Definition Array.h:155
int64_t stride
The constraint stride.
Definition Array.h:157
string name
The name of this dimension.
Definition Array.h:143
int64_t size
The unconstrained dimension size.
Definition Array.h:142
int64_t stop
The constraint end index.
Definition Array.h:156
bool use_sdim_for_slice
Used to control printing the DMR in data responses.
Definition Array.h:153
int64_t c_size
Size of dimension once constrained.
Definition Array.h:158