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 "DMR.h"
48#include "D4Dimensions.h"
49#include "D4Maps.h"
50#include "D4Group.h"
51#include "D4EnumDefs.h"
52#include "D4Enum.h"
53#include "XMLWriter.h"
54
55#include "util.h"
56#include "debug.h"
57#include "InternalErr.h"
58#include "escaping.h"
59#include "DapIndent.h"
60
61using namespace std;
62
63namespace libdap {
64
65Array::dimension::dimension(D4Dimension *d) :
66 dim(d), use_sdim_for_slice(true)
67{
68 size = d->size();
69 name = d->name();
70
71 start = 0;
72 stop = size - 1;
73 stride = 1;
74 c_size = size;
75}
76
77void Array::_duplicate(const Array &a)
78{
79 _shape = a._shape;
80
81 // Deep copy the Maps if they are being used.
82 if (a.d_maps) {
83 d_maps = new D4Maps(*a.d_maps, this);
84 }
85 else {
86 d_maps = nullptr;
87 }
88}
89
90// The first method of calculating length works when only one dimension is
91// constrained, and you want the others to appear in the total. This is important
92// when selecting from grids since users may not select from all dimensions
93// in which case that means they want the whole thing. Array projection
94// should probably work this way too, but it doesn't. 9/21/2001 jhrg
95
102void Array::update_length(int)
103{
104 uint64_t length = 1;
105 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
106 length *= (*i).c_size;
107 }
108
109 set_length_ll(length);
110}
111
112
113void Array::update_length_ll(unsigned long long)
114{
115 unsigned long long length = 1;
116 for (const auto &i:_shape) {
117 length *= i.c_size;
118 }
119
120 set_length_ll(length);
121}
122// Construct an instance of Array. The (BaseType *) is assumed to be
123// allocated using new - The dtor for Vector will delete this object.
124
139Array::Array(const string &n, BaseType *v, bool is_dap4 /* default:false */) :
140 Vector(n, nullptr, dods_array_c, is_dap4)
141{
143 if (v)
144 BaseType::set_is_dap4(v->is_dap4());
145}
146
159Array::Array(const string &n, const string &d, BaseType *v, bool is_dap4 /* default:false */) :
160 Vector(n, d, nullptr, dods_array_c, is_dap4)
161{
163 if (v)
164 BaseType::set_is_dap4(v->is_dap4());
165}
166
168Array::Array(const Array &rhs) :
169 Vector(rhs)
170{
171 _duplicate(rhs);
172}
173
176{
177 delete d_maps;
178}
179
180BaseType *
182{
183 return new Array(*this);
184}
185
186Array &
187Array::operator=(const Array &rhs)
188{
189 if (this == &rhs) return *this;
190 Vector::operator=(rhs);
191 _duplicate(rhs);
192 return *this;
193}
194
196{
197 Array *dest = static_cast<Array*>(ptr_duplicate());
198
199 // If it's already a DAP4 object then we can just return it!
200 if (is_dap4()) {
201 container->add_var_nocopy(dest);
202 }
203
204 // Process the Array's dimensions, making D4 shared dimensions for
205 // D2 dimensions that are named. If there is just a size, don't make
206 // a D4Dimension (In DAP4 you cannot share a dimension unless it has
207 // a name). jhrg 3/18/14
208
209 D4Dimensions *root_dims = root->dims();
210 for (Array::Dim_iter dap2_dim = dest->dim_begin(), e = dest->dim_end(); dap2_dim != e; ++dap2_dim) {
211 if (!(*dap2_dim).name.empty()) {
212
213 // If a D4Dimension with the name already exists, use it.
214 D4Dimension *d4_dim = root_dims->find_dim((*dap2_dim).name);
215 if (!d4_dim) {
216 d4_dim = new D4Dimension((*dap2_dim).name, (*dap2_dim).size);
217 root_dims->add_dim_nocopy(d4_dim);
218 }
219 else {
220 DBG(cerr << __func__ << "() -" <<
221 " Using Existing D4Dimension '"<< d4_dim->name() << "' (" <<
222 (void *)d4_dim << ")"<< endl);;
223
224 if (d4_dim->size() != (unsigned long) (*dap2_dim).size) {
225 // TODO Revisit this decision. jhrg 3/18/14
226 // ...in case the name/size are different, make a unique D4Dimension
227 // but don't fiddle with the name. Not sure I like this idea, so I'm
228 // making the case explicit (could be rolled in to the block above).
229 // jhrg 3/18/14
230 //
231 // This is causing problems in the FITS handler because there are cases
232 // where two arrays have dimensions with the same name but different
233 // sizes. The deserializing code is using the first size listed, which is
234 // wrong in some cases. I'm going to try making this new D4Dimension using
235 // the dim name along with the variable name. jhrg 8/15/14
236 d4_dim = new D4Dimension((*dap2_dim).name + "_" + name(), (*dap2_dim).size);
237 DBG(cerr << __func__ << "() -" <<
238 " Utilizing Name/Size Conflict Naming Artifice. name'"<< d4_dim->name() << "' (" <<
239 (void *)d4_dim << ")"<< endl);;
240 root_dims->add_dim_nocopy(d4_dim);
241 }
242 }
243 // At this point d4_dim's name and size == those of (*d) so just set
244 // the D4Dimension pointer so it matches the one in the D4Group.
245 (*dap2_dim).dim = d4_dim;
246 }
247
248 }
249
250 // Copy the D2 attributes to D4 Attributes
252 dest->set_is_dap4(true);
253 container->add_var_nocopy(dest);
254 DBG(cerr << __func__ << "() - END (array:" << name() << ")" << endl);;
255}
256
257bool Array::is_dap2_grid()
258{
259 bool is_grid = false;
260 if (this->is_dap4()) {
261 DBG( cerr << __func__ << "() - Array '"<< name() << "' is DAP4 object!" << endl);
262 auto root = dynamic_cast<D4Group*>(this->get_ancestor());
263 if (!root)
264 throw InternalErr(__FILE__, __LINE__, string("Could not get the root group for ").append(this->name()));
265 D4Maps *d4_maps = this->maps();
266 is_grid = d4_maps->size(); // It can't be a grid if there are no maps...
267 if (is_grid) {
268 DBG( cerr << __func__ << "() - Array '"<< name() << "' has D4Maps." << endl);
269 // hmmm this might be a DAP2 Grid...
270 D4Maps::D4MapsIter i = d4_maps->map_begin();
271 D4Maps::D4MapsIter e = d4_maps->map_end();
272 while (i != e) {
273 DBG( cerr << __func__ << "() - Map '"<< (*i)->array()->name() << " has " << (*i)->array()->_shape.size() << " dimension(s)." << endl);
274 if ((*i)->array(root)->_shape.size() > 1) {
275 is_grid = false;
276 i = e;
277 }
278 else {
279 i++;
280 }
281 }
282 }
283 else {
284 DBG( cerr << __func__ << "() - Array '"<< name() << "' has no D4Maps." << endl);
285 }
286 }
287
288 DBG( cerr << __func__ << "() - is_grid: "<< (is_grid?"true":"false") << endl);
289 return is_grid;
290}
291
307std::vector<BaseType *> *
309{
310 DBG(cerr << __func__ << "() - BEGIN Array '"<< name() << "'" << endl);;
311
312 BaseType *dest;
313 if (!is_dap4()) { // Don't convert a DAP2 thing
314 dest = ptr_duplicate();
315 }
316 else {
317 // At this point we have a DAP4 Array. It have D4Attributes and nothing
318 // in the DAP2 AttrTable (which is held as a reference, defined in BaseType).
319 // This test determines in the D4 Array qualifies as a D2 Grid.
320 if (is_dap2_grid()) {
321 // Oh yay! Grids are special.
322 DBG(cerr << __func__ << "() - Array '"<< name() << "' is dap2 Grid!" << endl);;
323 Grid *g = new Grid(name());
324 dest = g;
325 Array *grid_array = static_cast<Array *>(ptr_duplicate());
326 grid_array->set_is_dap4(false);
327 g->set_array(grid_array);
328
329 // Fix for HK-403. jhrg 6/17/19
331
332 // Process the Map Arrays.
333 auto root = dynamic_cast<D4Group*>(this->get_ancestor());
334 if (!root)
335 throw InternalErr(__FILE__, __LINE__, string("Could not get the root group for ").append(this->name()));
336 D4Maps *d4_maps = this->maps();
337 vector<BaseType *> dropped_maps;
338 D4Maps::D4MapsIter miter = d4_maps->map_begin();
339 D4Maps::D4MapsIter end = d4_maps->map_end();
340 for (; miter != end; miter++) {
341 D4Map *d4_map = (*miter);
342 Array *d4_map_array = const_cast<Array*>(d4_map->array(root));
343 vector<BaseType *> *d2_result = d4_map_array->transform_to_dap2(&(g->get_attr_table()));
344 if (d2_result) {
345 if (d2_result->size() > 1)
346 throw Error(internal_error, "D4Map Array conversion resulted in multiple DAP2 objects.");
347
348 // TODO - This is probably slow and needs a better pattern. const_cast? static_cast?
349 Array *d2_map_array = dynamic_cast<Array *>((*d2_result)[0]);
350 if (d2_map_array) {
351 if (d2_map_array->dimensions() != 1)
352 throw Error(internal_error, "DAP2 array from D4Map Array conversion has more than 1 dimension.");
353
354 d2_map_array->set_is_dap4(false);
355 g->add_map(d2_map_array, false);
356 AttrTable at = d2_map_array->get_attr_table();
357 DBG( cerr << __func__ << "() - " <<
358 "DAS For Grid Map '" << d2_map_array->name() << "':" << endl;
359 at.print(cerr); );
360 }
361 else {
362 throw Error(internal_error, "Unable to interpret returned DAP2 content.");
363 }
364 delete d2_result;
365 }
366 else {
367 dropped_maps.push_back(d4_map_array);
368 }
369 }
370
371 // Did we have a transform failure?
372 if (!dropped_maps.empty()) {
373 // Yup... tell the story in the attributes.
374 AttrTable *dv_table = Constructor::make_dropped_vars_attr_table(&dropped_maps);
375 dest->get_attr_table().append_container(dv_table, dv_table->get_name());
376 }
377 }
378 else {
379 DBG( cerr << __func__ << "() - Array '"<< name() << "' is not a Grid!" << endl);
380
381 BaseType *proto = prototype();
382 switch (proto->type()) {
383 case dods_int64_c:
384 case dods_uint64_c:
385 case dods_enum_c:
386 case dods_opaque_c:
387 // For now we punt on these types as they have no easy representation in
388 // the DAP2 data model. By setting this to NULL we cause the Array to be
389 // dropped and this will be reflected in the metadata (DAS).
390 dest = NULL;
391 break;
392
393 default:
394 // ptr_duplicate() does the Attributes too.
395 dest = ptr_duplicate();
396
397 // Fix for HK-403. jhrg 6/17/19
398 // Only transform the DAP4 attributes to DAP2 ones if the DAP2 object lacks
399 // attributes. If the new DAP2 variable already has attributes, they were
400 // added by this process (driven by D4Group::transform_to_dap2() and calling
401 // attributes()->transform_to_dap2() will put a second copy of each attribute's
402 // value in the DAP2 AttrTable. This attribute transform code (here and elsewhere)
403 // depends on the AttrTable for a DAP4 variable initially being empty. Once it
404 // contains attributes, the code assumes they were put there by this transform
405 // process. jhrg 6/18/19
406 if (dest->get_attr_table().get_size() == 0) {
408 dest->get_attr_table().set_name(name());
409 }
410
411 dest->set_is_dap4(false);
412 break;
413 }
414 }
415 }
416
417 vector<BaseType *> *result;
418 if (dest) {
419 result = new vector<BaseType *>();
420 result->push_back(dest);
421 }
422 else {
423 result = NULL;
424 }
425
426 DBG( cerr << __func__ << "() - END Array '"<< name() << "'" << endl);;
427 return result;
428}
429
441void Array::update_dimension_pointers(D4Dimensions *old_dims, D4Dimensions *new_dims)
442{
443 std::vector<dimension>::iterator i = _shape.begin(), e = _shape.end();
444 while (i != e) {
445 D4Dimensions::D4DimensionsIter old_i = old_dims->dim_begin(), old_e = old_dims->dim_end();
446 while (old_i != old_e) {
447 if ((*i).dim == *old_i) {
448 (*i).dim = new_dims->find_dim((*old_i)->name());
449 }
450 ++old_i;
451 }
452
453 ++i;
454 }
455}
456
482{
483// If 'v' is an Array, add the template instance to this object and
484// then copy the dimension information. Odd semantics; I wonder if this
485//is ever used. jhrg 6/13/12
486 if (v && v->type() == dods_array_c) {
487 Array *a = static_cast<Array*>(v);
488 Vector::add_var(a->var());
489
490 Dim_iter i = a->dim_begin();
491 Dim_iter i_end = a->dim_end();
492 while (i != i_end) {
494 ++i;
495 }
496 }
497 else {
499 }
500}
501
502void Array::add_var_nocopy(BaseType *v, Part)
503{
504// If 'v' is an Array, add the template instance to this object and
505// then copy the dimension information. Odd semantics; I wonder if this
506//is ever used. jhrg 6/13/12
507 if (v && v->type() == dods_array_c) {
508 Array &a = dynamic_cast<Array&>(*v);
509 Vector::add_var_nocopy(a.var());
510 Dim_iter i = a.dim_begin();
511 Dim_iter i_end = a.dim_end();
512 while (i != i_end) {
514 ++i;
515 }
516 }
517 else {
518 Vector::add_var_nocopy(v);
519 }
520}
521
533void Array::append_dim(int size, const string &name)
534{
535 dimension d(size, www2id(name));
536 _shape.push_back(d);
537
539}
540
541void Array::append_dim_ll(int64_t size, const string &name)
542{
543
544#if 0
545 dimension d(size, www2id(name));
546 _shape.push_back(d);
547#endif
548
549 _shape.emplace_back(size,www2id(name));
551}
552
553void Array::append_dim(D4Dimension *dim)
554{
555 dimension d(/*dim->size(), www2id(dim->name()),*/dim);
556 _shape.push_back(d);
557
559}
560
566void Array::prepend_dim(int size, const string& name/* = "" */)
567{
568 dimension d(size, www2id(name));
569// Shifts the whole array, but it's tiny in general
570 _shape.insert(_shape.begin(), d);
571
572 update_length(); // the number is ignored...
573}
574
576{
577 dimension d(/*dim->size(), www2id(dim->name()),*/dim);
578// Shifts the whole array, but it's tiny in general
579 _shape.insert(_shape.begin(), d);
580
581 update_length(); // the number is ignored...
582}
583
588{
589 _shape.clear();
590}
591
597void Array::rename_dim(const string &oldName, const string &newName)
598{
599 std::vector<dimension>::iterator i = _shape.begin(), e = _shape.end();
600 while (i != e) {
601 dimension &d = *i;
602 if (d.name == oldName) {
603 DBG(cerr << "Old name = " << d.name << " newName = " << newName << endl);
604 d.name = newName;
605 }
606
607 ++i;
608 }
609}
610
617{
618 set_length(-1);
619
620 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
621 (*i).start = 0;
622 (*i).stop = (*i).size - 1;
623 (*i).stride = 1;
624 (*i).c_size = (*i).size;
625
627 }
628}
629
643
644// Note: MS VC++ won't tolerate embedded newlines in strings, hence the \n
645// is explicit.
646static const char *array_sss =
647 "Invalid constraint parameters: At least one of the start, stride or stop \n\
648specified do not match the array variable.";
649
670void Array::add_constraint(Dim_iter i, int start, int stride, int stop)
671{
672 dimension &d = *i;
673
674 DBG(cerr << "add_constraint: d_size = " << d.size << endl);
675 DBG(cerr << "add_constraint: start = " << start << endl);
676 DBG(cerr << "add_constraint: stop = " << stop << endl);
677 DBG(cerr << "add_constraint: stride = " << stride << endl);
678
679// if stop is -1, set it to the array's max element index
680// jhrg 12/20/12
681 // Check if d.size is greater than INT_MAX, if yes, the following block needs to be re-worked. STOP
682 if (stop == -1) {
683 if (d.size >DODS_INT_MAX) {
684 // The total size of this dimension is greater than the maximum 32-bit integer.
685 throw Error(malformed_expr,
686 "The dimension size is too large. use add_constraint_ll()");
687 }
688 else
689 stop = d.size - 1;
690 }
691
692// Check for bad constraints.
693// Jose Garcia
694// Usually invalid data for a constraint is the user's mistake
695// because they build a wrong URL in the client side.
696 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0) throw Error(malformed_expr, array_sss);
697
698 if (((stop - start) / stride + 1) > d.size) throw Error(malformed_expr, array_sss);
699
700 d.start = start;
701 d.stop = stop;
702 d.stride = stride;
703
704 d.c_size = (stop - start) / stride + 1;
705
706 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
707
709
710 d.use_sdim_for_slice = false;
711}
712
713void Array::add_constraint_ll(Dim_iter i, int64_t start, int64_t stride, int64_t stop)
714{
715 dimension &d = *i;
716 DBG(cerr << "add_constraint_ll: d_size = " << d.size << endl);
717 DBG(cerr << "add_constraint_ll: start = " << start << endl);
718 DBG(cerr << "add_constraint_ll: stop = " << stop << endl);
719 DBG(cerr << "add_constraint_ll: stride = " << stride << endl);
720
721
722
723// if stop is -1, set it to the array's max element index
724// jhrg 12/20/12
725 if (stop == -1) stop = d.size - 1;
726
727// Check for bad constraints.
728// Jose Garcia
729// Usually invalid data for a constraint is the user's mistake
730// because they build a wrong URL in the client side.
731 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0) throw Error(malformed_expr, array_sss);
732
733 if (((stop - start) / stride + 1) > d.size) throw Error(malformed_expr, array_sss);
734
735 d.start = start;
736 d.stop = stop;
737 d.stride = stride;
738
739 d.c_size = (stop - start) / stride + 1;
740
741 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
742
744
745 d.use_sdim_for_slice = false;
746}
747void Array::add_constraint(Dim_iter i, D4Dimension *dim)
748{
749 dimension &d = *i;
750 DBG(cerr << "add_constraint d4dimension: stride = " << dim->c_stride() << endl);
751
752 if (dim->constrained()) add_constraint_ll(i, dim->c_start(), dim->c_stride(), dim->c_stop());
753
754 dim->set_used_by_projected_var(true);
755
756// In this case the value below overrides the value for use_sdim_for_slice
757// set in the above call. jhrg 12/20/13
758 d.use_sdim_for_slice = true;
759}
760
763{
764 return _shape.begin();
765}
766
769{
770 return _shape.end();
771}
772
773//TODO Many of these methods take a bool parameter that serves no use; remove.
774
783unsigned int Array::dimensions(bool /*constrained*/)
784{
785 return _shape.size();
786}
787
805int Array::dimension_size(Dim_iter i, bool constrained)
806{
807 int size = 0;
808
809 if (!_shape.empty()) {
810 if (constrained) {
811 if ((*i).c_size >DODS_INT_MAX) {
812 throw Error(malformed_expr,
813 "The dimension size is too large. Use dimension_size_ll()");
814 }
815 else
816 size = (*i).c_size;
817 }
818 else {
819 if ((*i).size >DODS_INT_MAX) {
820 throw Error(malformed_expr,
821 "The dimension size is too large. Use dimension_size_ll()");
822 }
823 else
824 size = (*i).size;
825 }
826 }
827
828 return size;
829}
830
849int Array::dimension_start(Dim_iter i, bool /*constrained*/)
850{
851 if ((*i).start > DODS_INT_MAX) {
852 throw Error(malformed_expr,
853 "The dimension start value is too large. Use dimension_start_ll()");
854 }
855 return (!_shape.empty()) ? (*i).start : 0;
856}
857
876int Array::dimension_stop(Dim_iter i, bool /*constrained*/)
877{
878 if ((*i).stop > DODS_INT_MAX) {
879 throw Error(malformed_expr,
880 "The dimension stop value is too large. Use dimension_stop_ll()");
881 }
882 return (!_shape.empty()) ? (*i).stop : 0;
883}
884
904int Array::dimension_stride(Dim_iter i, bool /*constrained*/)
905{
906 if ((*i).stride > DODS_INT_MAX) {
907 throw Error(malformed_expr,
908 "The dimension stride value is too large. Use dimension_stride_ll()");
909 }
910 return (!_shape.empty()) ? (*i).stride : 0;
911}
912
913int64_t Array::dimension_size_ll(Dim_iter i, bool constrained)
914{
915 int64_t size = 0;
916
917 if (!_shape.empty()) {
918 if (constrained)
919 size = (*i).c_size;
920 else
921 size = (*i).size;
922 }
923 return size;
924}
925
926int64_t Array::dimension_start_ll(Dim_iter i, bool /*constrained*/)
927{
928 return (!_shape.empty()) ? (*i).start : 0;
929}
930
931int64_t Array::dimension_stop_ll(Dim_iter i, bool /*constrained*/)
932{
933 return (!_shape.empty()) ? (*i).stop : 0;
934}
935
936int64_t Array::dimension_stride_ll(Dim_iter i, bool /*constrained*/)
937{
938 return (!_shape.empty()) ? (*i).stride : 0;
939}
940
952{
953// Jose Garcia
954// Since this method is public, it is possible for a user
955// to call it before the Array object has been properly set
956// this will cause an exception which is the user's fault.
957// (User in this context is the developer of the surrogate library.)
958 if (_shape.empty()) throw InternalErr(__FILE__, __LINE__, "*This* array has no dimensions.");
959 return (*i).name;
960}
961
963Array::dimension_D4dim(Dim_iter i)
964{
965 return (!_shape.empty()) ? (*i).dim : 0;
966}
967
968D4Maps *
969Array::maps()
970{
971 if (!d_maps) d_maps = new D4Maps(this); // init with this as parent
972 return d_maps;
973}
974
975#if 0
982unsigned int Array::width(bool constrained) const
983{
984
985 if (constrained) {
986 // This preserves the original method's semantics when we ask for the
987 // size of the constrained array but no constraint has been applied.
988 // In this case, length will be -1. Wrong, I know...
989 return length() * var()->width(constrained);
990 }
991 else {
992 int length = 1;
993 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
994 length *= dimension_size(i, false);
995 }
996 return length * var()->width(false);
997 }
998}
999#endif
1000
1001class PrintD4ArrayDimXMLWriter: public unary_function<Array::dimension&, void> {
1002 XMLWriter &xml;
1003// Was this variable constrained using local/direct slicing? i.e., is d_local_constraint set?
1004// If so, don't use shared dimensions; instead emit Dim elements that are anonymous.
1005 bool d_constrained;
1006public:
1007
1008 PrintD4ArrayDimXMLWriter(XMLWriter &xml, bool c) :
1009 xml(xml), d_constrained(c)
1010 {
1011 }
1012
1013 void operator()(Array::dimension &d)
1014 {
1015 // This duplicates code in D4Dimensions (where D4Dimension::print_dap4() is defined
1016 // because of the need to print the constrained size of a dimension. I think that
1017 // the constraint information has to be kept here and not in the dimension (since they
1018 // are shared dims). Could hack print_dap4() to take the constrained size, however.
1019 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dim") < 0)
1020 throw InternalErr(__FILE__, __LINE__, "Could not write Dim element");
1021
1022 string name = (d.dim) ? d.dim->fully_qualified_name() : d.name;
1023 // If there is a name, there must be a Dimension (named dimension) in scope
1024 // so write its name but not its size.
1025 if (!d_constrained && !name.empty()) {
1026 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) name.c_str())
1027 < 0) throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1028 }
1029 else if (d.use_sdim_for_slice) {
1030 assert(!name.empty());
1031 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) name.c_str())
1032 < 0) throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1033 }
1034 else {
1035 ostringstream size;
1036 size << (d_constrained ? d.c_size : d.size);
1037 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "size",
1038 (const xmlChar*) size.str().c_str()) < 0)
1039 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1040 }
1041
1042 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1043 throw InternalErr(__FILE__, __LINE__, "Could not end Dim element");
1044 }
1045};
1046
1047class PrintD4ConstructorVarXMLWriter: public unary_function<BaseType*, void> {
1048 XMLWriter &xml;
1049 bool d_constrained;
1050public:
1051 PrintD4ConstructorVarXMLWriter(XMLWriter &xml, bool c) :
1052 xml(xml), d_constrained(c)
1053 {
1054 }
1055
1056 void operator()(BaseType *btp)
1057 {
1058 btp->print_dap4(xml, d_constrained);
1059 }
1060};
1061
1062class PrintD4MapXMLWriter: public unary_function<D4Map*, void> {
1063 XMLWriter &xml;
1064
1065public:
1066 PrintD4MapXMLWriter(XMLWriter &xml) :
1067 xml(xml)
1068 {
1069 }
1070
1071 void operator()(D4Map *m)
1072 {
1073 m->print_dap4(xml);
1074 }
1075};
1076
1082void Array::print_dap4(XMLWriter &xml, bool constrained /* default: false*/)
1083{
1084 if (constrained && !send_p()) return;
1085
1086 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) var()->type_name().c_str()) < 0)
1087 throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
1088
1089 if (!name().empty())
1090 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) name().c_str()) < 0)
1091 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1092
1093// Hack job... Copied from D4Enum::print_xml_writer. jhrg 11/12/13
1094 if (var()->type() == dods_enum_c) {
1095 D4Enum *e = static_cast<D4Enum*>(var());
1096 string path = e->enumeration()->name();
1097 if (e->enumeration()->parent()) {
1098 // print the FQN for the enum def; D4Group::FQN() includes the trailing '/'
1099 path = static_cast<D4Group*>(e->enumeration()->parent()->parent())->FQN() + path;
1100 }
1101 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "enum", (const xmlChar*) path.c_str()) < 0)
1102 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for enum");
1103 }
1104
1105 if (prototype()->is_constructor_type()) {
1106 Constructor &c = static_cast<Constructor&>(*prototype());
1107 for_each(c.var_begin(), c.var_end(), PrintD4ConstructorVarXMLWriter(xml, constrained));
1108 // bind2nd(mem_fun_ref(&BaseType::print_dap4), xml));
1109 }
1110
1111// Drop the local_constraint which is per-array and use a per-dimension on instead
1112 for_each(dim_begin(), dim_end(), PrintD4ArrayDimXMLWriter(xml, constrained));
1113
1114 attributes()->print_dap4(xml);
1115
1116 for_each(maps()->map_begin(), maps()->map_end(), PrintD4MapXMLWriter(xml));
1117
1118 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1119 throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
1120}
1121
1139void Array::print_decl(FILE *out, string space, bool print_semi, bool constraint_info, bool constrained)
1140{
1141 ostringstream oss;
1142 print_decl(oss, space, print_semi, constraint_info, constrained);
1143 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1144}
1145
1163void Array::print_decl(ostream &out, string space, bool print_semi, bool constraint_info, bool constrained)
1164{
1165 if (constrained && !send_p()) return;
1166
1167// print it, but w/o semicolon
1168 var()->print_decl(out, space, false, constraint_info, constrained);
1169
1170 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
1171 out << "[";
1172 if ((*i).name != "") {
1173 out << id2www((*i).name) << " = ";
1174 }
1175 if (constrained) {
1176 out << (*i).c_size << "]";
1177 }
1178 else {
1179 out << (*i).size << "]";
1180 }
1181 }
1182
1183 if (print_semi) {
1184 out << ";\n";
1185 }
1186}
1187
1191void Array::print_xml(FILE *out, string space, bool constrained)
1192{
1193 XMLWriter xml(space);
1194 print_xml_writer_core(xml, constrained, "Array");
1195 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
1196}
1197
1201void Array::print_xml(ostream &out, string space, bool constrained)
1202{
1203 XMLWriter xml(space);
1204 print_xml_writer_core(xml, constrained, "Array");
1205 out << xml.get_doc();
1206}
1207
1211void Array::print_as_map_xml(FILE *out, string space, bool constrained)
1212{
1213 XMLWriter xml(space);
1214 print_xml_writer_core(xml, constrained, "Map");
1215 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
1216}
1217
1221void Array::print_as_map_xml(ostream &out, string space, bool constrained)
1222{
1223 XMLWriter xml(space);
1224 print_xml_writer_core(xml, constrained, "Map");
1225 out << xml.get_doc();
1226}
1227
1231void Array::print_xml_core(FILE *out, string space, bool constrained, string tag)
1232{
1233 XMLWriter xml(space);
1234 print_xml_writer_core(xml, constrained, tag);
1235 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
1236}
1237
1241void Array::print_xml_core(ostream &out, string space, bool constrained, string tag)
1242{
1243 XMLWriter xml(space);
1244 print_xml_writer_core(xml, constrained, tag);
1245 out << xml.get_doc();
1246}
1247
1248void Array::print_xml_writer(XMLWriter &xml, bool constrained)
1249{
1250 print_xml_writer_core(xml, constrained, "Array");
1251}
1252
1253void Array::print_as_map_xml_writer(XMLWriter &xml, bool constrained)
1254{
1255 print_xml_writer_core(xml, constrained, "Map");
1256}
1257
1258class PrintArrayDimXMLWriter: public unary_function<Array::dimension&, void> {
1259 XMLWriter &xml;
1260 bool d_constrained;
1261public:
1262 PrintArrayDimXMLWriter(XMLWriter &xml, bool c) :
1263 xml(xml), d_constrained(c)
1264 {
1265 }
1266
1267 void operator()(Array::dimension &d)
1268 {
1269 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "dimension") < 0)
1270 throw InternalErr(__FILE__, __LINE__, "Could not write dimension element");
1271
1272 if (!d.name.empty())
1273 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) d.name.c_str())
1274 < 0) throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1275
1276 ostringstream size;
1277 size << (d_constrained ? d.c_size : d.size);
1278 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "size", (const xmlChar*) size.str().c_str())
1279 < 0) throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1280
1281 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1282 throw InternalErr(__FILE__, __LINE__, "Could not end dimension element");
1283 }
1284};
1285
1286void Array::print_xml_writer_core(XMLWriter &xml, bool constrained, string tag)
1287{
1288 if (constrained && !send_p()) return;
1289
1290 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) tag.c_str()) < 0)
1291 throw InternalErr(__FILE__, __LINE__, "Could not write " + tag + " element");
1292
1293 if (!name().empty())
1294 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) name().c_str()) < 0)
1295 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1296
1298
1299 BaseType *btp = var();
1300 string tmp_name = btp->name();
1301 btp->set_name("");
1302 btp->print_xml_writer(xml, constrained);
1303 btp->set_name(tmp_name);
1304
1305 for_each(dim_begin(), dim_end(), PrintArrayDimXMLWriter(xml, constrained));
1306
1307 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1308 throw InternalErr(__FILE__, __LINE__, "Could not end " + tag + " element");
1309}
1310
1322uint64_t Array::print_array(FILE *out, uint64_t index, unsigned int dims, uint64_t shape[])
1323{
1324 ostringstream oss;
1325 uint64_t i = print_array(oss, index, dims, shape);
1326 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1327
1328 return i;
1329}
1330
1342uint64_t Array::print_array(ostream &out, uint64_t index, unsigned int dims, uint64_t shape[])
1343{
1344 if (dims == 1) {
1345 out << "{";
1346
1347 // Added test in case this method is passed an array with no elements. jhrg 1/27/16
1348 if (shape[0] >= 1) {
1349 for (uint64_t i = 0; i < shape[0] - 1; ++i) {
1350 var_ll(index++)->print_val(out, "", false);
1351 out << ", ";
1352 }
1353 var_ll(index++)->print_val(out, "", false);
1354 }
1355
1356 out << "}";
1357
1358 return index;
1359 }
1360 else {
1361 out << "{";
1362 // Fixed an off-by-one error in the following loop. Since the array
1363 // length is shape[dims-1]-1 *and* since we want one less dimension
1364 // than that, the correct limit on this loop is shape[dims-2]-1. From
1365 // Todd Karakasian.
1366 //
1367 // The saga continues; the loop test should be `i < shape[0]-1'. jhrg
1368 // 9/12/96.
1369 //
1370 // For arrays that hold zero values but have rank > 1, the print out
1371 // may look a little odd (e.g., x[4][0] will print as { {}, {}, {}, {} })
1372 // but it's not wrong and this is really for debugging mostly. jhrg 1/28/16
1373 if (shape[0] > 0) {
1374 for (uint64_t i = 0; i < shape[0] - 1; ++i) {
1375 index = print_array(out, index, dims - 1, shape + 1);
1376 out << ",";
1377 }
1378
1379 index = print_array(out, index, dims - 1, shape + 1);
1380 }
1381
1382 out << "}";
1383
1384 return index;
1385 }
1386}
1387
1388void Array::print_val(FILE *out, string space, bool print_decl_p)
1389{
1390 ostringstream oss;
1391 print_val(oss, space, print_decl_p);
1392 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1393}
1394
1395void Array::print_val(ostream &out, string space, bool print_decl_p)
1396{
1397// print the declaration if print decl is true.
1398// for each dimension,
1399// for each element,
1400// print the array given its shape, number of dimensions.
1401// Add the `;'
1402
1403 if (print_decl_p) {
1404 print_decl(out, space, false, false, false);
1405 out << " = ";
1406 }
1407
1408 auto shape = new uint64_t[dimensions(true)];
1409 unsigned int index = 0;
1410 for (Dim_iter i = _shape.begin(); i != _shape.end() && index < dimensions(true); ++i)
1411 shape[index++] = dimension_size_ll(i, true);
1412
1413 print_array(out, 0, dimensions(true), shape);
1414
1415 delete[] shape;
1416 shape = 0;
1417
1418 if (print_decl_p) {
1419 out << ";\n";
1420 }
1421}
1422
1432bool Array::check_semantics(string &msg, bool)
1433{
1434 bool sem = BaseType::check_semantics(msg) && !_shape.empty();
1435
1436 if (!sem) msg = "An array variable must have dimensions";
1437
1438 return sem;
1439}
1440
1441
1449 stringstream sqr_brkty_stuff;
1450 for(auto itr=a.dim_begin(); itr!=a.dim_end(); itr++){
1451 sqr_brkty_stuff << "[";
1452 string dim_name = a.dimension_name(itr);
1453 if(!dim_name.empty()){
1454 sqr_brkty_stuff << dim_name << "=";
1455 }
1456 sqr_brkty_stuff << a.dimension_size_ll(itr,true) << "]";
1457 }
1458 return sqr_brkty_stuff.str();
1459}
1460
1467bool Array::is_dap4_projected(std::vector<std::string> &inventory)
1468{
1469 bool has_projected_dap4 = false;
1470 if(send_p()) {
1471 if(prototype()->is_constructor_type()){
1472 has_projected_dap4 = prototype()->is_dap4_projected(inventory) || attributes()->has_dap4_types(FQN(),inventory);
1473 }
1474 else {
1475 Type type = prototype()->type();
1476 has_projected_dap4 = (type == libdap::dods_int8_c ) || (type == dods_uint64_c) || (type == dods_int64_c);
1477 if(has_projected_dap4) {
1478 inventory.emplace_back(prototype()->type_name() + " " + FQN() + get_dims_decl(*this));
1479 }
1480 has_projected_dap4 |= attributes()->has_dap4_types(FQN(), inventory);
1481 }
1482 }
1483 return has_projected_dap4;
1484
1485}
1486
1495void Array::dump(ostream &strm) const
1496{
1497 strm << DapIndent::LMarg << "Array::dump - (" << (void *) this << ")" << endl;
1498 DapIndent::Indent();
1499 Vector::dump(strm);
1500 strm << DapIndent::LMarg << "shape:" << endl;
1501 DapIndent::Indent();
1502 Dim_citer i = _shape.begin();
1503 Dim_citer ie = _shape.end();
1504 unsigned int dim_num = 0;
1505 for (; i != ie; i++) {
1506 strm << DapIndent::LMarg << "dimension " << dim_num++ << ":" << endl;
1507 DapIndent::Indent();
1508 strm << DapIndent::LMarg << "name: " << (*i).name << endl;
1509 strm << DapIndent::LMarg << "size: " << (*i).size << endl;
1510 strm << DapIndent::LMarg << "start: " << (*i).start << endl;
1511 strm << DapIndent::LMarg << "stop: " << (*i).stop << endl;
1512 strm << DapIndent::LMarg << "stride: " << (*i).stride << endl;
1513 strm << DapIndent::LMarg << "constrained size: " << (*i).c_size << endl;
1514 DapIndent::UnIndent();
1515 }
1516 DapIndent::UnIndent();
1517 DapIndent::UnIndent();
1518}
1519
1527
1528 vs_info.filter = my_vs_info.filter;
1529
1530 for (const auto &def_lev:my_vs_info.deflate_levels)
1531 vs_info.deflate_levels.push_back(def_lev);
1532
1533 for (const auto &chunk_dim:my_vs_info.chunk_dims)
1534 vs_info.chunk_dims.push_back(chunk_dim);
1535
1536 for (const auto &vci:my_vs_info.var_chunk_info) {
1537 var_chunk_info_t vci_t;
1538 vci_t.filter_mask = vci.filter_mask;
1539 vci_t.chunk_direct_io_offset = vci.chunk_direct_io_offset;
1540 vci_t.chunk_buffer_size = vci.chunk_buffer_size;
1541 for (const auto &chunk_coord:vci.chunk_coords)
1542 vci_t.chunk_coords.push_back(chunk_coord);
1543 vs_info.var_chunk_info.push_back(vci_t);
1544 }
1545
1546}
1547
1548} // namespace libdap
A multidimensional array of identical data types.
Definition Array.h:123
void print_dap4(XMLWriter &xml, bool constrained=false) override
Print the DAP4 representation of an array.
Definition Array.cc:1082
virtual int dimension_start(Dim_iter i, bool constrained=false)
Return the start index of a dimension.
Definition Array.cc:849
virtual void clear_constraint()
Clears the projection; add each projected dimension explicitly using add_constraint.
Definition Array.cc:639
Dim_iter dim_end()
Definition Array.cc:768
virtual int dimension_stop(Dim_iter i, bool constrained=false)
Return the stop index of the constraint.
Definition Array.cc:876
void dump(ostream &strm) const override
dumps information about this object
Definition Array.cc:1495
virtual void update_length(int size=0)
Definition Array.cc:102
bool is_dap4_projected(std::vector< std::string > &projected_dap4_inventory) override
Definition Array.cc:1467
virtual void add_constraint(Dim_iter i, int start, int stride, int stop)
Adds a constraint to an Array dimension.
Definition Array.cc:670
virtual string dimension_name(Dim_iter i)
Returns the name of the specified dimension.
Definition Array.cc:951
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:1163
std::vector< dimension >::const_iterator Dim_citer
Definition Array.h:233
void print_xml(ostream &out, string space=" ", bool constrained=false) override
Definition Array.cc:1201
void print_val(ostream &out, string space="", bool print_decl_p=true) override
Prints the value of the variable.
Definition Array.cc:1395
BaseType * ptr_duplicate() override
Definition Array.cc:181
void append_dim(int size, const string &name="")
Add a dimension of a given size.
Definition Array.cc:533
void rename_dim(const string &oldName="", const string &newName="")
Renames dimension.
Definition Array.cc:597
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:308
virtual int dimension_size(Dim_iter i, bool constrained=false)
Returns the size of the dimension.
Definition Array.cc:805
void clear_all_dims()
Definition Array.cc:587
void add_var(BaseType *v, Part p=nil) override
Add the BaseType pointer to this constructor type instance.
Definition Array.cc:481
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:1322
virtual void print_as_map_xml(ostream &out, string space=" ", bool constrained=false)
Definition Array.cc:1221
void print_xml_writer(XMLWriter &xml, bool constrained=false) override
Definition Array.cc:1248
std::vector< dimension >::iterator Dim_iter
Definition Array.h:241
virtual void reset_constraint()
Reset constraint to select entire array.
Definition Array.cc:616
void set_var_storage_info(const var_storage_info &my_vs_info)
Set the variable storage information for direct IO optimization.
Definition Array.cc:1526
virtual ~Array()
The Array destructor.
Definition Array.cc:175
virtual void print_xml_core(FILE *out, string space, bool constrained, string tag)
Definition Array.cc:1231
void prepend_dim(int size, const string &name="")
Definition Array.cc:566
Dim_iter dim_begin()
Definition Array.cc:762
void transform_to_dap4(D4Group *root, Constructor *container) override
DAP2 to DAP4 transform.
Definition Array.cc:195
Array(const string &n, BaseType *v, bool is_dap4=false)
Array constructor.
Definition Array.cc:139
bool check_semantics(string &msg, bool all=false) override
Check semantic features of the Array.
Definition Array.cc:1432
virtual unsigned int dimensions(bool constrained=false)
Return the total number of dimensions in the array.
Definition Array.cc:783
virtual int dimension_stride(Dim_iter i, bool constrained=false)
Returns the stride value of the constraint.
Definition Array.cc:904
Contains the attributes for a dataset.
Definition AttrTable.h:154
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
Definition AttrTable.cc:554
virtual void set_name(const string &n)
Set the name of this attribute table.
Definition AttrTable.cc:273
virtual string get_name() const
Get the name of this attribute table.
Definition AttrTable.cc:266
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:259
The basic data type for the DODS DAP types.
Definition BaseType.h:120
virtual bool is_dap4_projected(std::vector< string > &projected_dap4_inventory)
Definition BaseType.cc:1323
virtual string type_name() const
Returns the type of the class instance as a string.
Definition BaseType.cc:376
virtual AttrTable & get_attr_table()
Definition BaseType.cc:579
virtual string name() const
Returns the name of the class instance.
Definition BaseType.cc:317
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:1009
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:1305
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:409
virtual D4Attributes * attributes()
Definition BaseType.cc:596
virtual std::string FQN() const
Definition BaseType.cc:329
virtual bool send_p()
Should this variable be sent?
Definition BaseType.cc:551
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition BaseType.cc:1215
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition BaseType.cc:126
virtual Type type() const
Returns the type of the class instance.
Definition BaseType.cc:362
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition BaseType.cc:1096
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
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.
vector< D4Dimension * >::iterator D4DimensionsIter
Iterator used for D4Dimensions.
Holds a DAP4 enumeration.
Definition D4Enum.h:56
D4Dimensions * dims()
Get the dimensions defined for this Group.
Definition D4Group.h:84
std::string FQN() const override
Definition D4Group.cc:187
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:94
Holds the Grid data type.
Definition Grid.h:123
virtual void set_array(Array *p_new_arr)
Definition Grid.cc:377
virtual Array * add_map(Array *p_new_map, bool add_copy)
Definition Grid.cc:443
A class for software fault reporting.
Definition InternalErr.h:65
Holds a one-dimensional collection of DAP2 data types.
Definition Vector.h:83
void dump(ostream &strm) const override
dumps information about this object
Definition Vector.cc:2665
void add_var(BaseType *v, Part p=nil) override
Add the BaseType pointer to this constructor type instance.
Definition Vector.cc:2552
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:218
BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=nullptr) override
Definition Vector.cc:486
void set_length(int64_t l) override
Sets the length of the vector. This function does not allocate any new space.
Definition Vector.cc:434
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:1448
string www2id(const string &in, const string &escape, const string &except)
Definition escaping.cc:220
Part
Names the parts of multi-section constructor data types.
Definition Type.h:48
string id2www(string in, const string &allowable)
Definition escaping.cc:153
int64_t start
The constraint start index.
Definition Array.h:158
int64_t stride
The constraint stride.
Definition Array.h:160
string name
The name of this dimension.
Definition Array.h:146
int64_t size
The unconstrained dimension size.
Definition Array.h:145
int64_t stop
The constraint end index.
Definition Array.h:159
bool use_sdim_for_slice
Used to control printing the DMR in data responses.
Definition Array.h:156
int64_t c_size
Size of dimension once constrained.
Definition Array.h:161