libdap Updated for version 3.20.10
libdap4 is an implementation of OPeNDAP's DAP protocol.
Vector.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 1995-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 class Vector. This class is the basis for all the
32// vector-type classes in libdap's <Array, List>.
33//
34// 11/21/95 jhrg
35
36#include "config.h"
37
38#include <cstring>
39#include <cassert>
40
41//#define DODS_DEBUG 1
42
43#include <sstream>
44#include <vector>
45#include <algorithm>
46#include <typeinfo>
47
48#include <stdint.h>
49
50#include "crc.h"
51
52#include "Vector.h"
53#include "Marshaller.h"
54#include "UnMarshaller.h"
55
56#include "D4StreamMarshaller.h"
57#include "D4StreamUnMarshaller.h"
58
59#include "D4Enum.h"
60
61#include "Type.h"
62#include "dods-datatypes.h"
63#include "escaping.h"
64#include "util.h"
65#include "debug.h"
66#include "InternalErr.h"
67#include "DapIndent.h"
68
69#undef CLEAR_LOCAL_DATA
70
71using std::cerr;
72using std::endl;
73
74namespace libdap {
75
76void Vector::m_duplicate(const Vector & v)
77{
78 d_length = v.d_length;
79
80 // _var holds the type of the elements. That is, it holds a BaseType
81 // which acts as a template for the type of each element.
82 if (v.d_proto) {
83 // Vector manages this ptr, delete before assigning a new object. jhrg 2/19/22
84 if (d_proto) delete d_proto;
85 d_proto = v.d_proto->ptr_duplicate(); // use ptr_duplicate()
86 d_proto->set_parent(this); // ptr_duplicate does not set d_parent.
87 }
88 else {
89 d_proto = nullptr;
90 }
91
92 // d_compound_buf and d_buf (further down) hold the values of the Vector. The field
93 // d_compound_buf is used when the Vector holds non-numeric data (including strings,
94 // although it used to be that was not the case jhrg 2/10/05) while d_buf
95 // holds numeric values.
96 if (v.d_compound_buf.empty()) {
97 d_compound_buf = v.d_compound_buf;
98 }
99 else {
100 // Failure to set the size will make the [] operator barf on the LHS
101 // of the assignment inside the loop.
102 d_compound_buf.resize(d_length);
103 for (int i = 0; i < d_length; ++i) {
104 // There's no need to call set_parent() for each element; we
105 // maintain the back pointer using the d_proto member. These
106 // instances are used to hold _values_ only while the d_proto
107 // field holds the type information for the elements.
108 d_compound_buf[i] = v.d_compound_buf[i]->ptr_duplicate();
109 }
110 }
111
112 // copy the strings. This copies the values.
113 d_str = v.d_str;
114
115 // copy numeric values if there are any.
116 d_buf = 0; // init to null
117 if (v.d_buf) // only copy if data present
118 val2buf(v.d_buf); // store v's value in this's _BUF.
119
120 d_capacity = v.d_capacity;
121}
122
128{
129 // Not cardinal if no d_proto at all!
130 if (!d_proto) {
131 return false;
132 }
133
134 switch (d_proto->type()) {
135 case dods_byte_c:
136 case dods_char_c:
137 case dods_int16_c:
138 case dods_uint16_c:
139 case dods_int32_c:
140 case dods_uint32_c:
141 case dods_float32_c:
142 case dods_float64_c:
143 // New cardinal types for DAP4
144 case dods_int8_c:
145 case dods_uint8_c:
146 case dods_int64_c:
147 case dods_uint64_c:
148
149 case dods_enum_c:
150 return true;
151
152 // These must be handled differently.
153 case dods_str_c:
154 case dods_url_c:
155 case dods_opaque_c:
156
157 case dods_array_c:
158
159 case dods_structure_c:
160 case dods_sequence_c:
161 case dods_grid_c:
162 return false;
163
164 default:
165 assert("Vector::var: Unrecognized type");
166 return false;
167 }
168}
169
182unsigned int Vector::m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
183{
184 // Make sure we HAVE a _var, or we cannot continue.
185 if (!d_proto) {
186 throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
187 }
188
189 // Make sure we only do this for the correct data types.
190 if (!m_is_cardinal_type()) {
191 throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
192 }
193
195
196 // Handle this special case where this is an array that holds no values
197 if (numEltsOfType == 0)
198 return 0;
199
200 // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
201 unsigned int bytesPerElt = d_proto->width();
202 unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
203 d_buf = new char[bytesNeeded];
204
205 d_capacity = numEltsOfType;
206 return bytesNeeded;
207}
208
211{
212 delete[] d_buf;
213 d_buf = nullptr;
214 d_capacity = 0;
215}
216
220template<class CardType>
221void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int numElts)
222{
223 if (numElts < 0) {
224 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
225 }
226 if (!fromArray) {
227 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
228 }
229 set_length(numElts);
231 if (d_buf)
232 memcpy(d_buf, fromArray, numElts * sizeof(CardType));
233 set_read_p(true);
234}
235
251Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
252 BaseType(n, t, is_dap4)
253{
254 if (v)
255 add_var(v);
256
257 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
258 if (d_proto)
259 d_proto->set_parent(this);
260}
261
280Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
281 BaseType(n, d, t, is_dap4)
282{
283 if (v)
284 add_var(v);
285
286 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
287 if (d_proto)
288 d_proto->set_parent(this);
289}
290
292Vector::Vector(const Vector & rhs) : BaseType(rhs)
293
294{
295 DBG2(cerr << "Entering Vector const ctor for object: " << this <<
296 endl); DBG2(cerr << "RHS: " << &rhs << endl);
297
298 m_duplicate(rhs);
299}
300
301Vector::~Vector()
302{
303 DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
304
305 delete d_proto;
306 d_proto = nullptr;
307
308 // Clears all buffers
310
311 DBG2(cerr << "Exiting ~Vector" << endl);
312}
313
314Vector & Vector::operator=(const Vector & rhs)
315{
316 if (this == &rhs)
317 return *this;
318 BaseType::operator=(rhs);
319 m_duplicate(rhs);
320 return *this;
321}
322
323void Vector::set_name(const std::string& name)
324{
326 // We need to set the prototype name as well since
327 // this is what gets output in the dds! Otherwise, there's a mismatch.
328 if (d_proto) {
329 d_proto->set_name(name);
330 }
331}
332
333int Vector::element_count(bool leaves)
334{
335 if (!leaves)
336 return 1;
337 else
338 return d_proto->element_count(leaves);
339 // var() only works for simple types!
340 // jhrg 8/19/13 return var(0)->element_count(leaves);
341}
342
343// These mfuncs set the _send_p and _read_p fields of BaseType. They differ
344// from BaseType's version in that they set both the Vector object's copy of
345// _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
346// is a scalar, but does matter when it is an aggregate.
347
354void Vector::set_send_p(bool state)
355{
356 if (d_proto) {
357 d_proto->set_send_p(state);
358
359 // because some code may depend on the BaseType*s held in d_compound_buf
360 // behaving as if they are 'ordinary' DAP variables, make sure their send_p
361 // flag is set if they exist. Because space in the vector is allocated
362 // before values (BaseType*s) are added, check for nulls and limit the
363 // iteration to only those elements actually in the object including any
364 // constraints that may have been applied - these are values not declarations.
365 // jhrg 5/13/16
366 switch (d_proto->type()) {
367 case dods_structure_c:
368 case dods_sequence_c:
369 case dods_grid_c:
370 if (d_compound_buf.size() > 0) {
371 for (unsigned long long i = 0; i < (unsigned) d_length; ++i) {
372 if (d_compound_buf[i]) d_compound_buf[i]->set_send_p(state);
373 }
374 }
375 break;
376
377 default:
378 break;
379 }
380 }
381
383}
384
391void Vector::set_read_p(bool state)
392{
393 if (d_proto) {
394 d_proto->set_read_p(state);
395
396 // See comment above.
397 switch (d_proto->type()) {
398 case dods_structure_c:
399 case dods_sequence_c:
400 case dods_grid_c:
401 if (d_compound_buf.size() > 0) {
402 for (unsigned long long i = 0; i < (unsigned)d_length; ++i) {
403 if (d_compound_buf[i]) d_compound_buf[i]->set_read_p(state);
404 }
405 }
406 break;
407
408 default:
409 break;
410 }
411 }
412
414}
415
433BaseType *Vector::var(const string &n, bool exact, btp_stack *s)
434{
435 string name = www2id(n);
436 DBG2(cerr << "Vector::var: Looking for " << name << endl);
437
438 if (name == "" || d_proto->name() == name) {
439 if (s)
440 s->push(this);
441 return d_proto;
442 }
443
444 // If this is a Vector of constructor types, look for 'name' recursively.
445 // Make sure to check for the case where name is the default (the empty
446 // string). 9/1/98 jhrg
447 if (d_proto->is_constructor_type()) {
448 BaseType *result = d_proto->var(name, exact, s);
449 if (result && s)
450 s->push(this);
451 return result;
452 }
453
454 return NULL;
455}
456
467BaseType *Vector::var(const string & n, btp_stack & s)
468{
469 string name = www2id(n);
470
471 if (d_proto->is_constructor_type())
472 return d_proto->var(name, s);
473 else {
474 s.push((BaseType *) this);
475 return d_proto;
476 }
477}
478
490BaseType *Vector::var(unsigned int i)
491{
492
493 switch (d_proto->type()) {
494 case dods_byte_c:
495 case dods_char_c:
496 case dods_int8_c:
497 case dods_uint8_c:
498 case dods_int16_c:
499 case dods_uint16_c:
500 case dods_int32_c:
501 case dods_uint32_c:
502 case dods_int64_c:
503 case dods_uint64_c:
504
505 case dods_enum_c:
506
507 case dods_float32_c:
508 case dods_float64_c:
509 // Transfer the ith value to the BaseType *d_proto
510 d_proto->val2buf(d_buf + (i * d_proto->width()));
511 return d_proto;
512
513 case dods_str_c:
514 case dods_url_c:
515 d_proto->val2buf(&d_str[i]);
516 return d_proto;
517
518 case dods_opaque_c:
519 case dods_array_c:
520 case dods_structure_c:
521 case dods_sequence_c:
522 case dods_grid_c:
523 return d_compound_buf[i];
524
525 default:
526 throw Error ("Vector::var: Unrecognized type");
527 }
528}
529
536unsigned int Vector::width(bool constrained) const
537{
538 // Jose Garcia
539 assert(d_proto);
540
541 return length() * d_proto->width(constrained);
542}
543
548int Vector::length() const
549{
550 return d_length;
551}
552
556{
557 d_length = l;
558}
559
569{
570 // I added this check, which alters the behavior of the method. jhrg 8/14/13
571 if (m_is_cardinal_type())
572 throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
573
574 // Use resize() since other parts of the code use operator[]. Note that size() should
575 // be used when resize() is used. Using capacity() creates problems as noted in the
576 // comment in set_vec_nocopy(). jhrg 5/19/17
577 d_compound_buf.resize(l, 0); // Fill with NULLs
578 d_capacity = d_compound_buf.size(); // size in terms of number of elements.
579}
580
598{
599 DBG(cerr << "Vector::intern_data: " << name() << endl);
600 if (!read_p())
601 read(); // read() throws Error and InternalErr
602
603 // length() is not capacity; it must be set explicitly in read().
604 int num = length();
605
606 switch (d_proto->type()) {
607 case dods_byte_c:
608 case dods_int16_c:
609 case dods_uint16_c:
610 case dods_int32_c:
611 case dods_uint32_c:
612 case dods_float32_c:
613 case dods_float64_c:
614 // For these cases, read() puts the data into d_buf,
615 // which is what we need.
616 break;
617
618 case dods_str_c:
619 case dods_url_c:
620 // For these cases, read() will put the data into d_str[],
621 // which is also what we need.
622 break;
623
624 case dods_array_c:
625 // This is an error since there can never be an Array of Array.
626 throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
627
628 case dods_structure_c:
629 case dods_sequence_c:
630 case dods_grid_c:
631 DBG(cerr << "Vector::intern_data: found ctor" << endl);
632 // For these cases, we need to call read() for each of the 'num'
633 // elements in the 'd_compound_buf[]' array of BaseType object pointers.
634 //
635 // I changed the test here from '... = 0' to '... < num' to accommodate
636 // the case where the array is zero-length.
637 if (d_compound_buf.capacity() < (unsigned)num)
638 throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements.");
639
640 for (int i = 0; i < num; ++i)
641 d_compound_buf[i]->intern_data(eval, dds);
642
643 break;
644
645 default:
646 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
647 }
648}
649
661bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
662{
663 // Added to streamline zero-length arrays. Not needed for correct function,
664 // but explicitly handling this case here makes the code easier to follow.
665 // In libdap::Vector::val2buf() there is a test that will catch the zero-length
666 // case as well. We still need to call serialize since it will write size
667 // information that the client depends on. jhrg 2/17/16
668 if (length() == 0)
669 set_read_p(true);
670 else if (!read_p())
671 read(); // read() throws Error and InternalErr
672
673 if (ce_eval && !eval.eval_selection(dds, dataset()))
674 return true;
675
676 // length() is not capacity; it must be set explicitly in read().
677 int num = length();
678
679 bool status = false;
680
681 switch (d_proto->type()) {
682 case dods_byte_c:
683 m.put_vector(d_buf, num, *this);
684 status = true;
685 break;
686
687 case dods_int16_c:
688 case dods_uint16_c:
689 case dods_int32_c:
690 case dods_uint32_c:
691 case dods_float32_c:
692 case dods_float64_c:
693 m.put_vector(d_buf, num, d_proto->width(), *this);
694 status = true;
695
696 break;
697
698 case dods_str_c:
699 case dods_url_c:
700 if (d_str.capacity() == 0)
701 throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
702
703 m.put_int(num);
704
705 for (int i = 0; i < num; ++i)
706 m.put_str(d_str[i]);
707
708 status = true;
709 break;
710
711 case dods_array_c:
712 case dods_structure_c:
713 case dods_sequence_c:
714 case dods_grid_c:
715 //Jose Garcia
716 // Not setting the capacity of d_compound_buf is an internal error.
717 if (d_compound_buf.capacity() == 0)
718 throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
719
720 m.put_int(num);
721 status = true;
722 for (int i = 0; i < num && status; ++i)
723 status = status && d_compound_buf[i]->serialize(eval, dds, m, false);
724
725 break;
726
727 default:
728 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
729 }
730
731#ifdef CLEAR_LOCAL_DATA
733#endif
734
735 return status;
736}
737
738// Read an object from the network and internalize it. For a Vector this is
739// handled differently for a `cardinal' type. Vectors of Cardinals are
740// stored using the `C' representations because these objects often are used
741// to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
742// arrays of non-cardinal types are stored as Vectors of the C++ objects or
743// DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
744// Grid are vectors of the libdap Structure, ... classes).
745//
746// The boolean parameter REUSE determines whether internal storage is reused
747// or not. If true, the _buf member is assumed to be large enough to hold the
748// incoming cardinal data and is *not* reallocated. If false, new storage is
749// allocated. If the internal buffer has not yet been allocated, then this
750// parameter has no effect (i.e., storage is allocated). This parameter
751// effects storage for cardinal data only.
752//
753// Returns: True is successful, false otherwise.
754
755bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
756{
757 unsigned int num;
758 unsigned i = 0;
759
760 switch (d_proto->type()) {
761 case dods_byte_c:
762 case dods_int16_c:
763 case dods_uint16_c:
764 case dods_int32_c:
765 case dods_uint32_c:
766 case dods_float32_c:
767 case dods_float64_c:
768 um.get_int((int &) num);
769
770 DBG(cerr << "Vector::deserialize: num = " << num << endl);
771 DBG(cerr << "Vector::deserialize: length = " << length() << endl);
772
773 if (length() == -1)
774 set_length(num);
775
776 if (num != (unsigned int) length())
777 throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes for the variable '" + name() + "'.");
778
779 if (!d_buf || !reuse) {
780 // Make d_buf be large enough for length() elements of _var->type()
781 // m_create...() deletes the old buffer.
783 DBG(cerr << "Vector::deserialize: allocating "
784 << width() << " bytes for an array of "
785 << length() << " " << d_proto->type_name() << endl);
786 }
787
788 // Added to accommodate zero-length arrays.
789 // Note that the rest of the cases will just send the size without data
790 // but that these calls trigger error testing in the UnMarshaller code.
791 // jhrg 1/28/16
792 if (num == 0)
793 return true;
794
795 if (d_proto->type() == dods_byte_c)
796 um.get_vector((char **) &d_buf, num, *this);
797 else
798 um.get_vector((char **) &d_buf, num, d_proto->width(), *this);
799
800 DBG(cerr << "Vector::deserialize: read " << num << " elements\n");
801
802 break;
803
804 case dods_str_c:
805 case dods_url_c:
806 um.get_int((int &) num);
807
808 if (length() == -1)
809 set_length(num);
810
811 if (num != (unsigned int) length())
812 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
813
814 d_str.resize((num > 0) ? num : 0); // Fill with NULLs
815 d_capacity = num; // capacity is number of strings we can fit.
816
817 for (i = 0; i < num; ++i) {
818 string str;
819 um.get_str(str);
820 d_str[i] = str;
821
822 }
823
824 break;
825
826 case dods_array_c:
827 // Added jhrg 5/18/17
828 // This replaces a comment that was simply 'TO DO'
829 throw InternalErr(__FILE__, __LINE__, "Array of array!");
830
831 case dods_structure_c:
832 case dods_sequence_c:
833 case dods_grid_c:
834 um.get_int((int &) num);
835
836 if (length() == -1)
837 set_length(num);
838
839 if (num != (unsigned int) length())
840 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
841
842 vec_resize(num);
843
844 for (i = 0; i < num; ++i) {
845 d_compound_buf[i] = d_proto->ptr_duplicate();
846 d_compound_buf[i]->deserialize(um, dds);
847 }
848
849 break;
850
851 default:
852 throw InternalErr(__FILE__, __LINE__, "Unknown type!");
853 }
854
855 return false;
856}
857
859{
860 switch (d_proto->type()) {
861 case dods_byte_c:
862 case dods_char_c:
863 case dods_int8_c:
864 case dods_uint8_c:
865
866 case dods_int16_c:
867 case dods_uint16_c:
868
869 case dods_int32_c:
870 case dods_uint32_c:
871 case dods_float32_c:
872
873 case dods_int64_c:
874 case dods_uint64_c:
875 case dods_float64_c:
876
877 case dods_enum_c:
878 checksum.AddData(reinterpret_cast<uint8_t*>(d_buf), length() * d_proto->width());
879 break;
880
881 case dods_str_c:
882 case dods_url_c:
883 for (int64_t i = 0, e = length(); i < e; ++i)
884 checksum.AddData(reinterpret_cast<const uint8_t*>(d_str[i].data()), d_str[i].length());
885 break;
886
887 case dods_opaque_c:
888 case dods_structure_c:
889 case dods_sequence_c:
890 d_proto->compute_checksum(checksum);
891 break;
892
893 case dods_array_c: // No array of array
894 case dods_grid_c: // No grids in DAP4
895 default:
896 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
897 }
898}
899
900void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
901{
902 if (!read_p())
903 read(); // read() throws Error and InternalErr
904
905 switch (d_proto->type()) {
906 case dods_byte_c:
907 case dods_char_c:
908 case dods_int8_c:
909 case dods_uint8_c:
910 case dods_int16_c:
911 case dods_uint16_c:
912 case dods_int32_c:
913 case dods_uint32_c:
914 case dods_int64_c:
915 case dods_uint64_c:
916
917 case dods_enum_c:
918
919 case dods_float32_c:
920 case dods_float64_c:
921
922 case dods_str_c:
923 case dods_url_c:
924#if 0
925 compute_checksum(checksum);
926#endif
927 break;
928
929 case dods_opaque_c:
930 case dods_structure_c:
931 case dods_sequence_c:
932 // Modified the assertion here from '... != 0' to '... >= length())
933 // to accommodate the case of a zero-length array. jhrg 1/28/16
934 assert(d_compound_buf.capacity() >= (unsigned)length());
935
936 for (int i = 0, e = length(); i < e; ++i)
937 d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/);
938 break;
939
940 case dods_array_c: // No Array of Array in DAP4 either...
941 case dods_grid_c:
942 default:
943 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
944 }
945}
946
947void
948Vector::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter /*= false*/)
949{
950 if (!read_p())
951 read(); // read() throws Error and InternalErr
952#if 0
953 if (filter && !eval.eval_selection(dmr, dataset()))
954 return true;
955#endif
956 int64_t num = length(); // The constrained length in elements
957
958 DBG(cerr << __func__ << ", num: " << num << endl);
959
960 // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16
961 if (num == 0)
962 return;
963
964 switch (d_proto->type()) {
965 case dods_byte_c:
966 case dods_char_c:
967 case dods_int8_c:
968 case dods_uint8_c:
969 m.put_vector(d_buf, num);
970 break;
971
972 case dods_int16_c:
973 case dods_uint16_c:
974 case dods_int32_c:
975 case dods_uint32_c:
976 case dods_int64_c:
977 case dods_uint64_c:
978 m.put_vector(d_buf, num, d_proto->width());
979 break;
980
981 case dods_enum_c:
982 if (d_proto->width() == 1)
983 m.put_vector(d_buf, num);
984 else
985 m.put_vector(d_buf, num, d_proto->width());
986 break;
987
988 case dods_float32_c:
989 m.put_vector_float32(d_buf, num);
990 break;
991
992 case dods_float64_c:
993 m.put_vector_float64(d_buf, num);
994 break;
995
996 case dods_str_c:
997 case dods_url_c:
998 assert((int64_t)d_str.capacity() >= num);
999
1000 for (int64_t i = 0; i < num; ++i)
1001 m.put_str(d_str[i]);
1002
1003 break;
1004
1005 case dods_array_c:
1006 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1007
1008 case dods_opaque_c:
1009 case dods_structure_c:
1010 case dods_sequence_c:
1011 assert(d_compound_buf.capacity() >= 0);
1012
1013 for (int64_t i = 0; i < num; ++i) {
1014 DBG(cerr << __func__ << "d_compound_buf[" << i << "] " << d_compound_buf[i] << endl);
1015 d_compound_buf[i]->serialize(m, dmr, filter);
1016 }
1017
1018 break;
1019
1020 case dods_grid_c:
1021 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1022
1023 default:
1024 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
1025 }
1026
1027#ifdef CLEAR_LOCAL_DATA
1029#endif
1030}
1031
1032void
1034{
1035 if (m_is_cardinal_type()) {
1036 if (d_buf)
1038 if (!d_buf)
1040 }
1041
1042 DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl);
1043
1044 // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16
1045 if (length() == 0)
1046 return;
1047
1048 switch (d_proto->type()) {
1049 case dods_byte_c:
1050 case dods_char_c:
1051 case dods_int8_c:
1052 case dods_uint8_c:
1053 um.get_vector((char *)d_buf, length());
1054 break;
1055
1056 case dods_int16_c:
1057 case dods_uint16_c:
1058 case dods_int32_c:
1059 case dods_uint32_c:
1060 case dods_int64_c:
1061 case dods_uint64_c:
1062 um.get_vector((char *)d_buf, length(), d_proto->width());
1063 break;
1064
1065 case dods_enum_c:
1066 if (d_proto->width() == 1)
1067 um.get_vector((char *)d_buf, length());
1068 else
1069 um.get_vector((char *)d_buf, length(), d_proto->width());
1070 break;
1071
1072 case dods_float32_c:
1073 um.get_vector_float32((char *)d_buf, length());
1074 break;
1075
1076 case dods_float64_c:
1077 um.get_vector_float64((char *)d_buf, length());
1078 break;
1079
1080 case dods_str_c:
1081 case dods_url_c: {
1082 int64_t len = length();
1083 d_str.resize((len > 0) ? len : 0); // Fill with NULLs
1084 d_capacity = len; // capacity is number of strings we can fit.
1085
1086 for (int64_t i = 0; i < len; ++i) {
1087 um.get_str(d_str[i]);
1088 }
1089
1090 break;
1091 }
1092
1093 case dods_array_c:
1094 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1095
1096 case dods_opaque_c:
1097 case dods_structure_c:
1098 case dods_sequence_c: {
1099 vec_resize(length());
1100
1101 for (int64_t i = 0, end = length(); i < end; ++i) {
1102 d_compound_buf[i] = d_proto->ptr_duplicate();
1103 d_compound_buf[i]->deserialize(um, dmr);
1104 }
1105
1106 break;
1107 }
1108
1109 case dods_grid_c:
1110 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1111
1112 default:
1113 throw InternalErr(__FILE__, __LINE__, "Unknown type.");
1114 }
1115}
1116
1144unsigned int Vector::val2buf(void *val, bool reuse)
1145{
1146 // Jose Garcia
1147
1148 // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
1149 if (!val && length() == 0)
1150 return 0;
1151
1152 // I *think* this method has been mainly designed to be use by read which
1153 // is implemented in the surrogate library. Passing NULL as a pointer to
1154 // this method will be an error of the creator of the surrogate library.
1155 // Even though I recognize the fact that some methods inside libdap++ can
1156 // call val2buf, I think by now no coding bugs such as misusing val2buf
1157 // will be in libdap++, so it will be an internal error from the
1158 // surrogate library.
1159 if (!val)
1160 throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
1161
1162 switch (d_proto->type()) {
1163 case dods_byte_c:
1164 case dods_char_c:
1165 case dods_int8_c:
1166 case dods_uint8_c:
1167 case dods_int16_c:
1168 case dods_uint16_c:
1169 case dods_int32_c:
1170 case dods_uint32_c:
1171 case dods_int64_c:
1172 case dods_uint64_c:
1173
1174 case dods_enum_c:
1175
1176 case dods_float32_c:
1177 case dods_float64_c:
1178#if 0
1179 if (d_buf && !reuse)
1181#endif
1182 // First time or no reuse (free'd above)
1183 if (!d_buf || !reuse)
1185
1186 // width(true) returns the size in bytes given the constraint
1187 if (d_buf)
1188 memcpy(d_buf, val, width(true));
1189 break;
1190
1191 case dods_str_c:
1192 case dods_url_c:
1193 // Assume val points to an array of C++ string objects. Copy
1194 // them into the vector<string> field of this object.
1195 // Note: d_length is the number of elements in the Vector
1196 d_str.resize(d_length);
1197 d_capacity = d_length;
1198 for (int i = 0; i < d_length; ++i)
1199 d_str[i] = *(static_cast<string *> (val) + i);
1200
1201 break;
1202
1203 default:
1204 throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1205
1206 }
1207
1208 return width(true);
1209}
1210
1249unsigned int Vector::buf2val(void **val)
1250{
1251 // Jose Garcia
1252 // The same comment in Vector::val2buf applies here!
1253 if (!val)
1254 throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1255
1256 unsigned int wid = static_cast<unsigned int> (width(true /* constrained */));
1257
1258 // This is the width computed using length(). The
1259 // length() property is changed when a projection
1260 // constraint is applied. Thus, this is the number of
1261 // bytes in the buffer given the current constraint.
1262
1263 switch (d_proto->type()) {
1264 case dods_byte_c:
1265 case dods_char_c:
1266 case dods_int8_c:
1267 case dods_uint8_c:
1268 case dods_int16_c:
1269 case dods_uint16_c:
1270 case dods_int32_c:
1271 case dods_uint32_c:
1272 case dods_int64_c:
1273 case dods_uint64_c:
1274
1275 case dods_enum_c:
1276
1277 case dods_float32_c:
1278 case dods_float64_c:
1279 if (!d_buf)
1280 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1281 if (!*val)
1282 *val = new char[wid];
1283
1284 memcpy(*val, d_buf, wid);
1285 return wid;
1286
1287 case dods_str_c:
1288 case dods_url_c: {
1289 if (d_str.empty())
1290 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
1291 if (!*val)
1292 *val = new string[d_length];
1293
1294 for (int i = 0; i < d_length; ++i)
1295 *(static_cast<string *> (*val) + i) = d_str[i];
1296
1297 return width();
1298 }
1299
1300 default:
1301 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1302 }
1303
1304 //return wid;
1305}
1306
1327void Vector::set_vec(unsigned int i, BaseType * val)
1328{
1329 Vector::set_vec_nocopy(i, val->ptr_duplicate());
1330}
1331
1343void Vector::set_vec_nocopy(unsigned int i, BaseType * val)
1344{
1345 // Jose Garcia
1346 // This is a public method which allows users to set the elements
1347 // of *this* vector. Passing an invalid index, a NULL pointer or
1348 // mismatching the vector type are internal errors.
1349 if (i >= static_cast<unsigned int> (d_length))
1350 throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1351 if (!val)
1352 throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1353 if (val->type() != d_proto->type())
1354 throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
1355
1356 // This code originally used capacity() instead of size(), but that was an error.
1357 // Use capacity() when using reserve() and size() when using resize(). Mixing
1358 // capacity() with resize() leaves holes in the data, where (pointer) values are
1359 // filled with nulls during successive calls to resize(). The resize() heuristic
1360 // remembers previous calls on a given vector<> and allocates larger than requested
1361 // blocks of memory on successive calls, which has the strange affect of erasing
1362 // values already in the vector in the parts just added.
1363 // jhrg 5/18/17
1364 if (i >= d_compound_buf.size()) {
1365 vec_resize(d_compound_buf.size() + 100);
1366 }
1367
1368 d_compound_buf[i] = val;
1369}
1370
1381{
1382 if (d_buf) {
1383 delete[] d_buf;
1384 d_buf = 0;
1385 }
1386
1387 for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
1388 delete d_compound_buf[i];
1389 d_compound_buf[i] = 0;
1390 }
1391
1392 // Force memory to be reclaimed.
1393 d_compound_buf.resize(0);
1394 d_str.resize(0);
1395
1396 d_capacity = 0;
1397 set_read_p(false);
1398}
1399
1407unsigned int Vector::get_value_capacity() const
1408{
1409 return d_capacity;
1410}
1411
1421void Vector::reserve_value_capacity(unsigned int numElements)
1422{
1423 if (!d_proto) {
1424 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1425 }
1426 switch (d_proto->type()) {
1427 case dods_byte_c:
1428 case dods_char_c:
1429 case dods_int8_c:
1430 case dods_uint8_c:
1431 case dods_int16_c:
1432 case dods_uint16_c:
1433 case dods_int32_c:
1434 case dods_uint32_c:
1435 case dods_int64_c:
1436 case dods_uint64_c:
1437
1438 case dods_enum_c:
1439
1440 case dods_float32_c:
1441 case dods_float64_c:
1442 // Make _buf be the right size and set _capacity
1444 break;
1445
1446 case dods_str_c:
1447 case dods_url_c:
1448 // Make sure the d_str has enough room for all the strings.
1449 // Technically not needed, but it will speed things up for large arrays.
1450 d_str.reserve(numElements);
1451 d_capacity = numElements;
1452 break;
1453
1454 case dods_array_c:
1455 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1456
1457 case dods_opaque_c:
1458 case dods_structure_c:
1459 case dods_sequence_c:
1460 case dods_grid_c:
1461 // not clear anyone will go this path, but best to be complete.
1462 d_compound_buf.reserve(numElements);
1463 d_capacity = numElements;
1464 break;
1465
1466 default:
1467 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1468 } // switch
1469
1470}
1471
1478{
1479 // Use the current length of the vector as the reserve amount.
1481}
1482
1511unsigned int
1512Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
1513{
1514 static const string funcName = "set_value_slice_from_row_major_vector:";
1515
1516 // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1517 Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
1518
1519 bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
1520 if (!typesMatch) {
1521 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
1522 }
1523
1524 // Make sure the data exists
1525 if (!rowMajorData.read_p()) {
1526 throw InternalErr(__FILE__, __LINE__,
1527 funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1528 }
1529
1530 // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1531 if (rowMajorData.length() < 0) {
1532 throw InternalErr(__FILE__, __LINE__,
1533 funcName
1534 + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
1535 }
1536
1537 // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
1538 // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
1539 if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
1540 throw InternalErr(__FILE__, __LINE__,
1541 funcName
1542 + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1543 }
1544
1545 // Make sure there's enough room in this Vector to store all the elements requested. Again,
1546 // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1547 if (d_capacity < (startElement + rowMajorData.length())) {
1548 throw InternalErr(__FILE__, __LINE__,
1549 funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1550 }
1551
1552 // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1553 switch (d_proto->type()) {
1554 case dods_int8_c:
1555 case dods_uint8_c:
1556 case dods_byte_c:
1557 case dods_char_c:
1558 case dods_int16_c:
1559 case dods_uint16_c:
1560 case dods_int32_c:
1561 case dods_uint32_c:
1562 case dods_int64_c:
1563 case dods_uint64_c:
1564
1565 case dods_enum_c:
1566
1567 case dods_float32_c:
1568 case dods_float64_c: {
1569 if (!d_buf) {
1570 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1571 }
1572 if (!rowMajorData.d_buf) {
1573 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1574 }
1575 // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1576 int varWidth = d_proto->width();
1577 char* pFromBuf = rowMajorData.d_buf;
1578 int numBytesToCopy = rowMajorData.width(true);
1579 char* pIntoBuf = d_buf + (startElement * varWidth);
1580 memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
1581 break;
1582 }
1583
1584 case dods_str_c:
1585 case dods_url_c:
1586 // Strings need to be copied directly
1587 for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
1588 d_str[startElement + i] = rowMajorData.d_str[i];
1589 }
1590 break;
1591
1592 case dods_array_c:
1593 case dods_opaque_c:
1594 case dods_structure_c:
1595 case dods_sequence_c:
1596 case dods_grid_c:
1597 // Not sure that this function will be used for these type of nested objects, so I will throw here.
1598 throw InternalErr(__FILE__, __LINE__,
1599 funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
1600
1601 default:
1602 throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1603 } // switch (_var->type())
1604
1605 // This is how many elements we copied.
1606 return (unsigned int) rowMajorData.length();
1607}
1608
1617template <typename T>
1618static bool types_match(Type t, T *cpp_var)
1619{
1620 switch (t) {
1621 case dods_byte_c:
1622 case dods_char_c:
1623 case dods_uint8_c:
1624 return typeid(cpp_var) == typeid(dods_byte*);
1625
1626 case dods_int8_c:
1627 return typeid(cpp_var) == typeid(dods_int8*);
1628 case dods_int16_c:
1629 return typeid(cpp_var) == typeid(dods_int16*);
1630 case dods_uint16_c:
1631 return typeid(cpp_var) == typeid(dods_uint16*);
1632 case dods_int32_c:
1633 return typeid(cpp_var) == typeid(dods_int32*);
1634 case dods_uint32_c:
1635 return typeid(cpp_var) == typeid(dods_uint32*);
1636 case dods_int64_c:
1637 return typeid(cpp_var) == typeid(dods_int64*);
1638 case dods_uint64_c:
1639 return typeid(cpp_var) == typeid(dods_uint64*);
1640
1641 case dods_float32_c:
1642 return typeid(cpp_var) == typeid(dods_float32*);
1643 case dods_float64_c:
1644 return typeid(cpp_var) == typeid(dods_float64*);
1645
1646 case dods_null_c:
1647 case dods_enum_c:
1648 case dods_str_c:
1649 case dods_url_c:
1650 case dods_opaque_c:
1651 case dods_array_c:
1652 case dods_structure_c:
1653 case dods_sequence_c:
1654 case dods_group_c:
1655 default:
1656 return false;
1657 }
1658}
1659
1661
1663template <typename T>
1664bool Vector::set_value_worker(T *v, int sz)
1665{
1666 if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1667 return false;
1668
1670 return true;
1671}
1672
1673bool Vector::set_value(dods_byte *val, int sz)
1674{
1675 return set_value_worker(val, sz);
1676}
1677bool Vector::set_value(dods_int8 *val, int sz)
1678{
1679 return set_value_worker(val, sz);
1680}
1681bool Vector::set_value(dods_int16 *val, int sz)
1682{
1683 return set_value_worker(val, sz);
1684}
1685bool Vector::set_value(dods_uint16 *val, int sz)
1686{
1687 return set_value_worker(val, sz);
1688}
1689bool Vector::set_value(dods_int32 *val, int sz)
1690{
1691 return set_value_worker(val, sz);
1692}
1693bool Vector::set_value(dods_uint32 *val, int sz)
1694{
1695 return set_value_worker(val, sz);
1696}
1697bool Vector::set_value(dods_int64 *val, int sz)
1698{
1699 return set_value_worker(val, sz);
1700}
1701bool Vector::set_value(dods_uint64 *val, int sz)
1702{
1703 return set_value_worker(val, sz);
1704}
1705bool Vector::set_value(dods_float32 *val, int sz)
1706{
1707 return set_value_worker(val, sz);
1708}
1709bool Vector::set_value(dods_float64 *val, int sz)
1710{
1711 return set_value_worker(val, sz);
1712}
1713
1721bool Vector::set_value(string *val, int sz)
1722{
1723 if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
1724 d_str.resize(sz);
1725 d_capacity = sz;
1726 for (int t = 0; t < sz; t++) {
1727 d_str[t] = val[t];
1728 }
1729 set_length(sz);
1730 set_read_p(true);
1731 return true;
1732 }
1733 else {
1734 return false;
1735 }
1736}
1737
1738template<typename T>
1739bool Vector::set_value_worker(vector<T> &v, int sz)
1740{
1741 return set_value(v.data(), sz);
1742}
1743
1744bool Vector::set_value(vector<dods_byte> &val, int sz)
1745{
1746 return set_value_worker(val, sz);
1747}
1748bool Vector::set_value(vector<dods_int8> &val, int sz)
1749{
1750 return set_value_worker(val, sz);
1751}
1752bool Vector::set_value(vector<dods_int16> &val, int sz)
1753{
1754 return set_value_worker(val, sz);
1755}
1756bool Vector::set_value(vector<dods_uint16> &val, int sz)
1757{
1758 return set_value_worker(val, sz);
1759}
1760bool Vector::set_value(vector<dods_int32> &val, int sz)
1761{
1762 return set_value_worker(val, sz);
1763}
1764bool Vector::set_value(vector<dods_uint32> &val, int sz)
1765{
1766 return set_value_worker(val, sz);
1767}
1768bool Vector::set_value(vector<dods_int64> &val, int sz)
1769{
1770 return set_value_worker(val, sz);
1771}
1772bool Vector::set_value(vector<dods_uint64> &val, int sz)
1773{
1774 return set_value_worker(val, sz);
1775}
1776bool Vector::set_value(vector<dods_float32> &val, int sz)
1777{
1778 return set_value_worker(val, sz);
1779}
1780bool Vector::set_value(vector<dods_float64> &val, int sz)
1781{
1782 return set_value_worker(val, sz);
1783}
1784
1785
1787bool Vector::set_value(vector<string> &val, int sz)
1788{
1789 if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
1790 d_str.resize(sz);
1791 d_capacity = sz;
1792 for (int t = 0; t < sz; t++) {
1793 d_str[t] = val[t];
1794 }
1795 set_length(sz);
1796 set_read_p(true);
1797 return true;
1798 }
1799 else {
1800 return false;
1801 }
1802}
1804
1806
1823template <typename T>
1824void Vector::value_worker(vector<unsigned int> *indices, T *b) const
1825{
1826 // unsigned long currentIndex;
1827#if 0
1828 // Iterator version. Not tested, jhrg 8/14/13
1829 for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
1830 unsigned long currentIndex = *i;
1831 if(currentIndex > (unsigned int)length()){
1832 stringstream s;
1833 s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
1834 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1835 throw Error(s.str());
1836 }
1837 b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
1838 }
1839#endif
1840 for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
1841 unsigned long currentIndex = (*indices)[i];
1842 if (currentIndex > (unsigned int)length()) {
1843 stringstream s;
1844 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1845 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1846 throw Error(s.str());
1847 }
1848 b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
1849 }
1850}
1851void Vector::value(vector<unsigned int> *indices, dods_byte *b) const { value_worker(indices, b); }
1852void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const { value_worker(indices, b); }
1853void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const { value_worker(indices, b); }
1854void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const { value_worker(indices, b); }
1855void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const { value_worker(indices, b); }
1856void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const { value_worker(indices, b); }
1857void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const { value_worker(indices, b); }
1858void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const { value_worker(indices, b); }
1859void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
1860void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
1861
1862#if 0
1863template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
1864template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
1865template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
1866template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
1867template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
1868template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
1869template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
1870template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
1871template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
1872template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
1873#endif
1874
1876void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const
1877{
1878 unsigned long currentIndex;
1879
1880 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
1881 for(unsigned long i=0; i<subsetIndex->size() ;++i){
1882 currentIndex = (*subsetIndex)[i] ;
1883 if(currentIndex > (unsigned int)length()){
1884 stringstream s;
1885 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1886 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1887 throw Error(s.str());
1888 }
1889 b[i] = d_str[currentIndex];
1890 }
1891 }
1892}
1893
1894template <typename T>
1895void Vector::value_worker(T *v) const
1896{
1897 // Only copy if v is not null and the proto's type matches.
1898 // For Enums, use the element type since type == dods_enum_c.
1899 if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1900 memcpy(v, d_buf, length() * sizeof(T));
1901}
1902void Vector::value(dods_byte *b) const { value_worker(b); }
1903void Vector::value(dods_int8 *b) const { value_worker(b); }
1904void Vector::value(dods_int16 *b) const { value_worker(b); }
1905void Vector::value(dods_uint16 *b) const { value_worker(b); }
1906void Vector::value(dods_int32 *b) const { value_worker(b); }
1907void Vector::value(dods_uint32 *b) const { value_worker(b); }
1908void Vector::value(dods_int64 *b) const { value_worker(b); }
1909void Vector::value(dods_uint64 *b) const { value_worker(b); }
1910void Vector::value(dods_float32 *b) const { value_worker(b); }
1911void Vector::value(dods_float64 *b) const { value_worker(b); }
1912
1913#if 0
1914template void Vector::value(dods_byte *v) const;
1915template void Vector::value(dods_int8 *v) const;
1916template void Vector::value(dods_int16 *v) const;
1917template void Vector::value(dods_uint16 *v) const;
1918template void Vector::value(dods_int32 *v) const;
1919template void Vector::value(dods_uint32 *v) const;
1920template void Vector::value(dods_int64 *v) const;
1921template void Vector::value(dods_uint64 *v) const;
1922template void Vector::value(dods_float32 *v) const;
1923template void Vector::value(dods_float64 *v) const;
1924#endif
1925
1926
1928void Vector::value(vector<string> &b) const
1929{
1930 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
1931 b = d_str;
1932}
1933
1937{
1938 void *buffer = new char[width(true)];
1939
1940 memcpy(buffer, d_buf, width(true));
1941
1942 return buffer;
1943}
1945
1962{
1963#if 0
1964 // Why doesn't this work? tried all 3 variants. jhrg 8/14/13
1965 Vector::add_var_nocopy(v->ptr_duplicate(), p);
1966 add_var_nocopy(v->ptr_duplicate(), p);
1967 add_var_nocopy(v->ptr_duplicate());
1968#else
1969 // Delete the current template variable
1970 if (d_proto) {
1971 delete d_proto;
1972 d_proto = 0;
1973 }
1974
1975 // if 'v' is null, just set _var to null and exit.
1976 if (!v) {
1977 d_proto = 0;
1978 }
1979 else {
1980 // Jose Garcia
1981 // By getting a copy of this object to be assigned to _var
1982 // we let the owner of 'v' to deallocate it as necessary.
1983 d_proto = v->ptr_duplicate();
1984
1985 // If 'v' has a name, use it as the name of the array. If v doesn't have
1986 // a name, then make sure to copy the array's name to it
1987 // so that software which uses the template's name will still work.
1988 if (!v->name().empty())
1989 set_name(v->name());
1990 else
1991 d_proto->set_name(name());
1992
1993 d_proto->set_parent(this); // Vector --> child
1994
1995 DBG(cerr << "Vector::add_var: Added variable " << v << " ("
1996 << v->name() << " " << v->type_name() << ")" << endl);
1997 }
1998#endif
1999}
2000
2001void Vector::add_var_nocopy(BaseType * v, Part)
2002{
2003 // Delete the current template variable
2004 if (d_proto) {
2005 delete d_proto;
2006 d_proto = 0;
2007 }
2008
2009 // if 'v' is null, just set _var to null and exit.
2010 if (!v) {
2011 d_proto = 0;
2012 }
2013 else {
2014 d_proto = v;
2015
2016 // If 'v' has a name, use it as the name of the array. If it *is*
2017 // empty, then make sure to copy the array's name to the template
2018 // so that software which uses the template's name will still work.
2019 if (!v->name().empty())
2020 set_name(v->name());
2021 else
2022 d_proto->set_name(name());
2023
2024 d_proto->set_parent(this); // Vector is the parent; proto is the child
2025
2026 DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " ("
2027 << v->name() << " " << v->type_name() << ")" << endl);
2028 }
2029}
2030
2031bool Vector::check_semantics(string & msg, bool)
2032{
2033 return BaseType::check_semantics(msg);
2034}
2035
2044void Vector::dump(ostream &strm) const
2045{
2046 strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
2047 DapIndent::Indent();
2048 BaseType::dump(strm);
2049 strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
2050 if (d_proto) {
2051 strm << DapIndent::LMarg << "base type:" << endl;
2052 DapIndent::Indent();
2053 d_proto->dump(strm);
2054 DapIndent::UnIndent();
2055 }
2056 else {
2057 strm << DapIndent::LMarg << "base type: not set" << endl;
2058 }
2059 strm << DapIndent::LMarg << "vector contents:" << endl;
2060 DapIndent::Indent();
2061 for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
2062 if (d_compound_buf[i])
2063 d_compound_buf[i]->dump(strm);
2064 else
2065 strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
2066 }
2067 DapIndent::UnIndent();
2068 strm << DapIndent::LMarg << "strings:" << endl;
2069 DapIndent::Indent();
2070 for (unsigned i = 0; i < d_str.size(); i++) {
2071 strm << DapIndent::LMarg << d_str[i] << endl;
2072 }
2073 DapIndent::UnIndent();
2074 if (d_buf) {
2075 switch (d_proto != 0 ? d_proto->type() : 0) {
2076 case dods_byte_c:
2077 case dods_char_c:
2078 strm << DapIndent::LMarg << "_buf: ";
2079 strm.write(d_buf, d_length);
2080 strm << endl;
2081 break;
2082
2083 case 0:
2084 default:
2085 strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl;
2086 break;
2087 }
2088 }
2089 else {
2090 strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
2091 }
2092
2093 DapIndent::UnIndent();
2094}
2095
2096} // namespace libdap
2097
Definition crc.h:77
void AddData(const uint8_t *pData, const uint32_t length)
Definition crc.h:98
The basic data type for the DODS DAP types.
Definition BaseType.h:118
virtual string type_name() const
Returns the type of the class instance as a string.
Definition BaseType.cc:375
virtual bool read()
Read data into a local buffer.
Definition BaseType.cc:895
virtual string name() const
Returns the name of the class instance.
Definition BaseType.cc:316
virtual bool read_p()
Has this variable been read?
Definition BaseType.cc:476
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:1295
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition BaseType.cc:512
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition BaseType.cc:354
virtual void set_parent(BaseType *parent)
Definition BaseType.cc:729
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition BaseType.cc:439
void dump(ostream &strm) const override
dumps information about this object
Definition BaseType.cc:287
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition BaseType.cc:340
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:408
virtual void set_send_p(bool state)
Definition BaseType.cc:564
virtual BaseType * ptr_duplicate()=0
virtual unsigned int val2buf(void *val, bool reuse=false)=0
Loads class data.
virtual void compute_checksum(Crc32 &checksum)=0
include the data for this variable in the checksum DAP4 includes a checksum with every data response....
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition BaseType.cc:1205
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=nullptr)
Returns a pointer to a member of a constructor class.
Definition BaseType.cc:754
virtual Type type() const
Returns the type of the class instance.
Definition BaseType.cc:361
Evaluate a constraint expression.
bool eval_selection(DDS &dds, const std::string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator and is called ...
Holds a DAP4 enumeration.
Definition D4Enum.h:56
Marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using DAP4's receiv...
Read data from the stream made by D4StreamMarshaller.
A class for error processing.
Definition Error.h:94
A class for software fault reporting.
Definition InternalErr.h:65
abstract base class used to marshal/serialize dap data objects
Definition Marshaller.h:50
abstract base class used to unmarshall/deserialize dap data objects
Holds a one-dimensional collection of DAP2 data types.
Definition Vector.h:81
virtual void add_var(BaseType *v, Part p=nil)
Add the BaseType pointer to this constructor type instance.
Definition Vector.cc:1961
virtual void set_length(int l)
Definition Vector.cc:555
virtual unsigned int get_value_capacity() const
Definition Vector.cc:1407
void set_vec_nocopy(unsigned int i, BaseType *val)
Sets element i to value val. Set the ith element to val. Extend the vector if needed.
Definition Vector.cc:1343
void m_set_cardinal_values_internal(const CardType *fromArray, int numElts)
Definition Vector.cc:221
virtual int length() const
Definition Vector.cc:548
virtual unsigned int set_value_slice_from_row_major_vector(const Vector &rowMajorData, unsigned int startElement)
Definition Vector.cc:1512
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
Definition Vector.cc:391
virtual void set_send_p(bool state)
Indicates that the data is ready to send.
Definition Vector.cc:354
void set_vec(unsigned int i, BaseType *val)
Sets element i to value val.
Definition Vector.cc:1327
virtual unsigned int width(bool constrained=false) const
Returns the width of the data, in bytes.
Definition Vector.cc:536
virtual unsigned int val2buf(void *val, bool reuse=false)
Reads data into the Vector buffer.
Definition Vector.cc:1144
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Serialize a Vector.
Definition Vector.cc:661
virtual void compute_checksum(Crc32 &checksum)
include the data for this variable in the checksum DAP4 includes a checksum with every data response....
Definition Vector.cc:858
virtual void dump(ostream &strm) const
dumps information about this object
Definition Vector.cc:2044
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition Vector.cc:433
virtual void set_name(const std::string &name)
Sets the name of the class instance.
Definition Vector.cc:323
virtual int element_count(bool leaves)
Count the members of constructor types.
Definition Vector.cc:333
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition Vector.cc:755
virtual void intern_data()
Read data into this variable.
Definition Vector.cc:900
bool m_is_cardinal_type() const
Definition Vector.cc:127
virtual void clear_local_data()
Definition Vector.cc:1380
virtual void * value()
Definition Vector.cc:1936
void vec_resize(int l)
Definition Vector.cc:568
void m_delete_cardinal_data_buffer()
Definition Vector.cc:210
virtual void reserve_value_capacity()
Definition Vector.cc:1477
unsigned int m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
Definition Vector.cc:182
virtual unsigned int buf2val(void **val)
Copies data from the Vector buffer.
Definition Vector.cc:1249
Vector(const string &n, BaseType *v, const Type &t, bool is_dap4=false)
The Vector constructor.
Definition Vector.cc:251
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition Vector.cc:2031
top level DAP object to house generic methods
Type
Identifies the data type.
Definition Type.h:94
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