libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
Array.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) 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#include <functional>
38#include <sstream>
39
40#include "Array.h"
41#include "Grid.h"
42
43#include "D4Dimensions.h"
44#include "D4Enum.h"
45#include "D4EnumDefs.h"
46#include "D4Group.h"
47#include "D4Maps.h"
48#include "DMR.h"
49#include "XMLWriter.h"
50
51#include "DapIndent.h"
52#include "InternalErr.h"
53#include "debug.h"
54#include "escaping.h"
55
56using namespace std;
57
58namespace libdap {
59
60// This constructor is defined here so that D4Dimensions.h does not need to be included in Array.h
63
64void Array::_duplicate(const Array &a) {
65 _shape = a._shape;
66
67 // Deep copy the Maps if they are being used.
68 if (a.d_maps) {
69 d_maps = new D4Maps(*a.d_maps, this);
70 } else {
71 d_maps = nullptr;
72 }
73}
74
75// The first method of calculating length works when only one dimension is
76// constrained, and you want the others to appear in the total. This is important
77// when selecting from grids since users may not select from all dimensions
78// in which case that means they want the whole thing. Array projection
79// should probably work this way too, but it doesn't. 9/21/2001 jhrg
80
88 uint64_t length = 1;
89 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
90 length *= (*i).c_size;
91 }
92
94}
95
96void Array::update_length_ll(unsigned long long) {
97 unsigned long long length = 1;
98 for (const auto &i : _shape) {
99 length *= i.c_size;
100 }
101
103}
104// Construct an instance of Array. The (BaseType *) is assumed to be
105// allocated using new - The dtor for Vector will delete this object.
106
121Array::Array(const string &n, BaseType *v, bool is_dap4 /* default:false */)
122 : Vector(n, nullptr, dods_array_c, is_dap4) {
124 if (v)
126}
127
140Array::Array(const string &n, const string &d, BaseType *v, bool is_dap4 /* default:false */)
141 : Vector(n, d, nullptr, dods_array_c, is_dap4) {
143 if (v)
145}
146
148Array::Array(const Array &rhs) : Vector(rhs) { _duplicate(rhs); }
149
151Array::~Array() { delete d_maps; }
152
153BaseType *Array::ptr_duplicate() { return new Array(*this); }
154
156 if (this == &rhs)
157 return *this;
159 _duplicate(rhs);
160 return *this;
161}
162
164 Array *dest = static_cast<Array *>(ptr_duplicate());
165
166 // If it's already a DAP4 object then we can just return it!
167 if (is_dap4()) {
168 container->add_var_nocopy(dest);
169 }
170
171 // Process the Array's dimensions, making D4 shared dimensions for
172 // D2 dimensions that are named. If there is just a size, don't make
173 // a D4Dimension (In DAP4 you cannot share a dimension unless it has
174 // a name). jhrg 3/18/14
175
176 D4Dimensions *root_dims = root->dims();
177 for (Array::Dim_iter dap2_dim = dest->dim_begin(), e = dest->dim_end(); dap2_dim != e; ++dap2_dim) {
178 if (!(*dap2_dim).name.empty()) {
179
180 // If a D4Dimension with the name already exists, use it.
181 D4Dimension *d4_dim = root_dims->find_dim((*dap2_dim).name);
182 if (!d4_dim) {
183 d4_dim = new D4Dimension((*dap2_dim).name, (*dap2_dim).size);
184 root_dims->add_dim_nocopy(d4_dim);
185 } else {
186 DBG(cerr << __func__ << "() -" << " Using Existing D4Dimension '" << d4_dim->name() << "' ("
187 << (void *)d4_dim << ")" << endl);
188
189 if (d4_dim->size() != (unsigned long)(*dap2_dim).size) {
190 // TODO Revisit this decision. jhrg 3/18/14
191 // ...in case the name/size are different, make a unique D4Dimension
192 // but don't fiddle with the name. Not sure I like this idea, so I'm
193 // making the case explicit (could be rolled in to the block above).
194 // jhrg 3/18/14
195 //
196 // This is causing problems in the FITS handler because there are cases
197 // where two arrays have dimensions with the same name but different
198 // sizes. The deserializing code is using the first size listed, which is
199 // wrong in some cases. I'm going to try making this new D4Dimension using
200 // the dim name along with the variable name. jhrg 8/15/14
201 d4_dim = new D4Dimension((*dap2_dim).name + "_" + name(), (*dap2_dim).size);
202 DBG(cerr << __func__ << "() -" << " Utilizing Name/Size Conflict Naming Artifice. name'"
203 << d4_dim->name() << "' (" << (void *)d4_dim << ")" << endl);
204 root_dims->add_dim_nocopy(d4_dim);
205 }
206 }
207 // At this point d4_dim's name and size == those of (*d) so just set
208 // the D4Dimension pointer so it matches the one in the D4Group.
209 (*dap2_dim).dim = d4_dim;
210 }
211 }
212
213 // Copy the D2 attributes to D4 Attributes
215 dest->set_is_dap4(true);
216 container->add_var_nocopy(dest);
217 DBG(cerr << __func__ << "() - END (array:" << name() << ")" << endl);
218}
219
221 bool is_grid = false;
222 if (this->is_dap4()) {
223 DBG(cerr << __func__ << "() - Array '" << name() << "' is DAP4 object!" << endl);
224 auto root = dynamic_cast<D4Group *>(this->get_ancestor());
225 if (!root)
226 throw InternalErr(__FILE__, __LINE__, string("Could not get the root group for ").append(this->name()));
227 D4Maps *d4_maps = this->maps();
228 is_grid = d4_maps->size(); // It can't be a grid if there are no maps...
229 if (is_grid) {
230 DBG(cerr << __func__ << "() - Array '" << name() << "' has D4Maps." << endl);
231 // hmmm this might be a DAP2 Grid...
232 D4Maps::D4MapsIter i = d4_maps->map_begin();
233 D4Maps::D4MapsIter e = d4_maps->map_end();
234 while (i != e) {
235 DBG(cerr << __func__ << "() - Map '" << (*i)->array()->name() << " has " << (*i)->array()->_shape.size()
236 << " dimension(s)." << endl);
237 if ((*i)->array(root)->_shape.size() > 1) {
238 is_grid = false;
239 i = e;
240 } else {
241 i++;
242 }
243 }
244 } else {
245 DBG(cerr << __func__ << "() - Array '" << name() << "' has no D4Maps." << endl);
246 }
247 }
248
249 DBG(cerr << __func__ << "() - is_grid: " << (is_grid ? "true" : "false") << endl);
250 return is_grid;
251}
252
268std::vector<BaseType *> *Array::transform_to_dap2(AttrTable *) {
269 DBG(cerr << __func__ << "() - BEGIN Array '" << name() << "'" << endl);
270
271 BaseType *dest;
272 if (!is_dap4()) { // Don't convert a DAP2 thing
273 dest = ptr_duplicate();
274 } else {
275 // At this point we have a DAP4 Array. It have D4Attributes and nothing
276 // in the DAP2 AttrTable (which is held as a reference, defined in BaseType).
277 // This test determines in the D4 Array qualifies as a D2 Grid.
278 if (is_dap2_grid()) {
279 // Oh yay! Grids are special.
280 DBG(cerr << __func__ << "() - Array '" << name() << "' is dap2 Grid!" << endl);
281 ;
282 Grid *g = new Grid(name());
283 dest = g;
284 Array *grid_array = static_cast<Array *>(ptr_duplicate());
285 grid_array->set_is_dap4(false);
286 g->set_array(grid_array);
287
288 // Fix for HK-403. jhrg 6/17/19
290
291 // Process the Map Arrays.
292 auto root = dynamic_cast<D4Group *>(this->get_ancestor());
293 if (!root)
294 throw InternalErr(__FILE__, __LINE__, string("Could not get the root group for ").append(this->name()));
295 D4Maps *d4_maps = this->maps();
296 vector<BaseType *> dropped_maps;
297 D4Maps::D4MapsIter miter = d4_maps->map_begin();
298 D4Maps::D4MapsIter end = d4_maps->map_end();
299 for (; miter != end; miter++) {
300 D4Map *d4_map = (*miter);
301 Array *d4_map_array = const_cast<Array *>(d4_map->array(root));
302 vector<BaseType *> *d2_result = d4_map_array->transform_to_dap2(&(g->get_attr_table()));
303 if (d2_result) {
304 if (d2_result->size() > 1)
305 throw Error(internal_error, "D4Map Array conversion resulted in multiple DAP2 objects.");
306
307 // TODO - This is probably slow and needs a better pattern. const_cast? static_cast?
308 Array *d2_map_array = dynamic_cast<Array *>((*d2_result)[0]);
309 if (d2_map_array) {
310 if (d2_map_array->dimensions() != 1)
311 throw Error(internal_error,
312 "DAP2 array from D4Map Array conversion has more than 1 dimension.");
313
314 d2_map_array->set_is_dap4(false);
315 g->add_map(d2_map_array, false);
316 AttrTable at = d2_map_array->get_attr_table();
317 DBG(cerr << __func__ << "() - " << "DAS For Grid Map '" << d2_map_array->name() << "':" << endl;
318 at.print(cerr););
319 } else {
320 throw Error(internal_error, "Unable to interpret returned DAP2 content.");
321 }
322 delete d2_result;
323 } else {
324 dropped_maps.push_back(d4_map_array);
325 }
326 }
327
328 // Did we have a transform failure?
329 if (!dropped_maps.empty()) {
330 // Yup... tell the story in the attributes.
331 AttrTable *dv_table = Constructor::make_dropped_vars_attr_table(&dropped_maps);
332 dest->get_attr_table().append_container(dv_table, dv_table->get_name());
333 }
334 } else {
335 DBG(cerr << __func__ << "() - Array '" << name() << "' is not a Grid!" << endl);
336
337 BaseType *proto = prototype();
338 switch (proto->type()) {
339 case dods_int64_c:
340 case dods_uint64_c:
341 case dods_enum_c:
342 case dods_opaque_c:
343 // For now we punt on these types as they have no easy representation in
344 // the DAP2 data model. By setting this to NULL we cause the Array to be
345 // dropped and this will be reflected in the metadata (DAS).
346 dest = NULL;
347 break;
348
349 default:
350 // ptr_duplicate() does the Attributes too.
351 dest = ptr_duplicate();
352
353 // Fix for HK-403. jhrg 6/17/19
354 // Only transform the DAP4 attributes to DAP2 ones if the DAP2 object lacks
355 // attributes. If the new DAP2 variable already has attributes, they were
356 // added by this process (driven by D4Group::transform_to_dap2() and calling
357 // attributes()->transform_to_dap2() will put a second copy of each attribute's
358 // value in the DAP2 AttrTable. This attribute transform code (here and elsewhere)
359 // depends on the AttrTable for a DAP4 variable initially being empty. Once it
360 // contains attributes, the code assumes they were put there by this transform
361 // process. jhrg 6/18/19
362 if (dest->get_attr_table().get_size() == 0) {
364 dest->get_attr_table().set_name(name());
365 }
366
367 dest->set_is_dap4(false);
368 break;
369 }
370 }
371 }
372
373 vector<BaseType *> *result = nullptr;
374 if (dest) {
375 result = new vector<BaseType *>();
376 result->push_back(dest);
377 }
378
379 DBG(cerr << __func__ << "() - END Array '" << name() << "'" << endl);
380 return result;
381}
382
394void Array::update_dimension_pointers(D4Dimensions *old_dims, D4Dimensions *new_dims) {
395 std::vector<dimension>::iterator i = _shape.begin(), e = _shape.end();
396 while (i != e) {
397 D4Dimensions::D4DimensionsIter old_i = old_dims->dim_begin(), old_e = old_dims->dim_end();
398 while (old_i != old_e) {
399 if ((*i).dim == *old_i) {
400 (*i).dim = new_dims->find_dim((*old_i)->name());
401 }
402 ++old_i;
403 }
404
405 ++i;
406 }
407}
408
432
434 // If 'v' is an Array, add the template instance to this object and
435 // then copy the dimension information. Odd semantics; I wonder if this
436 // is ever used. jhrg 6/13/12
437 if (v && v->type() == dods_array_c) {
438 Array *a = static_cast<Array *>(v);
439 Vector::add_var(a->var());
440
441 Dim_iter i = a->dim_begin();
442 Dim_iter i_end = a->dim_end();
443 while (i != i_end) {
445 ++i;
446 }
447 } else {
449 }
450}
451
453 // If 'v' is an Array, add the template instance to this object and
454 // then copy the dimension information. Odd semantics; I wonder if this
455 // is ever used. jhrg 6/13/12
456 if (v && v->type() == dods_array_c) {
457 Array &a = dynamic_cast<Array &>(*v);
459 Dim_iter i = a.dim_begin();
460 Dim_iter i_end = a.dim_end();
461 while (i != i_end) {
463 ++i;
464 }
465 } else {
467 }
468}
469
481void Array::append_dim(int size, const string &name) {
482 dimension d(size, www2id(name));
483 _shape.push_back(d);
484
486}
487
488void Array::append_dim_ll(int64_t size, const string &name) {
489 _shape.emplace_back(size, www2id(name));
491}
492
494 dimension d(/*dim->size(), www2id(dim->name()),*/ dim);
495 _shape.push_back(d);
496
498}
499
505void Array::prepend_dim(int size, const string &name /* = "" */) {
506 dimension d(size, www2id(name));
507 // Shifts the whole array, but it's tiny in general
508 _shape.insert(_shape.begin(), d);
509
510 update_length(); // the number is ignored...
511}
512
514 dimension d(/*dim->size(), www2id(dim->name()),*/ dim);
515 // Shifts the whole array, but it's tiny in general
516 _shape.insert(_shape.begin(), d);
517
518 update_length(); // the number is ignored...
519}
520
524void Array::clear_all_dims() { _shape.clear(); }
525
530
531void Array::rename_dim(const string &oldName, const string &newName) {
532 std::vector<dimension>::iterator i = _shape.begin(), e = _shape.end();
533 while (i != e) {
534 dimension &d = *i;
535 if (d.name == oldName) {
536 DBG(cerr << "Old name = " << d.name << " newName = " << newName << endl);
537 d.name = newName;
538 }
539
540 ++i;
541 }
542}
543
550 set_length(-1);
551
552 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
553 (*i).start = 0;
554 (*i).stop = (*i).size - 1;
555 (*i).stride = 1;
556 (*i).c_size = (*i).size;
557
559 }
560}
561
572
573// Note: MS VC++ won't tolerate embedded newlines in strings, hence the \n
574// is explicit.
575static const char *array_sss = "Invalid constraint parameters: At least one of the start, stride or stop \n\
576specified do not match the array variable.";
577
598void Array::add_constraint(Dim_iter i, int start, int stride, int stop) {
599 dimension &d = *i;
600
601 DBG(cerr << "add_constraint: d_size = " << d.size << endl);
602 DBG(cerr << "add_constraint: start = " << start << endl);
603 DBG(cerr << "add_constraint: stop = " << stop << endl);
604 DBG(cerr << "add_constraint: stride = " << stride << endl);
605
606 // if stop is -1, set it to the array's max element index
607 // jhrg 12/20/12
608 // Check if d.size is greater than INT_MAX, if yes, the following block needs to be re-worked. STOP
609 if (stop == -1) {
610 if (d.size > DODS_INT_MAX) {
611 // The total size of this dimension is greater than the maximum 32-bit integer.
612 throw Error(malformed_expr, "The dimension size is too large. use add_constraint_ll()");
613 } else
614 stop = d.size - 1;
615 }
616
617 // Check for bad constraints.
618 // Jose Garcia
619 // Usually invalid data for a constraint is the user's mistake
620 // because they build a wrong URL in the client side.
621 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0)
622 throw Error(malformed_expr, array_sss);
623
624 if (((stop - start) / stride + 1) > d.size)
625 throw Error(malformed_expr, array_sss);
626
627 d.start = start;
628 d.stop = stop;
629 d.stride = stride;
630
631 d.c_size = (stop - start) / stride + 1;
632
633 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
634
636
637 d.use_sdim_for_slice = false;
638}
639
640void Array::add_constraint_ll(Dim_iter i, int64_t start, int64_t stride, int64_t stop) {
641 dimension &d = *i;
642 DBG(cerr << "add_constraint_ll: d_size = " << d.size << endl);
643 DBG(cerr << "add_constraint_ll: start = " << start << endl);
644 DBG(cerr << "add_constraint_ll: stop = " << stop << endl);
645 DBG(cerr << "add_constraint_ll: stride = " << stride << endl);
646
647 // if stop is -1, set it to the array's max element index
648 // jhrg 12/20/12
649 if (stop == -1)
650 stop = d.size - 1;
651
652 // Check for bad constraints.
653 // Jose Garcia
654 // Usually invalid data for a constraint is the user's mistake
655 // because they build a wrong URL in the client side.
656 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0)
657 throw Error(malformed_expr, array_sss);
658
659 if (((stop - start) / stride + 1) > d.size)
660 throw Error(malformed_expr, array_sss);
661
662 d.start = start;
663 d.stop = stop;
664 d.stride = stride;
665
666 d.c_size = (stop - start) / stride + 1;
667
668 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
669
671
672 d.use_sdim_for_slice = false;
673}
675 dimension &d = *i;
676 DBG(cerr << "add_constraint d4dimension: stride = " << dim->c_stride() << endl);
677
678 if (dim->constrained())
679 add_constraint_ll(i, dim->c_start(), dim->c_stride(), dim->c_stop());
680
681 dim->set_used_by_projected_var(true);
682
683 // In this case the value below overrides the value for use_sdim_for_slice
684 // set in the above call. jhrg 12/20/13
685 d.use_sdim_for_slice = true;
686}
687
689Array::Dim_iter Array::dim_begin() { return _shape.begin(); }
690
692Array::Dim_iter Array::dim_end() { return _shape.end(); }
693
694// TODO Many of these methods take a bool parameter that serves no use; remove.
695
704unsigned int Array::dimensions(bool /*constrained*/) { return _shape.size(); }
705
723int Array::dimension_size(Dim_iter i, bool constrained) {
724 int size = 0;
725
726 if (!_shape.empty()) {
727 if (constrained) {
728 if ((*i).c_size > DODS_INT_MAX) {
729 throw Error(malformed_expr, "The dimension size is too large. Use dimension_size_ll()");
730 } else
731 size = (*i).c_size;
732 } else {
733 if ((*i).size > DODS_INT_MAX) {
734 throw Error(malformed_expr, "The dimension size is too large. Use dimension_size_ll()");
735 } else
736 size = (*i).size;
737 }
738 }
739
740 return size;
741}
742
761int Array::dimension_start(Dim_iter i, bool /*constrained*/) {
762 if ((*i).start > DODS_INT_MAX) {
763 throw Error(malformed_expr, "The dimension start value is too large. Use dimension_start_ll()");
764 }
765 return (!_shape.empty()) ? (*i).start : 0;
766}
767
786int Array::dimension_stop(Dim_iter i, bool /*constrained*/) {
787 if ((*i).stop > DODS_INT_MAX) {
788 throw Error(malformed_expr, "The dimension stop value is too large. Use dimension_stop_ll()");
789 }
790 return (!_shape.empty()) ? (*i).stop : 0;
791}
792
812int Array::dimension_stride(Dim_iter i, bool /*constrained*/) {
813 if ((*i).stride > DODS_INT_MAX) {
814 throw Error(malformed_expr, "The dimension stride value is too large. Use dimension_stride_ll()");
815 }
816 return (!_shape.empty()) ? (*i).stride : 0;
817}
818
819int64_t Array::dimension_size_ll(Dim_iter i, bool constrained) {
820 int64_t size = 0;
821
822 if (!_shape.empty()) {
823 if (constrained)
824 size = (*i).c_size;
825 else
826 size = (*i).size;
827 }
828 return size;
829}
830
831int64_t Array::dimension_start_ll(Dim_iter i, bool /*constrained*/) { return (!_shape.empty()) ? (*i).start : 0; }
832
833int64_t Array::dimension_stop_ll(Dim_iter i, bool /*constrained*/) { return (!_shape.empty()) ? (*i).stop : 0; }
834
835int64_t Array::dimension_stride_ll(Dim_iter i, bool /*constrained*/) { return (!_shape.empty()) ? (*i).stride : 0; }
836
848 // Jose Garcia
849 // Since this method is public, it is possible for a user
850 // to call it before the Array object has been properly set
851 // this will cause an exception which is the user's fault.
852 // (User in this context is the developer of the surrogate library.)
853 if (_shape.empty())
854 throw InternalErr(__FILE__, __LINE__, "*This* array has no dimensions.");
855 return (*i).name;
856}
857
858D4Dimension *Array::dimension_D4dim(Dim_iter i) { return (!_shape.empty()) ? (*i).dim : 0; }
859
861 if (!d_maps)
862 d_maps = new D4Maps(this); // init with this as parent
863 return d_maps;
864}
865
866void Array::print_dim_element(const XMLWriter &xml, const dimension &d, bool constrained) {
867 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar *)"Dim") < 0)
868 throw InternalErr(__FILE__, __LINE__, "Could not write Dim element");
869
870 string name = (d.dim) ? d.dim->fully_qualified_name() : d.name;
871 // If there is a name, there must be a Dimension (named dimension) in scope
872 // so write its name but not its size.
873 if (!constrained && !name.empty()) {
874 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name", (const xmlChar *)name.c_str()) < 0)
875 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
876 } else if (d.use_sdim_for_slice) {
877 assert(!name.empty());
878 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name", (const xmlChar *)name.c_str()) < 0)
879 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
880 } else {
881 ostringstream size;
882 size << (constrained ? d.c_size : d.size);
883 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"size",
884 (const xmlChar *)size.str().c_str()) < 0)
885 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
886 }
887
888 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
889 throw InternalErr(__FILE__, __LINE__, "Could not end Dim element");
890}
891
897void Array::print_dap4(XMLWriter &xml, bool constrained /* default: false*/) {
898 if (constrained && !send_p())
899 return;
900
901 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar *)var()->type_name().c_str()) < 0)
902 throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
903
904 if (!name().empty())
905 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name", (const xmlChar *)name().c_str()) < 0)
906 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
907
908 // Hack job... Copied from D4Enum::print_xml_writer. jhrg 11/12/13
909 if (var()->type() == dods_enum_c) {
910 D4Enum *e = static_cast<D4Enum *>(var());
911 string path = e->enumeration()->name();
912 if (e->enumeration()->parent()) {
913 // print the FQN for the enum def; D4Group::FQN() includes the trailing '/'
914 path = static_cast<D4Group *>(e->enumeration()->parent()->parent())->FQN() + path;
915 }
916 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"enum", (const xmlChar *)path.c_str()) < 0)
917 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for enum");
918 }
919
921 auto const &c = dynamic_cast<Constructor &>(*prototype());
922 for (auto var : c.variables()) {
923 var->print_dap4(xml, constrained);
924 }
925 }
926
927 for (auto const &d : shape()) {
928 print_dim_element(xml, d, constrained);
929 }
930
931 attributes()->print_dap4(xml);
932
933 auto print_d4_map = [&xml](D4Map *m) { m->print_dap4(xml); };
934
935 for_each(maps()->map_begin(), maps()->map_end(), print_d4_map);
936
937 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
938 throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
939}
940
958void Array::print_decl(FILE *out, string space, bool print_semi, bool constraint_info, bool constrained) {
959 ostringstream oss;
960 print_decl(oss, space, print_semi, constraint_info, constrained);
961 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
962}
963
981void Array::print_decl(ostream &out, string space, bool print_semi, bool constraint_info, bool constrained) {
982 if (constrained && !send_p())
983 return;
984
985 // print it, but w/o semicolon
986 var()->print_decl(out, space, false, constraint_info, constrained);
987
988 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
989 out << "[";
990 if ((*i).name != "") {
991 out << id2www((*i).name) << " = ";
992 }
993 if (constrained) {
994 out << (*i).c_size << "]";
995 } else {
996 out << (*i).size << "]";
997 }
998 }
999
1000 if (print_semi) {
1001 out << ";\n";
1002 }
1003}
1004
1008void Array::print_xml(FILE *out, string space, bool constrained) {
1009 XMLWriter xml(space);
1010 print_xml_writer_core(xml, constrained, "Array");
1011 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
1012}
1013
1017void Array::print_xml(ostream &out, string space, bool constrained) {
1018 XMLWriter xml(space);
1019 print_xml_writer_core(xml, constrained, "Array");
1020 out << xml.get_doc();
1021}
1022
1026void Array::print_as_map_xml(FILE *out, string space, bool constrained) {
1027 XMLWriter xml(space);
1028 print_xml_writer_core(xml, constrained, "Map");
1029 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
1030}
1031
1035void Array::print_as_map_xml(ostream &out, string space, bool constrained) {
1036 XMLWriter xml(space);
1037 print_xml_writer_core(xml, constrained, "Map");
1038 out << xml.get_doc();
1039}
1040
1044void Array::print_xml_core(FILE *out, string space, bool constrained, string tag) {
1045 XMLWriter xml(space);
1046 print_xml_writer_core(xml, constrained, tag);
1047 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
1048}
1049
1053void Array::print_xml_core(ostream &out, string space, bool constrained, string tag) {
1054 XMLWriter xml(space);
1055 print_xml_writer_core(xml, constrained, tag);
1056 out << xml.get_doc();
1057}
1058
1059void Array::print_xml_writer(XMLWriter &xml, bool constrained) { print_xml_writer_core(xml, constrained, "Array"); }
1060
1061void Array::print_as_map_xml_writer(XMLWriter &xml, bool constrained) {
1062 print_xml_writer_core(xml, constrained, "Map");
1063}
1064
1065void Array::print_xml_writer_core(XMLWriter &xml, bool constrained, string tag) {
1066 if (constrained && !send_p())
1067 return;
1068
1069 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar *)tag.c_str()) < 0)
1070 throw InternalErr(__FILE__, __LINE__, "Could not write " + tag + " element");
1071
1072 if (!name().empty() &&
1073 xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name", (const xmlChar *)name().c_str()) < 0)
1074 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1075
1077
1078 BaseType *btp = var();
1079 string tmp_name = btp->name();
1080 btp->set_name("");
1081 btp->print_xml_writer(xml, constrained);
1082 btp->set_name(tmp_name);
1083
1084 for (auto const &d : shape()) {
1085 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar *)"dimension") < 0)
1086 throw InternalErr(__FILE__, __LINE__, "Could not write dimension element");
1087
1088 if (!d.name.empty())
1089 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name",
1090 (const xmlChar *)d.name.c_str()) < 0)
1091 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1092
1093 ostringstream size;
1094 size << (constrained ? d.c_size : d.size);
1095 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"size",
1096 (const xmlChar *)size.str().c_str()) < 0)
1097 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1098
1099 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1100 throw InternalErr(__FILE__, __LINE__, "Could not end dimension element");
1101 }
1102
1103 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1104 throw InternalErr(__FILE__, __LINE__, "Could not end " + tag + " element");
1105}
1106
1118uint64_t Array::print_array(FILE *out, uint64_t index, unsigned int dims, uint64_t shape[]) {
1119 ostringstream oss;
1120 uint64_t i = print_array(oss, index, dims, shape);
1121 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1122
1123 return i;
1124}
1125
1137uint64_t Array::print_array(ostream &out, uint64_t index, unsigned int dims, uint64_t shape[]) {
1138 if (dims == 1) {
1139 out << "{";
1140
1141 // Added test in case this method is passed an array with no elements. jhrg 1/27/16
1142 if (shape[0] >= 1) {
1143 for (uint64_t i = 0; i < shape[0] - 1; ++i) {
1144 var_ll(index++)->print_val(out, "", false);
1145 out << ", ";
1146 }
1147 var_ll(index++)->print_val(out, "", false);
1148 }
1149
1150 out << "}";
1151
1152 return index;
1153 } else {
1154 out << "{";
1155 // Fixed an off-by-one error in the following loop. Since the array
1156 // length is shape[dims-1]-1 *and* since we want one less dimension
1157 // than that, the correct limit on this loop is shape[dims-2]-1. From
1158 // Todd Karakasian.
1159 //
1160 // The saga continues; the loop test should be `i < shape[0]-1'. jhrg
1161 // 9/12/96.
1162 //
1163 // For arrays that hold zero values but have rank > 1, the print out
1164 // may look a little odd (e.g., x[4][0] will print as { {}, {}, {}, {} })
1165 // but it's not wrong and this is really for debugging mostly. jhrg 1/28/16
1166 if (shape[0] > 0) {
1167 for (uint64_t i = 0; i < shape[0] - 1; ++i) {
1168 index = print_array(out, index, dims - 1, shape + 1);
1169 out << ",";
1170 }
1171
1172 index = print_array(out, index, dims - 1, shape + 1);
1173 }
1174
1175 out << "}";
1176
1177 return index;
1178 }
1179}
1180
1181void Array::print_val(FILE *out, string space, bool print_decl_p) {
1182 ostringstream oss;
1183 print_val(oss, space, print_decl_p);
1184 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1185}
1186
1187void Array::print_val(ostream &out, string space, bool print_decl_p) {
1188 // print the declaration if print decl is true.
1189 // for each dimension,
1190 // for each element,
1191 // print the array given its shape, number of dimensions.
1192 // Add the `;'
1193
1194 if (print_decl_p) {
1195 print_decl(out, space, false, false, false);
1196 out << " = ";
1197 }
1198
1199 auto shape = new uint64_t[dimensions(true)];
1200 unsigned int index = 0;
1201 for (auto i = _shape.begin(); i != _shape.end() && index < dimensions(true); ++i)
1202 shape[index++] = dimension_size_ll(i, true);
1203
1204 print_array(out, 0, dimensions(true), shape);
1205
1206 delete[] shape;
1207 shape = nullptr;
1208
1209 if (print_decl_p) {
1210 out << ";\n";
1211 }
1212}
1213
1222
1223bool Array::check_semantics(string &msg, bool) {
1224 bool sem = BaseType::check_semantics(msg) && !_shape.empty();
1225
1226 if (!sem)
1227 msg = "An array variable must have dimensions";
1228
1229 return sem;
1230}
1231
1239 stringstream sqr_brkty_stuff;
1240 for (auto itr = a.dim_begin(); itr != a.dim_end(); itr++) {
1241 sqr_brkty_stuff << "[";
1242 string dim_name = a.dimension_name(itr);
1243 if (!dim_name.empty()) {
1244 sqr_brkty_stuff << dim_name << "=";
1245 }
1246 sqr_brkty_stuff << a.dimension_size_ll(itr, true) << "]";
1247 }
1248 return sqr_brkty_stuff.str();
1249}
1250
1257bool Array::is_dap4_projected(std::vector<std::string> &inventory) {
1258 bool has_projected_dap4 = false;
1259 if (send_p()) {
1260 if (prototype()->is_constructor_type()) {
1261 has_projected_dap4 =
1262 prototype()->is_dap4_projected(inventory) || attributes()->has_dap4_types(FQN(), inventory);
1263 } else {
1264 Type type = prototype()->type();
1265 has_projected_dap4 = (type == libdap::dods_int8_c) || (type == dods_uint64_c) || (type == dods_int64_c);
1266 if (has_projected_dap4) {
1267 inventory.emplace_back(prototype()->type_name() + " " + FQN() + get_dims_decl(*this));
1268 }
1269 has_projected_dap4 |= attributes()->has_dap4_types(FQN(), inventory);
1270 }
1271 }
1272 return has_projected_dap4;
1273}
1274
1283void Array::dump(std::ostream &strm) const {
1284 strm << DapIndent::LMarg << "Array::dump - (" << static_cast<const void *>(this) << ")\n";
1286 Vector::dump(strm);
1287
1288 strm << DapIndent::LMarg << "shape:\n";
1290
1291 unsigned int dim_num = 0;
1292 for (const auto &dim : _shape) {
1293 strm << DapIndent::LMarg << "dimension " << dim_num++ << ":\n";
1295
1296 auto print_attr = [&strm](const std::string &name, const auto &value) {
1297 strm << DapIndent::LMarg << name << ": " << value << '\n';
1298 };
1299
1300 print_attr("name", dim.name);
1301 print_attr("size", dim.size);
1302 print_attr("start", dim.start);
1303 print_attr("stop", dim.stop);
1304 print_attr("stride", dim.stride);
1305 print_attr("constrained size", dim.c_size);
1306
1308 }
1309
1312}
1313
1321
1322 vs_info.filter = my_vs_info.filter;
1323
1324 for (const auto &def_lev : my_vs_info.deflate_levels)
1325 vs_info.deflate_levels.push_back(def_lev);
1326
1327 for (const auto &chunk_dim : my_vs_info.chunk_dims)
1328 vs_info.chunk_dims.push_back(chunk_dim);
1329
1330 for (const auto &vci : my_vs_info.var_chunk_info) {
1331 var_chunk_info_t vci_t;
1332 vci_t.filter_mask = vci.filter_mask;
1333 vci_t.chunk_direct_io_offset = vci.chunk_direct_io_offset;
1334 vci_t.chunk_buffer_size = vci.chunk_buffer_size;
1335 for (const auto &chunk_coord : vci.chunk_coords)
1336 vci_t.chunk_coords.push_back(chunk_coord);
1337 vs_info.var_chunk_info.push_back(vci_t);
1338 }
1339}
1340
1341} // namespace libdap
#define internal_error
Internal server error (500)
Definition Error.h:63
#define malformed_expr
(400)
Definition Error.h:66
A multidimensional array of identical data types.
Definition Array.h:121
virtual void print_as_map_xml_writer(XMLWriter &xml, bool constrained)
Definition Array.cc:1061
void print_dap4(XMLWriter &xml, bool constrained=false) override
Print the DAP4 representation of an array.
Definition Array.cc:897
virtual int dimension_start(Dim_iter i, bool constrained=false)
Return the start index of a dimension.
Definition Array.cc:761
virtual void clear_constraint()
Clears the projection; add each projected dimension explicitly using add_constraint.
Definition Array.cc:571
virtual void add_constraint_ll(Dim_iter i, int64_t start, int64_t stride, int64_t stop)
Definition Array.cc:640
Dim_iter dim_end()
Definition Array.cc:692
bool is_dap2_grid()
Definition Array.cc:220
virtual int64_t dimension_start_ll(Dim_iter i, bool constrained=false)
Definition Array.cc:831
virtual int64_t dimension_stop_ll(Dim_iter i, bool constrained=false)
Definition Array.cc:833
virtual int dimension_stop(Dim_iter i, bool constrained=false)
Return the stop index of the constraint.
Definition Array.cc:786
void dump(ostream &strm) const override
dumps information about this object
Definition Array.cc:1283
virtual void update_length(int size=0)
Definition Array.cc:87
bool is_dap4_projected(std::vector< std::string > &projected_dap4_inventory) override
Definition Array.cc:1257
virtual void add_constraint(Dim_iter i, int start, int stride, int stop)
Adds a constraint to an Array dimension.
Definition Array.cc:598
virtual string dimension_name(Dim_iter i)
Returns the name of the specified dimension.
Definition Array.cc:847
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:981
friend class D4Group
Definition Array.h:200
virtual int64_t dimension_size_ll(Dim_iter i, bool constrained=false)
Definition Array.cc:819
void print_xml(ostream &out, string space=" ", bool constrained=false) override
Definition Array.cc:1017
void print_val(ostream &out, string space="", bool print_decl_p=true) override
Prints the value of the variable.
Definition Array.cc:1187
BaseType * ptr_duplicate() override
Definition Array.cc:153
void append_dim(int size, const string &name="")
Add a dimension of a given size.
Definition Array.cc:481
std::vector< dimension >::iterator Dim_iter
Definition Array.h:225
virtual D4Maps * maps()
Definition Array.cc:860
virtual D4Dimension * dimension_D4dim(Dim_iter i)
Definition Array.cc:858
void rename_dim(const string &oldName="", const string &newName="")
Renames dimension.
Definition Array.cc:531
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:268
std::vector< dimension > & shape()
Definition Array.h:209
virtual int dimension_size(Dim_iter i, bool constrained=false)
Returns the size of the dimension.
Definition Array.cc:723
void clear_all_dims()
Definition Array.cc:524
virtual void print_xml_writer_core(XMLWriter &out, bool constrained, string tag)
Definition Array.cc:1065
std::vector< dimension >::const_iterator Dim_citer
Definition Array.h:217
void add_var(BaseType *v, Part p=nil) override
Add the BaseType pointer to this constructor type instance.
Definition Array.cc:433
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:1118
virtual void print_as_map_xml(ostream &out, string space=" ", bool constrained=false)
Definition Array.cc:1035
void print_xml_writer(XMLWriter &xml, bool constrained=false) override
Definition Array.cc:1059
virtual void reset_constraint()
Reset constraint to select entire array.
Definition Array.cc:549
void set_var_storage_info(const var_storage_info &my_vs_info)
Set the variable storage information for direct IO optimization.
Definition Array.cc:1320
virtual ~Array()
The Array destructor.
Definition Array.cc:151
virtual void print_xml_core(FILE *out, string space, bool constrained, string tag)
Definition Array.cc:1044
void add_var_nocopy(BaseType *v, Part p=nil) override
Definition Array.cc:452
void append_dim_ll(int64_t size, const string &name="")
Definition Array.cc:488
void prepend_dim(int size, const string &name="")
Definition Array.cc:505
Dim_iter dim_begin()
Definition Array.cc:689
void transform_to_dap4(D4Group *root, Constructor *container) override
DAP2 to DAP4 transform.
Definition Array.cc:163
Array(const string &n, BaseType *v, bool is_dap4=false)
Array constructor.
Definition Array.cc:121
bool check_semantics(string &msg, bool all=false) override
Check semantic features of the Array.
Definition Array.cc:1223
virtual void update_length_ll(unsigned long long size=0)
Definition Array.cc:96
virtual unsigned int dimensions(bool constrained=false)
Return the total number of dimensions in the array.
Definition Array.cc:704
virtual int64_t dimension_stride_ll(Dim_iter i, bool constrained=false)
Definition Array.cc:835
void _duplicate(const Array &a)
Definition Array.cc:64
Array & operator=(const Array &rhs)
Definition Array.cc:155
virtual int dimension_stride(Dim_iter i, bool constrained=false)
Returns the stride value of the constraint.
Definition Array.cc:812
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 bool is_dap4_projected(std::vector< string > &projected_dap4_inventory)
Definition BaseType.cc:1148
virtual void print_xml_writer(XMLWriter &xml, bool constrained=false)
Definition BaseType.cc:987
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 bool is_dap4() const
Definition BaseType.h:181
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition BaseType.cc:314
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 void set_is_dap4(const bool v)
Definition BaseType.h:182
virtual BaseType * get_ancestor()
Definition BaseType.cc:638
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
virtual Type type() const
Returns the type of the class instance.
Definition BaseType.cc:329
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition BaseType.cc:949
static AttrTable * make_dropped_vars_attr_table(vector< BaseType * > *dropped_vars)
void add_var_nocopy(BaseType *bt, Part part=nil) override
void transform_to_dap4(AttrTable &at)
copy attributes from DAP2 to DAP4
void print_dap4(XMLWriter &xml) const
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
int64_t c_stop() const
unsigned long long size() const
string name() const
int64_t c_stride() const
void set_used_by_projected_var(bool state)
int64_t c_start() const
bool constrained() const
vector< D4Dimension * >::iterator D4DimensionsIter
Iterator used for D4Dimensions.
void add_dim_nocopy(D4Dimension *dim)
D4Dimension * find_dim(const string &name)
D4DimensionsIter dim_end()
Get an iterator to the end of the dimensions.
D4DimensionsIter dim_begin()
Get an iterator to the start of the dimensions.
D4EnumDefs * parent() const
Definition D4EnumDefs.h:87
string name() const
Definition D4EnumDefs.h:81
Holds a DAP4 enumeration.
Definition D4Enum.h:53
virtual D4EnumDef * enumeration() const
Definition D4Enum.h:112
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
int size() const
Definition D4Maps.h:179
D4MapsIter map_begin()
Definition D4Maps.h:176
vector< D4Map * >::iterator D4MapsIter
Definition D4Maps.h:118
D4MapsIter map_end()
Definition D4Maps.h:177
static ostream & LMarg(ostream &strm)
Definition DapIndent.cc:61
static void Indent()
Definition DapIndent.cc:44
static void UnIndent()
Definition DapIndent.cc:46
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:399
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
Vector & operator=(const Vector &rhs)
Definition Vector.cc:315
void add_var_nocopy(BaseType *v, Part p=nil) override
Definition Vector.cc:2391
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
virtual void value(dods_byte *b) const
Definition Vector.cc:2295
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
virtual BaseType * prototype() const
Definition Vector.h:163
Vector(const string &n, BaseType *v, const Type &t, bool is_dap4=false)
The Vector constructor.
Definition Vector.cc:254
virtual BaseType * var_ll(uint64_t i)
Definition Vector.cc:567
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
unsigned int get_doc_size()
Definition XMLWriter.cc:123
const char * get_doc()
Definition XMLWriter.cc:104
xmlTextWriterPtr get_writer() const
Definition XMLWriter.h:55
#define DBG(x)
Definition debug.h:58
#define DODS_INT_MAX
Definition dods-limits.h:73
top level DAP object to house generic methods
Definition AISConnect.cc:30
Type
Identifies the data type.
Definition Type.h:94
@ dods_int8_c
Definition Type.h:115
@ dods_int64_c
Definition Type.h:118
@ dods_uint64_c
Definition Type.h:119
@ dods_enum_c
Definition Type.h:120
@ dods_array_c
Definition Type.h:107
@ dods_opaque_c
Definition Type.h:121
string get_dims_decl(Array &a)
Definition Array.cc:1238
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
D4Dimension * dim
If not null, a weak pointer to the D4Dimension.
Definition Array.h:145
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
unsigned long long chunk_buffer_size
Definition Array.h:177
vector< unsigned long long > chunk_coords
Definition Array.h:178
unsigned long long chunk_direct_io_offset
Definition Array.h:176
vector< size_t > chunk_dims
Definition Array.h:184
vector< var_chunk_info_t > var_chunk_info
Definition Array.h:185
vector< unsigned int > deflate_levels
Definition Array.h:183