libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
Vector.cc
Go to the documentation of this file.
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2002,2003 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
25// (c) COPYRIGHT URI/MIT 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 <cassert>
39#include <cstdint>
40#include <cstring>
41
42#include <algorithm>
43#include <sstream>
44#include <typeinfo>
45#include <vector>
46
47#include "crc.h"
48
49#include "Marshaller.h"
50#include "UnMarshaller.h"
51#include "Vector.h"
52
53#include "D4StreamMarshaller.h"
55
56#include "D4Enum.h"
57
58#include "DapIndent.h"
59#include "InternalErr.h"
60#include "Type.h"
61#include "debug.h"
62#include "dods-datatypes.h"
63#include "dods-limits.h"
64#include "escaping.h"
65
66#undef CLEAR_LOCAL_DATA
67
68using std::cerr;
69using std::endl;
70
71namespace libdap {
72
73void Vector::m_duplicate(const Vector &v) {
74 d_length = v.d_length;
75 d_length_ll = v.d_length_ll;
76
77 // _var holds the type of the elements. That is, it holds a BaseType
78 // which acts as a template for the type of each element.
79 if (v.d_proto) {
80 // Vector manages this ptr, delete before assigning a new object. jhrg 2/19/22
81 if (d_proto)
82 delete d_proto;
83 d_proto = v.d_proto->ptr_duplicate(); // use ptr_duplicate()
84 d_proto->set_parent(this); // ptr_duplicate does not set d_parent.
85 } else {
86 d_proto = nullptr;
87 }
88
89 // d_compound_buf and d_buf (further down) hold the values of the Vector. The field
90 // d_compound_buf is used when the Vector holds non-numeric data (including strings,
91 // although it used to be that was not the case jhrg 2/10/05) while d_buf
92 // holds numeric values.
93 if (v.d_compound_buf.empty()) {
94 d_compound_buf = v.d_compound_buf;
95 } else {
96 // Failure to set the size will make the [] operator barf on the LHS
97 // of the assignment inside the loop.
98 d_compound_buf.resize(d_length);
99 for (int i = 0; i < d_length; ++i) {
100 // There's no need to call set_parent() for each element; we
101 // maintain the back pointer using the d_proto member. These
102 // instances are used to hold _values_ only while the d_proto
103 // field holds the type information for the elements.
104 d_compound_buf[i] = v.d_compound_buf[i]->ptr_duplicate();
105 }
106 }
107
108 // copy the strings. This copies the values.
109 d_str = v.d_str;
110
111 // copy numeric values if there are any.
112 d_buf = 0; // init to null
113 if (v.d_buf) // only copy if data present
114 val2buf(v.d_buf); // store v's value in this's _BUF.
115
116 d_capacity = v.d_capacity;
117 d_capacity_ll = v.d_capacity_ll;
118}
119
124bool Vector::m_is_cardinal_type() const {
125 // Not cardinal if no d_proto at all!
126 if (!d_proto) {
127 return false;
128 }
129
130 switch (d_proto->type()) {
131 case dods_byte_c:
132 case dods_char_c:
133 case dods_int16_c:
134 case dods_uint16_c:
135 case dods_int32_c:
136 case dods_uint32_c:
137 case dods_float32_c:
138 case dods_float64_c:
139 // New cardinal types for DAP4
140 case dods_int8_c:
141 case dods_uint8_c:
142 case dods_int64_c:
143 case dods_uint64_c:
144
145 case dods_enum_c:
146 return true;
147
148 // These must be handled differently.
149 case dods_str_c:
150 case dods_url_c:
151 case dods_opaque_c:
152
153 case dods_array_c:
154
155 case dods_structure_c:
156 case dods_sequence_c:
157 case dods_grid_c:
158 return false;
159
160 default:
161 assert("Vector::var: Unrecognized type");
162 return false;
163 }
164}
165
178int64_t Vector::m_create_cardinal_data_buffer_for_type(int64_t num_elements) {
179 // Make sure we HAVE a _var, or we cannot continue.
180 if (!d_proto) {
181 throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
182 }
183
184 // Make sure we only do this for the correct data types.
185 if (!m_is_cardinal_type()) {
186 throw InternalErr(__FILE__, __LINE__,
187 "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a "
188 "cardinal (simple data types).");
189 }
190
191 // Handle this special case where this is an array that holds no values
192 if (num_elements == 0)
193 return 0;
194
195 m_delete_cardinal_data_buffer();
196
197 // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
198#if 0
199 unsigned int bytesPerElt = d_proto->width();
200 unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
201#endif
202 int64_t bytesNeeded = d_proto->width_ll() * num_elements;
203 d_buf = new char[bytesNeeded];
204
205#if 0
206 d_capacity = (unsigned long long)num_elements;
207#endif
208 set_value_capacity((uint64_t)num_elements);
209 return bytesNeeded;
210}
211
213void Vector::m_delete_cardinal_data_buffer() {
214 delete[] d_buf;
215 d_buf = nullptr;
216 d_capacity = 0;
217 d_capacity_ll = 0;
218}
219
223template <class CardType> void Vector::m_set_cardinal_values_internal(const CardType *fromArray, int64_t numElts) {
224 if (numElts < 0) {
225 throw InternalErr(__FILE__, __LINE__,
226 "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
227 }
228 if (!fromArray) {
229 throw InternalErr(__FILE__, __LINE__,
230 "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
231 }
232 set_length_ll(numElts);
233 m_create_cardinal_data_buffer_for_type(numElts);
234 if (d_buf)
235 memcpy(d_buf, fromArray, numElts * sizeof(CardType));
236 set_read_p(true);
237}
238
254Vector::Vector(const string &n, BaseType *v, const Type &t, bool is_dap4 /* default:false */)
255 : BaseType(n, t, is_dap4) {
256 if (v)
257 add_var(v);
258
259 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
260 if (d_proto)
261 d_proto->set_parent(this);
262}
263
282Vector::Vector(const string &n, const string &d, BaseType *v, const Type &t, bool is_dap4 /* default:false */)
283 : BaseType(n, d, t, is_dap4) {
284 if (v)
285 add_var(v);
286
287 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
288 if (d_proto)
289 d_proto->set_parent(this);
290}
291
294 : BaseType(rhs)
295
296{
297 DBG2(cerr << "Entering Vector const ctor for object: " << this << endl);
298 DBG2(cerr << "RHS: " << &rhs << endl);
299
300 m_duplicate(rhs);
301}
302
304 delete d_proto;
305 d_proto = nullptr;
306
307 // Clears all buffers
308 try {
310 } catch (const std::exception &) {
311 // It's hard to know what to do - Log it when we can, but that can fail, too.
312 }
313}
314
316 if (this == &rhs)
317 return *this;
319 m_duplicate(rhs);
320 return *this;
321}
322
323void Vector::set_name(const std::string &name) {
325 // We need to set the prototype name as well since
326 // this is what gets output in the dds! Otherwise, there's a mismatch.
327 if (d_proto) {
328 d_proto->set_name(name);
329 }
330}
331
332int Vector::element_count(bool leaves) {
333 if (!leaves)
334 return 1;
335 else
336 return d_proto->element_count(leaves);
337 // var() only works for simple types!
338 // jhrg 8/19/13 return var(0)->element_count(leaves);
339}
340
341// These mfuncs set the _send_p and _read_p fields of BaseType. They differ
342// from BaseType's version in that they set both the Vector object's copy of
343// _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
344// is a scalar, but does matter when it is an aggregate.
345
352void Vector::set_send_p(bool state) {
353 if (d_proto) {
354 d_proto->set_send_p(state);
355
356 // because some code may depend on the BaseType*s held in d_compound_buf
357 // behaving as if they are 'ordinary' DAP variables, make sure their send_p
358 // flag is set if they exist. Because space in the vector is allocated
359 // before values (BaseType*s) are added, check for nulls and limit the
360 // iteration to only those elements actually in the object including any
361 // constraints that may have been applied - these are values not declarations.
362 // jhrg 5/13/16
363 switch (d_proto->type()) {
364 case dods_structure_c:
365 case dods_sequence_c:
366 case dods_grid_c:
367 if (d_compound_buf.size() > 0) {
368 for (unsigned long long i = 0; i < (unsigned)d_length; ++i) {
369 if (d_compound_buf[i])
370 d_compound_buf[i]->set_send_p(state);
371 }
372 }
373 break;
374
375 default:
376 break;
377 }
378 }
379
381}
382
389void Vector::set_read_p(bool state) {
390 if (d_proto) {
391 d_proto->set_read_p(state);
392
393 // See comment above.
394 switch (d_proto->type()) {
395 case dods_structure_c:
396 case dods_sequence_c:
397 case dods_grid_c:
398 if (d_compound_buf.size() > 0) {
399 for (unsigned long long i = 0; i < (unsigned)d_length; ++i) {
400 if (d_compound_buf[i])
401 d_compound_buf[i]->set_read_p(state);
402 }
403 }
404 break;
405
406 default:
407 break;
408 }
409 }
410
412}
413
424
432void Vector::set_length_ll(int64_t l) {
433 d_length_ll = l;
434 if (l <= DODS_INT_MAX)
435 d_length = (int)l;
436 else {
437 d_length = -1;
438 d_too_big_for_dap2 = true;
439 }
440}
441
443 d_capacity_ll = l;
444 if (l <= DODS_UINT_MAX)
445 d_capacity = (unsigned int)l;
446 else {
447 d_capacity = 0;
448 d_too_big_for_dap2 = true;
449 }
450}
451
469BaseType *Vector::var(const string &n, bool exact, btp_stack *s) {
470 string name = www2id(n);
471 DBG2(cerr << "Vector::var: Looking for " << name << endl);
472
473 if (name.empty() || d_proto->name() == name) {
474 if (s)
475 s->push(this);
476 return d_proto;
477 }
478
479 // If this is a Vector of constructor types, look for 'name' recursively.
480 // Make sure to check for the case where name is the default (the empty
481 // string). 9/1/98 jhrg
482 if (d_proto->is_constructor_type()) {
483 BaseType *result = d_proto->var(name, exact, s);
484 if (result && s)
485 s->push(this);
486 return result;
487 }
488
489 return NULL;
490}
491
502BaseType *Vector::var(const string &n, btp_stack &s) {
503 string name = www2id(n);
504
505 if (d_proto->is_constructor_type())
506 return d_proto->var(name, s);
507 else {
508 s.push((BaseType *)this);
509 return d_proto;
510 }
511}
512
524#if 0
525BaseType *Vector::var(unsigned int i)
526{
527 switch (d_proto->type()) {
528 case dods_byte_c:
529 case dods_char_c:
530 case dods_int8_c:
531 case dods_uint8_c:
532 case dods_int16_c:
533 case dods_uint16_c:
534 case dods_int32_c:
535 case dods_uint32_c:
536 case dods_int64_c:
537 case dods_uint64_c:
538
539 case dods_enum_c:
540
541 case dods_float32_c:
542 case dods_float64_c:
543 // Transfer the ith value to the BaseType *d_proto
544 d_proto->val2buf(d_buf + (i * (uint64_t)d_proto->width_ll()));
545 return d_proto;
546
547 case dods_str_c:
548 case dods_url_c:
549 d_proto->val2buf(&d_str[i]);
550 return d_proto;
551
552 case dods_opaque_c:
553 case dods_array_c:
554 case dods_structure_c:
555 case dods_sequence_c:
556 case dods_grid_c:
557 return d_compound_buf[i];
558
559 default:
560 throw Error ("Vector::var: Unrecognized type");
561 }
562}
563#endif
564
565BaseType *Vector::var(unsigned int i) { return var_ll(i); }
566
568 switch (d_proto->type()) {
569 case dods_byte_c:
570 case dods_char_c:
571 case dods_int8_c:
572 case dods_uint8_c:
573 case dods_int16_c:
574 case dods_uint16_c:
575 case dods_int32_c:
576 case dods_uint32_c:
577 case dods_int64_c:
578 case dods_uint64_c:
579
580 case dods_enum_c:
581
582 case dods_float32_c:
583 case dods_float64_c:
584 // Transfer the ith value to the BaseType *d_proto
585 d_proto->val2buf(d_buf + (i * (uint64_t)d_proto->width_ll()));
586 return d_proto;
587
588 case dods_str_c:
589 case dods_url_c:
590 d_proto->val2buf(&d_str[i]);
591 return d_proto;
592
593 case dods_opaque_c:
594 case dods_array_c:
595 case dods_structure_c:
596 case dods_sequence_c:
597 case dods_grid_c:
598 return d_compound_buf[i];
599
600 default:
601 throw Error("Vector::var: Unrecognized type");
602 }
603}
604
614 // I added this check, which alters the behavior of the method. jhrg 8/14/13
615 if (m_is_cardinal_type())
616 throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
617
618 // Use resize() since other parts of the code use operator[]. Note that size() should
619 // be used when resize() is used. Using capacity() creates problems as noted in the
620 // comment in set_vec_nocopy(). jhrg 5/19/17
621 d_compound_buf.resize(l, 0); // Fill with NULLs
622#if 0
623 d_capacity = d_compound_buf.size(); // size in terms of number of elements.
624#endif
625 set_value_capacity(d_compound_buf.size());
626}
627
628void Vector::vec_resize_ll(int64_t l) {
629 // I added this check, which alters the behavior of the method. jhrg 8/14/13
630 if (m_is_cardinal_type())
631 throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
632
633 // Use resize() since other parts of the code use operator[]. Note that size() should
634 // be used when resize() is used. Using capacity() creates problems as noted in the
635 // comment in set_vec_nocopy(). jhrg 5/19/17
636 d_compound_buf.resize(l, nullptr); // Fill with NULLs
637#if 0
638 d_capacity = d_compound_buf.size(); // size in terms of number of elements.
639#endif
640 set_value_capacity(d_compound_buf.size());
641}
642
659 DBG(cerr << "Vector::intern_data: " << name() << endl);
660 if (is_dap4())
661 throw Error(string("A method usable only with DAP2 variables was called on a DAP4 variable (")
662 .append(name())
663 .append(")."),
664 __FILE__, __LINE__);
665
666 if (!read_p())
667 read(); // read() throws Error and InternalErr
668
669 // length() is not capacity; it must be set explicitly in read().
670 int num = length();
671
672 switch (d_proto->type()) {
673 case dods_byte_c:
674 case dods_int16_c:
675 case dods_uint16_c:
676 case dods_int32_c:
677 case dods_uint32_c:
678 case dods_float32_c:
679 case dods_float64_c:
680 // For these cases, read() puts the data into d_buf,
681 // which is what we need.
682 break;
683
684 case dods_str_c:
685 case dods_url_c:
686 // For these cases, read() will put the data into d_str[],
687 // which is also what we need.
688 break;
689
690 case dods_array_c:
691 // This is an error since there can never be an Array of Array.
692 throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
693
694 case dods_structure_c:
695 case dods_sequence_c:
696 case dods_grid_c:
697 DBG(cerr << "Vector::intern_data: found ctor" << endl);
698 // For these cases, we need to call read() for each of the 'num'
699 // elements in the 'd_compound_buf[]' array of BaseType object pointers.
700 //
701 // I changed the test here from '... = 0' to '... < num' to accommodate
702 // the case where the array is zero-length.
703 if (d_compound_buf.capacity() < (unsigned)num)
704 throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements.");
705
706 for (int i = 0; i < num; ++i)
707 d_compound_buf[i]->intern_data(eval, dds);
708
709 break;
710
711 default:
712 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
713 }
714}
715
726bool Vector::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval) {
727 // Add protection against calling this with DAP4 types. Technically not needed,
728 // but the 'Unknown Datatype' message is not very useful. jhrg 7/28/22
729 if (is_dap4())
730 throw Error(string("A method usable only with DAP2 variables was called on a DAP4 variable (")
731 .append(name())
732 .append(")."),
733 __FILE__, __LINE__);
734
735 if (d_too_big_for_dap2)
736 throw Error("Trying to send a variable that is too large for DAP2.", __FILE__, __LINE__);
737
738 // Added to streamline zero-length arrays. Not needed for correct function,
739 // but explicitly handling this case here makes the code easier to follow.
740 // In libdap::Vector::val2buf() there is a test that will catch the zero-length
741 // case as well. We still need to call serialize since it will write size
742 // information that the client depends on. jhrg 2/17/16
743 if (length() == 0)
744 set_read_p(true);
745 else if (!read_p())
746 read(); // read() throws Error and InternalErr
747
748 if (ce_eval && !eval.eval_selection(dds, dataset()))
749 return true;
750
751 // length() is not capacity; it must be set explicitly in read().
752 int num = length();
753
754 bool status = false;
755
756 switch (d_proto->type()) {
757 case dods_byte_c:
758 m.put_vector(d_buf, num, *this);
759 status = true;
760 break;
761
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 assert((int)d_proto->width_ll() == d_proto->width_ll());
769 m.put_vector(d_buf, num, (int)d_proto->width_ll(), *this);
770 status = true;
771
772 break;
773
774 case dods_str_c:
775 case dods_url_c:
776 if (d_str.capacity() == 0)
777 throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
778
779 m.put_int(num);
780
781 for (int i = 0; i < num; ++i)
782 m.put_str(d_str[i]);
783
784 status = true;
785 break;
786
787 case dods_array_c:
788 case dods_structure_c:
789 case dods_sequence_c:
790 case dods_grid_c:
791 // Jose Garcia
792 // Not setting the capacity of d_compound_buf is an internal error.
793 if (d_compound_buf.capacity() == 0)
794 throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
795
796 m.put_int(num);
797 status = true;
798 for (int i = 0; i < num && status; ++i)
799 status = status && d_compound_buf[i]->serialize(eval, dds, m, false);
800
801 break;
802
803 default:
804 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
805 }
806
807#ifdef CLEAR_LOCAL_DATA
809#endif
810
811 return status;
812}
813
814// Read an object from the network and internalize it. For a Vector this is
815// handled differently for a `cardinal' type. Vectors of Cardinals are
816// stored using the `C' representations because these objects often are used
817// to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
818// arrays of non-cardinal types are stored as Vectors of the C++ objects or
819// DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
820// Grid are vectors of the libdap Structure, ... classes).
821//
822// The boolean parameter REUSE determines whether internal storage is reused
823// or not. If true, the _buf member is assumed to be large enough to hold the
824// incoming cardinal data and is *not* reallocated. If false, new storage is
825// allocated. If the internal buffer has not yet been allocated, then this
826// parameter has no effect (i.e., storage is allocated). This parameter
827// effects storage for cardinal data only.
828//
829// Returns: True is successful, false otherwise.
830
831bool Vector::deserialize(UnMarshaller &um, DDS *dds, bool reuse) {
832 unsigned int num;
833 unsigned i = 0;
834
835 if (is_dap4())
836 throw Error(string("A method usable only with DAP2 variables was called on a DAP4 variable (")
837 .append(name())
838 .append(")."),
839 __FILE__, __LINE__);
840
841 switch (d_proto->type()) {
842 case dods_byte_c:
843 case dods_int16_c:
844 case dods_uint16_c:
845 case dods_int32_c:
846 case dods_uint32_c:
847 case dods_float32_c:
848 case dods_float64_c:
849 um.get_int((int &)num);
850
851 DBG(cerr << "Vector::deserialize: num = " << num << endl);
852 DBG(cerr << "Vector::deserialize: length = " << length() << endl);
853
854 if (length() == -1)
855 set_length(num);
856
857 if (num != (unsigned int)length())
858 throw InternalErr(__FILE__, __LINE__,
859 "The server sent declarations and data with mismatched sizes for the variable '" +
860 name() + "'.");
861
862 if (!d_buf || !reuse) {
863 // Make d_buf be large enough for length_ll() elements of _var->type()
864 // m_create...() deletes the old buffer.
865 m_create_cardinal_data_buffer_for_type(length_ll());
866 }
867
868 // Added to accommodate zero-length arrays.
869 // Note that the rest of the cases will just send the size without data
870 // but that these calls trigger error testing in the UnMarshaller code.
871 // jhrg 1/28/16
872 if (num == 0)
873 return true;
874
875 if (d_proto->type() == dods_byte_c)
876 um.get_vector((char **)&d_buf, num, *this);
877 else {
878 assert((int)d_proto->width_ll() == d_proto->width_ll());
879 um.get_vector((char **)&d_buf, num, d_proto->width_ll(), *this);
880 }
881 break;
882
883 case dods_str_c:
884 case dods_url_c:
885 um.get_int((int &)num);
886
887 if (length() == -1)
888 set_length(num);
889
890 if (num != (unsigned int)length())
891 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
892
893 d_str.resize((num > 0) ? num : 0); // Fill with NULLs
894#if 0
895 d_capacity = num; // capacity is number of strings we can fit.
896#endif
897 set_value_capacity((uint64_t)num);
898
899 for (i = 0; i < num; ++i) {
900 string str;
901 um.get_str(str);
902 d_str[i] = str;
903 }
904
905 break;
906
907 case dods_array_c:
908 // Added jhrg 5/18/17
909 // This replaces a comment that was simply 'TO DO'
910 throw InternalErr(__FILE__, __LINE__, "Array of array!");
911
912 case dods_structure_c:
913 case dods_sequence_c:
914 case dods_grid_c:
915 um.get_int((int &)num);
916
917 if (length() == -1)
918 set_length(num);
919
920 if (num != (unsigned int)length())
921 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
922
923 vec_resize(num);
924
925 for (i = 0; i < num; ++i) {
926 d_compound_buf[i] = d_proto->ptr_duplicate();
927 d_compound_buf[i]->deserialize(um, dds);
928 }
929
930 break;
931
932 default:
933 throw InternalErr(__FILE__, __LINE__, "Unknown type!");
934 }
935
936 return false;
937}
938
940 switch (d_proto->type()) {
941 case dods_byte_c:
942 case dods_char_c:
943 case dods_int8_c:
944 case dods_uint8_c:
945
946 case dods_int16_c:
947 case dods_uint16_c:
948
949 case dods_int32_c:
950 case dods_uint32_c:
951 case dods_float32_c:
952
953 case dods_int64_c:
954 case dods_uint64_c:
955 case dods_float64_c:
956
957 case dods_enum_c:
958 checksum.AddData(reinterpret_cast<uint8_t *>(d_buf), length_ll() * d_proto->width_ll());
959 break;
960
961 case dods_str_c:
962 case dods_url_c:
963 for (int64_t i = 0, e = length(); i < e; ++i)
964 checksum.AddData(reinterpret_cast<const uint8_t *>(d_str[i].data()), d_str[i].size());
965 break;
966
967 case dods_opaque_c:
968 case dods_structure_c:
969 case dods_sequence_c:
970 d_proto->compute_checksum(checksum);
971 break;
972
973 case dods_array_c: // No array of array
974 case dods_grid_c: // No grids in DAP4
975 default:
976 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
977 }
978}
979
980void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/) {
981 if (!read_p())
982 read(); // read() throws Error and InternalErr
983
984 switch (d_proto->type()) {
985 case dods_byte_c:
986 case dods_char_c:
987 case dods_int8_c:
988 case dods_uint8_c:
989 case dods_int16_c:
990 case dods_uint16_c:
991 case dods_int32_c:
992 case dods_uint32_c:
993 case dods_int64_c:
994 case dods_uint64_c:
995
996 case dods_enum_c:
997
998 case dods_float32_c:
999 case dods_float64_c:
1000
1001 case dods_str_c:
1002 case dods_url_c:
1003#if 0
1004 compute_checksum(checksum);
1005#endif
1006 break;
1007
1008 case dods_opaque_c:
1009 case dods_structure_c:
1010 case dods_sequence_c:
1011 // Modified the assertion here from '... != 0' to '... >= length())
1012 // to accommodate the case of a zero-length array. jhrg 1/28/16
1013 assert(d_compound_buf.capacity() >= (unsigned)length());
1014
1015 for (int i = 0, e = length(); i < e; ++i)
1016 d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/);
1017 break;
1018
1019 case dods_array_c: // No Array of Array in DAP4 either...
1020 case dods_grid_c:
1021 default:
1022 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
1023 }
1024}
1025
1026void Vector::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter /*= false*/) {
1027 if (!read_p())
1028 read(); // read() throws Error and InternalErr
1029#if 0
1030 if (filter && !eval.eval_selection(dmr, dataset()))
1031 return true;
1032#endif
1033 int64_t num = length_ll(); // The constrained length in elements
1034
1035 DBG(cerr << __func__ << ", num: " << num << endl);
1036
1037 // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16
1038 if (num == 0)
1039 return;
1040
1041 switch (d_proto->type()) {
1042 case dods_byte_c:
1043 case dods_char_c:
1044 case dods_int8_c:
1045 case dods_uint8_c:
1046 m.put_vector(d_buf, num);
1047 break;
1048
1049 case dods_int16_c:
1050 case dods_uint16_c:
1051 case dods_int32_c:
1052 case dods_uint32_c:
1053 case dods_int64_c:
1054 case dods_uint64_c:
1055 m.put_vector(d_buf, num, (int)d_proto->width_ll());
1056 break;
1057
1058 case dods_enum_c:
1059 if (d_proto->width_ll() == 1)
1060 m.put_vector(d_buf, num);
1061 else
1062 m.put_vector(d_buf, num, (int)d_proto->width_ll());
1063 break;
1064
1065 case dods_float32_c:
1066 m.put_vector_float32(d_buf, num);
1067 break;
1068
1069 case dods_float64_c:
1070 m.put_vector_float64(d_buf, num);
1071 break;
1072
1073 case dods_str_c:
1074 case dods_url_c:
1075 assert((int64_t)d_str.capacity() >= num);
1076
1077 for (int64_t i = 0; i < num; ++i)
1078 m.put_str(d_str[i]);
1079
1080 break;
1081
1082 case dods_array_c:
1083 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1084
1085 case dods_opaque_c:
1086 case dods_structure_c:
1087 case dods_sequence_c:
1088 assert(d_compound_buf.capacity() >= 0);
1089
1090 for (int64_t i = 0; i < num; ++i) {
1091 DBG(cerr << __func__ << "d_compound_buf[" << i << "] " << d_compound_buf[i] << endl);
1092 d_compound_buf[i]->serialize(m, dmr, filter);
1093 }
1094
1095 break;
1096
1097 case dods_grid_c:
1098 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1099
1100 default:
1101 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
1102 }
1103
1104#ifdef CLEAR_LOCAL_DATA
1106#endif
1107}
1108
1110 if (m_is_cardinal_type()) {
1111 if (d_buf)
1112 m_delete_cardinal_data_buffer();
1113 if (!d_buf)
1114 m_create_cardinal_data_buffer_for_type(length());
1115 }
1116
1117 DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl);
1118
1119 // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16
1120 if (length() == 0)
1121 return;
1122
1123 switch (d_proto->type()) {
1124 case dods_byte_c:
1125 case dods_char_c:
1126 case dods_int8_c:
1127 case dods_uint8_c:
1128 um.get_vector((char *)d_buf, length_ll());
1129 break;
1130
1131 case dods_int16_c:
1132 case dods_uint16_c:
1133 case dods_int32_c:
1134 case dods_uint32_c:
1135 case dods_int64_c:
1136 case dods_uint64_c:
1137 um.get_vector((char *)d_buf, length_ll(), d_proto->width_ll());
1138 break;
1139
1140 case dods_enum_c:
1141 if (d_proto->width_ll() == 1)
1142 um.get_vector((char *)d_buf, length_ll());
1143 else
1144 um.get_vector((char *)d_buf, length_ll(), d_proto->width_ll());
1145 break;
1146
1147 case dods_float32_c:
1148 um.get_vector_float32((char *)d_buf, length_ll());
1149 break;
1150
1151 case dods_float64_c:
1152 um.get_vector_float64((char *)d_buf, length_ll());
1153 break;
1154
1155 case dods_str_c:
1156 case dods_url_c: {
1157 int64_t len = length_ll();
1158 d_str.resize((len > 0) ? len : 0); // Fill with NULLs
1159 if (len < 0)
1160 throw InternalErr(__FILE__, __LINE__, "The number of string length is less than 0 ");
1161#if 0
1162 d_capacity = len; // capacity is number of strings we can fit.
1163#endif
1164 set_value_capacity(len);
1165 for (int64_t i = 0; i < len; ++i) {
1166 um.get_str(d_str[i]);
1167 }
1168
1169 break;
1170 }
1171
1172 case dods_array_c:
1173 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1174
1175 case dods_opaque_c:
1176 case dods_structure_c:
1177 case dods_sequence_c: {
1178 vec_resize(length());
1179
1180 for (int64_t i = 0, end = length(); i < end; ++i) {
1181 d_compound_buf[i] = d_proto->ptr_duplicate();
1182 d_compound_buf[i]->deserialize(um, dmr);
1183 }
1184
1185 break;
1186 }
1187
1188 case dods_grid_c:
1189 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1190
1191 default:
1192 throw InternalErr(__FILE__, __LINE__, "Unknown type.");
1193 }
1194}
1195
1223#if 0
1224unsigned int Vector::val2buf(void *val, bool reuse)
1225{
1226 // Jose Garcia
1227
1228 // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
1229 if (!val && length() == 0)
1230 return 0;
1231
1232 // I *think* this method has been mainly designed to be use by read which
1233 // is implemented in the surrogate library. Passing NULL as a pointer to
1234 // this method will be an error of the creator of the surrogate library.
1235 // Even though I recognize the fact that some methods inside libdap++ can
1236 // call val2buf, I think by now no coding bugs such as misusing val2buf
1237 // will be in libdap++, so it will be an internal error from the
1238 // surrogate library.
1239 if (!val)
1240 throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
1241
1242 switch (d_proto->type()) {
1243 case dods_byte_c:
1244 case dods_char_c:
1245 case dods_int8_c:
1246 case dods_uint8_c:
1247 case dods_int16_c:
1248 case dods_uint16_c:
1249 case dods_int32_c:
1250 case dods_uint32_c:
1251 case dods_int64_c:
1252 case dods_uint64_c:
1253
1254 case dods_enum_c:
1255
1256 case dods_float32_c:
1257 case dods_float64_c:
1258#if 0
1259 if (d_buf && !reuse)
1260 m_delete_cardinal_data_buffer();
1261#endif
1262 // First time or no reuse (free'd above)
1263 if (!d_buf || !reuse)
1264 m_create_cardinal_data_buffer_for_type(length_ll());
1265
1266 // width_ll(true) returns the size in bytes given the constraint
1267 if (d_buf)
1268 memcpy(d_buf, val, (uint64_t)width_ll(true));
1269 break;
1270
1271 case dods_str_c:
1272 case dods_url_c:
1273 {
1274 // Assume val points to an array of C++ string objects. Copy
1275 // them into the vector<string> field of this object.
1276 // Note: d_length is the number of elements in the Vector
1277#if 0
1278 d_str.resize(d_length);
1279 d_capacity = d_length;
1280 for (int i = 0; i < d_length; ++i)
1281 d_str[i] = *(static_cast<string *> (val) + i);
1282#endif
1283 int64_t str_len = length_ll();
1284 if (str_len <0)
1285 throw InternalErr(__FILE__,__LINE__,"The number of string length is less than 0 ");
1286 d_str.resize(str_len);
1287 set_value_capacity(str_len);
1288 for (int64_t i = 0; i < str_len; ++i)
1289 d_str[i] = *(static_cast<string *> (val) + i);
1290 }
1291
1292 break;
1293
1294 default:
1295 throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1296
1297 }
1298
1299 return (unsigned int)width_ll(true);
1300}
1301#endif
1302
1303unsigned int Vector::val2buf(void *val, bool reuse) {
1304
1305 auto ret_value = (unsigned int)val2buf_ll(val, reuse);
1306 return ret_value;
1307}
1308
1309int64_t Vector::val2buf_ll(void *val, bool reuse) {
1310 // Jose Garcia
1311
1312 // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
1313 if (!val && length() == 0)
1314 return 0;
1315
1316 // I *think* this method has been mainly designed to be use by read which
1317 // is implemented in the surrogate library. Passing NULL as a pointer to
1318 // this method will be an error of the creator of the surrogate library.
1319 // Even though I recognize the fact that some methods inside libdap++ can
1320 // call val2buf, I think by now no coding bugs such as misusing val2buf
1321 // will be in libdap++, so it will be an internal error from the
1322 // surrogate library.
1323 if (!val)
1324 throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
1325
1326 switch (d_proto->type()) {
1327 case dods_byte_c:
1328 case dods_char_c:
1329 case dods_int8_c:
1330 case dods_uint8_c:
1331 case dods_int16_c:
1332 case dods_uint16_c:
1333 case dods_int32_c:
1334 case dods_uint32_c:
1335 case dods_int64_c:
1336 case dods_uint64_c:
1337
1338 case dods_enum_c:
1339
1340 case dods_float32_c:
1341 case dods_float64_c:
1342#if 0
1343 if (d_buf && !reuse)
1344 m_delete_cardinal_data_buffer();
1345#endif
1346 // First time or no reuse (free'd above)
1347 if (!d_buf || !reuse)
1348 m_create_cardinal_data_buffer_for_type(length_ll());
1349
1350 // width_ll(true) returns the size in bytes given the constraint
1351 if (d_buf)
1352 memcpy(d_buf, val, (uint64_t)width_ll(true));
1353 break;
1354
1355 case dods_str_c:
1356 case dods_url_c: {
1357 // Assume val points to an array of C++ string objects. Copy
1358 // them into the vector<string> field of this object.
1359 // Note: d_length is the number of elements in the Vector
1360#if 0
1361 d_str.resize(d_length);
1362 d_capacity = d_length;
1363 for (int i = 0; i < d_length; ++i)
1364 d_str[i] = *(static_cast<string *> (val) + i);
1365#endif
1366 int64_t str_len = length_ll();
1367 if (str_len < 0)
1368 throw InternalErr(__FILE__, __LINE__, "The number of string length is less than 0 ");
1369 d_str.resize(str_len);
1370 set_value_capacity(str_len);
1371 for (int64_t i = 0; i < str_len; ++i)
1372 d_str[i] = *(static_cast<string *>(val) + i);
1373 }
1374
1375 break;
1376
1377 default:
1378 throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1379 }
1380
1381 return width_ll(true);
1382}
1383
1422unsigned int Vector::buf2val(void **val) {
1423 // Jose Garcia
1424 // The same comment in Vector::val2buf applies here!
1425 if (!val)
1426 throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1427
1428 int64_t wid = width_ll(true /* constrained */);
1429
1430 // This is the width computed using length(). The
1431 // length() property is changed when a projection
1432 // constraint is applied. Thus, this is the number of
1433 // bytes in the buffer given the current constraint.
1434
1435 switch (d_proto->type()) {
1436 case dods_byte_c:
1437 case dods_char_c:
1438 case dods_int8_c:
1439 case dods_uint8_c:
1440 case dods_int16_c:
1441 case dods_uint16_c:
1442 case dods_int32_c:
1443 case dods_uint32_c:
1444 case dods_int64_c:
1445 case dods_uint64_c:
1446
1447 case dods_enum_c:
1448
1449 case dods_float32_c:
1450 case dods_float64_c:
1451 if (!d_buf)
1452 throw InternalErr(__FILE__, __LINE__,
1453 "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1454 if (!*val)
1455 *val = new char[wid];
1456
1457 memcpy(*val, d_buf, (uint64_t)wid);
1458 return (unsigned int)wid;
1459
1460 case dods_str_c:
1461 case dods_url_c: {
1462 if (d_str.empty())
1463 throw InternalErr(__FILE__, __LINE__,
1464 "Vector::buf2val: Logic error: called when string data buffer was empty!");
1465 if (!*val)
1466 *val = new string[d_length];
1467
1468 for (int i = 0; i < d_length; ++i)
1469 *(static_cast<string *>(*val) + i) = d_str[i];
1470
1471 return (unsigned int)width_ll();
1472 }
1473
1474 default:
1475 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1476 }
1477}
1478
1479int64_t Vector::buf2val_ll(void **val) {
1480 // Jose Garcia
1481 // The same comment in Vector::val2buf applies here!
1482 if (!val)
1483 throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1484
1485 int64_t wid = width_ll(true /* constrained */);
1486
1487 // This is the width computed using length(). The
1488 // length() property is changed when a projection
1489 // constraint is applied. Thus, this is the number of
1490 // bytes in the buffer given the current constraint.
1491
1492 switch (d_proto->type()) {
1493 case dods_byte_c:
1494 case dods_char_c:
1495 case dods_int8_c:
1496 case dods_uint8_c:
1497 case dods_int16_c:
1498 case dods_uint16_c:
1499 case dods_int32_c:
1500 case dods_uint32_c:
1501 case dods_int64_c:
1502 case dods_uint64_c:
1503
1504 case dods_enum_c:
1505
1506 case dods_float32_c:
1507 case dods_float64_c:
1508 if (!d_buf)
1509 throw InternalErr(__FILE__, __LINE__,
1510 "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1511 if (!*val)
1512 *val = new char[wid];
1513
1514 memcpy(*val, d_buf, wid);
1515 return wid;
1516
1517 case dods_str_c:
1518 case dods_url_c: {
1519 if (d_str.empty())
1520 throw InternalErr(__FILE__, __LINE__,
1521 "Vector::buf2val: Logic error: called when string data buffer was empty!");
1522 if (!*val)
1523 *val = new string[d_length_ll];
1524
1525 for (int64_t i = 0; i < d_length_ll; ++i)
1526 *(static_cast<string *>(*val) + i) = d_str[i];
1527
1528 return width_ll();
1529 }
1530
1531 default:
1532 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1533 }
1534}
1535
1556void Vector::set_vec(unsigned int i, BaseType *val) { Vector::set_vec_nocopy(i, val->ptr_duplicate()); }
1557
1559
1571void Vector::set_vec_nocopy(unsigned int i, BaseType *val) {
1572 // Jose Garcia
1573 // This is a public method which allows users to set the elements
1574 // of *this* vector. Passing an invalid index, a NULL pointer or
1575 // mismatching the vector type are internal errors.
1576 if (i >= static_cast<unsigned int>(d_length))
1577 throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1578 if (!val)
1579 throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1580 if (val->type() != d_proto->type())
1581 throw InternalErr(__FILE__, __LINE__,
1582 "invalid data: type of incoming object does not match *this* vector type.");
1583
1584 // This code originally used capacity() instead of size(), but that was an error.
1585 // Use capacity() when using reserve() and size() when using resize(). Mixing
1586 // capacity() with resize() leaves holes in the data, where (pointer) values are
1587 // filled with nulls during successive calls to resize(). The resize() heuristic
1588 // remembers previous calls on a given vector<> and allocates larger than requested
1589 // blocks of memory on successive calls, which has the strange affect of erasing
1590 // values already in the vector in the parts just added.
1591 // jhrg 5/18/17
1592 if (i >= d_compound_buf.size()) {
1593 vec_resize(d_compound_buf.size() + 100);
1594 }
1595
1596 d_compound_buf[i] = val;
1597}
1598
1599void Vector::set_vec_nocopy_ll(uint64_t i, BaseType *val) {
1600 // Jose Garcia
1601 // This is a public method which allows users to set the elements
1602 // of *this* vector. Passing an invalid index, a NULL pointer or
1603 // mismatching the vector type are internal errors.
1604 if (i >= static_cast<uint64_t>(length_ll()))
1605 throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1606 if (!val)
1607 throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1608 if (val->type() != d_proto->type())
1609 throw InternalErr(__FILE__, __LINE__,
1610 "invalid data: type of incoming object does not match *this* vector type.");
1611
1612 // This code originally used capacity() instead of size(), but that was an error.
1613 // Use capacity() when using reserve() and size() when using resize(). Mixing
1614 // capacity() with resize() leaves holes in the data, where (pointer) values are
1615 // filled with nulls during successive calls to resize(). The resize() heuristic
1616 // remembers previous calls on a given vector<> and allocates larger than requested
1617 // blocks of memory on successive calls, which has the strange affect of erasing
1618 // values already in the vector in the parts just added.
1619 // jhrg 5/18/17
1620 if (i >= d_compound_buf.size()) {
1621 vec_resize_ll(d_compound_buf.size() + 100);
1622 }
1623
1624 d_compound_buf[i] = val;
1625}
1626
1637 if (d_buf) {
1638 delete[] d_buf;
1639 d_buf = 0;
1640 }
1641
1642 for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
1643 delete d_compound_buf[i];
1644 d_compound_buf[i] = 0;
1645 }
1646
1647 // Force memory to be reclaimed.
1648 d_compound_buf.resize(0);
1649 d_str.resize(0);
1650
1651 d_capacity = 0;
1652 d_capacity_ll = 0;
1653 set_read_p(false);
1654}
1655
1663unsigned int Vector::get_value_capacity() const { return d_capacity; }
1664
1665uint64_t Vector::get_value_capacity_ll() const { return d_capacity_ll; }
1675void Vector::reserve_value_capacity(unsigned int numElements) {
1676 if (!d_proto) {
1677 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1678 }
1679 switch (d_proto->type()) {
1680 case dods_byte_c:
1681 case dods_char_c:
1682 case dods_int8_c:
1683 case dods_uint8_c:
1684 case dods_int16_c:
1685 case dods_uint16_c:
1686 case dods_int32_c:
1687 case dods_uint32_c:
1688 case dods_int64_c:
1689 case dods_uint64_c:
1690
1691 case dods_enum_c:
1692
1693 case dods_float32_c:
1694 case dods_float64_c:
1695 // Make _buf be the right size and set _capacity
1696 m_create_cardinal_data_buffer_for_type(numElements);
1697 break;
1698
1699 case dods_str_c:
1700 case dods_url_c:
1701 // Make sure the d_str has enough room for all the strings.
1702 // Technically not needed, but it will speed things up for large arrays.
1703 d_str.reserve(numElements);
1704#if 0
1705 d_capacity = numElements;
1706#endif
1707 set_value_capacity(numElements);
1708 break;
1709
1710 case dods_array_c:
1711 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1712
1713 case dods_opaque_c:
1714 case dods_structure_c:
1715 case dods_sequence_c:
1716 case dods_grid_c:
1717 // not clear anyone will go this path, but best to be complete.
1718 d_compound_buf.reserve(numElements);
1719#if 0
1720 d_capacity = numElements;
1721#endif
1722 set_value_capacity(numElements);
1723 break;
1724
1725 default:
1726 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1727 } // switch
1728}
1729
1736 // Use the current length of the vector as the reserve amount.
1738}
1739
1748void Vector::reserve_value_capacity_ll(uint64_t numElements) {
1749 if (!d_proto) {
1750 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1751 }
1752 switch (d_proto->type()) {
1753 case dods_byte_c:
1754 case dods_char_c:
1755 case dods_int8_c:
1756 case dods_uint8_c:
1757 case dods_int16_c:
1758 case dods_uint16_c:
1759 case dods_int32_c:
1760 case dods_uint32_c:
1761 case dods_int64_c:
1762 case dods_uint64_c:
1763
1764 case dods_enum_c:
1765
1766 case dods_float32_c:
1767 case dods_float64_c:
1768 // Make _buf be the right size and set _capacity
1769 m_create_cardinal_data_buffer_for_type(numElements);
1770 break;
1771
1772 case dods_str_c:
1773 case dods_url_c:
1774 // Make sure the d_str has enough room for all the strings.
1775 // Technically not needed, but it will speed things up for large arrays.
1776 d_str.reserve(numElements);
1777#if 0
1778 d_capacity = numElements;
1779#endif
1780 set_value_capacity(numElements);
1781 break;
1782
1783 case dods_array_c:
1784 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1785
1786 case dods_opaque_c:
1787 case dods_structure_c:
1788 case dods_sequence_c:
1789 case dods_grid_c:
1790 // not clear anyone will go this path, but best to be complete.
1791 d_compound_buf.reserve(numElements);
1792#if 0
1793 d_capacity = numElements;
1794#endif
1795 set_value_capacity(numElements);
1796 break;
1797
1798 default:
1799 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1800 } // switch
1801}
1802
1809 // Use the current length of the vector as the reserve amount.
1811}
1812
1818void Vector::reserve_value_capacity_ll_byte(uint64_t numBytes) { d_buf = new char[numBytes]; }
1847uint64_t Vector::set_value_slice_from_row_major_vector(const Vector &rowMajorDataC, uint64_t startElement) {
1848 static const string funcName = "set_value_slice_from_row_major_vector:";
1849
1850 // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1851 Vector &rowMajorData = const_cast<Vector &>(rowMajorDataC);
1852
1853 bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
1854 if (!typesMatch) {
1855 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
1856 }
1857
1858 // Make sure the data exists
1859 if (!rowMajorData.read_p()) {
1860 throw InternalErr(__FILE__, __LINE__,
1861 funcName +
1862 "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1863 }
1864
1865 // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1866 if (rowMajorData.length_ll() < 0) {
1867 throw InternalErr(
1868 __FILE__, __LINE__,
1869 funcName +
1870 "Logic error: the Vector to copy data from has length_ll() < 0 and was probably not initialized!");
1871 }
1872
1873 // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
1874 // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be
1875 // addressed.
1876 if (rowMajorData.get_value_capacity_ll() < static_cast<uint64_t>(rowMajorData.length_ll())) {
1877 throw InternalErr(
1878 __FILE__, __LINE__,
1879 funcName + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1880 }
1881
1882 // Make sure there's enough room in this Vector to store all the elements requested. Again,
1883 // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1884 if (d_capacity_ll < (startElement + rowMajorData.length_ll())) {
1885 throw InternalErr(__FILE__, __LINE__,
1886 funcName +
1887 "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1888 }
1889
1890 // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1891 switch (d_proto->type()) {
1892 case dods_int8_c:
1893 case dods_uint8_c:
1894 case dods_byte_c:
1895 case dods_char_c:
1896 case dods_int16_c:
1897 case dods_uint16_c:
1898 case dods_int32_c:
1899 case dods_uint32_c:
1900 case dods_int64_c:
1901 case dods_uint64_c:
1902
1903 case dods_enum_c:
1904
1905 case dods_float32_c:
1906 case dods_float64_c: {
1907 if (!d_buf) {
1908 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1909 }
1910 if (!rowMajorData.d_buf) {
1911 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1912 }
1913 // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1914 int64_t varWidth = d_proto->width_ll();
1915 char *pFromBuf = rowMajorData.d_buf;
1916 int64_t numBytesToCopy = rowMajorData.width_ll(true);
1917 char *pIntoBuf = d_buf + (startElement * varWidth);
1918 memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
1919 break;
1920 }
1921
1922 case dods_str_c:
1923 case dods_url_c:
1924 // Strings need to be copied directly
1925 for (uint64_t i = 0; i < static_cast<uint64_t>(rowMajorData.length_ll()); ++i) {
1926 d_str[startElement + i] = rowMajorData.d_str[i];
1927 }
1928 break;
1929
1930 case dods_array_c:
1931 case dods_opaque_c:
1932 case dods_structure_c:
1933 case dods_sequence_c:
1934 case dods_grid_c:
1935 // Not sure that this function will be used for these type of nested objects, so I will throw here.
1936 throw InternalErr(__FILE__, __LINE__,
1937 funcName +
1938 "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
1939
1940 default:
1941 throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1942 } // switch (_var->type())
1943
1944 // This is how many elements we copied.
1945 return (uint64_t)rowMajorData.length_ll();
1946}
1947
1956template <typename T> static bool types_match(Type t, T *cpp_var) {
1957 switch (t) {
1958 case dods_byte_c:
1959 case dods_char_c:
1960 case dods_uint8_c:
1961 return typeid(cpp_var) == typeid(dods_byte *);
1962
1963 case dods_int8_c:
1964 return typeid(cpp_var) == typeid(dods_int8 *);
1965 case dods_int16_c:
1966 return typeid(cpp_var) == typeid(dods_int16 *);
1967 case dods_uint16_c:
1968 return typeid(cpp_var) == typeid(dods_uint16 *);
1969 case dods_int32_c:
1970 return typeid(cpp_var) == typeid(dods_int32 *);
1971 case dods_uint32_c:
1972 return typeid(cpp_var) == typeid(dods_uint32 *);
1973 case dods_int64_c:
1974 return typeid(cpp_var) == typeid(dods_int64 *);
1975 case dods_uint64_c:
1976 return typeid(cpp_var) == typeid(dods_uint64 *);
1977
1978 case dods_float32_c:
1979 return typeid(cpp_var) == typeid(dods_float32 *);
1980 case dods_float64_c:
1981 return typeid(cpp_var) == typeid(dods_float64 *);
1982
1983 case dods_null_c:
1984 case dods_enum_c:
1985 case dods_str_c:
1986 case dods_url_c:
1987 case dods_opaque_c:
1988 case dods_array_c:
1989 case dods_structure_c:
1990 case dods_sequence_c:
1991 case dods_group_c:
1992 default:
1993 return false;
1994 }
1995}
1996
1998
1999
2000template <typename T> bool Vector::set_value_worker(T *v, int sz) {
2001 if (!v || !types_match(
2002 d_proto->type() == dods_enum_c ? static_cast<D4Enum *>(d_proto)->element_type() : d_proto->type(), v))
2003 return false;
2004 m_set_cardinal_values_internal(v, (int64_t)sz);
2005 return true;
2006}
2007
2008template <typename T> bool Vector::set_value_ll_worker(T *v, int64_t sz) {
2009 if (!v || !types_match(
2010 d_proto->type() == dods_enum_c ? static_cast<D4Enum *>(d_proto)->element_type() : d_proto->type(), v))
2011 return false;
2012
2013 m_set_cardinal_values_internal(v, sz);
2014 return true;
2015}
2016
2017bool Vector::set_value(dods_byte *val, int sz) { return set_value_worker(val, sz); }
2018
2019bool Vector::set_value(dods_int8 *val, int sz) { return set_value_worker(val, sz); }
2020bool Vector::set_value(dods_int16 *val, int sz) { return set_value_worker(val, sz); }
2021bool Vector::set_value(dods_uint16 *val, int sz) { return set_value_worker(val, sz); }
2022bool Vector::set_value(dods_int32 *val, int sz) { return set_value_worker(val, sz); }
2023bool Vector::set_value(dods_uint32 *val, int sz) { return set_value_worker(val, sz); }
2024bool Vector::set_value(dods_int64 *val, int sz) { return set_value_worker(val, sz); }
2025bool Vector::set_value(dods_uint64 *val, int sz) { return set_value_worker(val, sz); }
2026bool Vector::set_value(dods_float32 *val, int sz) { return set_value_worker(val, sz); }
2027bool Vector::set_value(dods_float64 *val, int sz) { return set_value_worker(val, sz); }
2028
2029bool Vector::set_value_ll(dods_byte *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2030
2031bool Vector::set_value_ll(dods_int8 *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2032bool Vector::set_value_ll(dods_int16 *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2033bool Vector::set_value_ll(dods_uint16 *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2034bool Vector::set_value_ll(dods_int32 *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2035bool Vector::set_value_ll(dods_uint32 *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2036bool Vector::set_value_ll(dods_int64 *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2037bool Vector::set_value_ll(dods_uint64 *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2038bool Vector::set_value_ll(dods_float32 *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2039bool Vector::set_value_ll(dods_float64 *val, int64_t sz) { return set_value_ll_worker(val, sz); }
2040
2048bool Vector::set_value(string *val, int sz) {
2049 if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
2050 d_str.resize(sz);
2051#if 0
2052 d_capacity = sz;
2053#endif
2055 for (int t = 0; t < sz; t++) {
2056 d_str[t] = val[t];
2057 }
2058 set_length(sz);
2059 set_read_p(true);
2060 return true;
2061 } else {
2062 return false;
2063 }
2064}
2065
2066bool Vector::set_value_ll(string *val, int64_t sz) {
2067 if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
2068 d_str.resize(sz);
2069#if 0
2070 d_capacity_ll = sz;
2071#endif
2073 for (int64_t t = 0; t < sz; t++) {
2074 d_str[t] = val[t];
2075 }
2076 set_length_ll(sz);
2077 set_read_p(true);
2078 return true;
2079 } else {
2080 return false;
2081 }
2082}
2083
2084template <typename T> bool Vector::set_value_worker(vector<T> &v, int sz) { return set_value(v.data(), sz); }
2085
2086template <typename T> bool Vector::set_value_ll_worker(vector<T> &v, int64_t sz) { return set_value_ll(v.data(), sz); }
2087
2088bool Vector::set_value(vector<dods_byte> &val, int sz) { return set_value_worker(val, sz); }
2089bool Vector::set_value(vector<dods_int8> &val, int sz) { return set_value_worker(val, sz); }
2090bool Vector::set_value(vector<dods_int16> &val, int sz) { return set_value_worker(val, sz); }
2091bool Vector::set_value(vector<dods_uint16> &val, int sz) { return set_value_worker(val, sz); }
2092bool Vector::set_value(vector<dods_int32> &val, int sz) { return set_value_worker(val, sz); }
2093bool Vector::set_value(vector<dods_uint32> &val, int sz) { return set_value_worker(val, sz); }
2094bool Vector::set_value(vector<dods_int64> &val, int sz) { return set_value_worker(val, sz); }
2095bool Vector::set_value(vector<dods_uint64> &val, int sz) { return set_value_worker(val, sz); }
2096bool Vector::set_value(vector<dods_float32> &val, int sz) { return set_value_worker(val, sz); }
2097bool Vector::set_value(vector<dods_float64> &val, int sz) { return set_value_worker(val, sz); }
2098
2099bool Vector::set_value_ll(vector<dods_byte> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2100bool Vector::set_value_ll(vector<dods_int8> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2101bool Vector::set_value_ll(vector<dods_int16> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2102bool Vector::set_value_ll(vector<dods_uint16> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2103bool Vector::set_value_ll(vector<dods_int32> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2104bool Vector::set_value_ll(vector<dods_uint32> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2105bool Vector::set_value_ll(vector<dods_int64> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2106bool Vector::set_value_ll(vector<dods_uint64> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2107bool Vector::set_value_ll(vector<dods_float32> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2108bool Vector::set_value_ll(vector<dods_float64> &val, int64_t sz) { return set_value_ll_worker(val, sz); }
2109
2111bool Vector::set_value(vector<string> &val, int sz) {
2112 if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
2113 d_str.resize(sz);
2114 d_capacity = sz;
2115 for (int t = 0; t < sz; t++) {
2116 d_str[t] = val[t];
2117 }
2118 set_length(sz);
2119 set_read_p(true);
2120 return true;
2121 } else {
2122 return false;
2123 }
2124}
2125
2126bool Vector::set_value_ll(vector<string> &val, int64_t sz) {
2127 if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
2128 d_str.resize(sz);
2129 d_capacity_ll = sz;
2130 for (int64_t t = 0; t < sz; t++) {
2131 d_str[t] = val[t];
2132 }
2133 set_length_ll(sz);
2134 set_read_p(true);
2135 return true;
2136 } else {
2137 return false;
2138 }
2139}
2140
2142
2144
2161template <typename T> void Vector::value_worker(vector<unsigned int> *indices, T *b) const {
2162#if 0
2163 // Iterator version. Not tested, jhrg 8/14/13
2164 for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
2165 unsigned long currentIndex = *i;
2166 if(currentIndex > (unsigned int)length()){
2167 stringstream s;
2168 s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
2169 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
2170 throw Error(s.str());
2171 }
2172 b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
2173 }
2174#endif
2175 for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
2176 unsigned long currentIndex = (*indices)[i];
2177 if (currentIndex > (unsigned int)length()) {
2178 stringstream s;
2179 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is "
2180 << "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name()
2181 << "'. ";
2182 throw Error(s.str());
2183 }
2184 b[i] = reinterpret_cast<T *>(d_buf)[currentIndex]; // I like this version - and it works!
2185 }
2186}
2187
2188template <typename T> void Vector::value_ll_worker(vector<uint64_t> *indices, T *b) const {
2189#if 0
2190 // Iterator version. Not tested, jhrg 8/14/13
2191 for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
2192 unsigned long currentIndex = *i;
2193 if(currentIndex > (unsigned int)length()){
2194 stringstream s;
2195 s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
2196 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
2197 throw Error(s.str());
2198 }
2199 b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
2200 }
2201#endif
2202 for (uint64_t i = 0, e = indices->size(); i < e; ++i) {
2203 uint64_t currentIndex = (*indices)[i];
2204 if (currentIndex > (uint64_t)length_ll()) {
2205 stringstream s;
2206 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is "
2207 << "outside the bounds of the internal storage [ length_ll()= " << length_ll() << " ] name: '" << name()
2208 << "'. ";
2209 throw Error(s.str());
2210 }
2211 b[i] = reinterpret_cast<T *>(d_buf)[currentIndex]; // I like this version - and it works!
2212 }
2213}
2214
2215void Vector::value(vector<unsigned int> *indices, dods_byte *b) const { value_worker(indices, b); }
2216void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const { value_worker(indices, b); }
2217void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const { value_worker(indices, b); }
2218void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const { value_worker(indices, b); }
2219void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const { value_worker(indices, b); }
2220void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const { value_worker(indices, b); }
2221void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const { value_worker(indices, b); }
2222void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const { value_worker(indices, b); }
2223void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
2224void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
2225
2226void Vector::value_ll(vector<uint64_t> *indices, dods_byte *b) const { value_ll_worker(indices, b); }
2227void Vector::value_ll(vector<uint64_t> *indices, dods_int8 *b) const { value_ll_worker(indices, b); }
2228void Vector::value_ll(vector<uint64_t> *indices, dods_int16 *b) const { value_ll_worker(indices, b); }
2229void Vector::value_ll(vector<uint64_t> *indices, dods_uint16 *b) const { value_ll_worker(indices, b); }
2230void Vector::value_ll(vector<uint64_t> *indices, dods_int32 *b) const { value_ll_worker(indices, b); }
2231void Vector::value_ll(vector<uint64_t> *indices, dods_uint32 *b) const { value_ll_worker(indices, b); }
2232void Vector::value_ll(vector<uint64_t> *indices, dods_int64 *b) const { value_ll_worker(indices, b); }
2233void Vector::value_ll(vector<uint64_t> *indices, dods_uint64 *b) const { value_ll_worker(indices, b); }
2234void Vector::value_ll(vector<uint64_t> *indices, dods_float32 *b) const { value_ll_worker(indices, b); }
2235void Vector::value_ll(vector<uint64_t> *indices, dods_float64 *b) const { value_ll_worker(indices, b); }
2236
2237#if 0
2238template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
2239template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
2240template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
2241template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
2242template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
2243template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
2244template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
2245template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
2246template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
2247template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
2248#endif
2249
2252void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const {
2253 unsigned long currentIndex;
2254
2255 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c) {
2256 for (unsigned long i = 0; i < subsetIndex->size(); ++i) {
2257 currentIndex = (*subsetIndex)[i];
2258 if (currentIndex > (unsigned int)length()) {
2259 stringstream s;
2260 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is "
2261 << "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name()
2262 << "'. ";
2263 throw Error(s.str());
2264 }
2265 b[i] = d_str[currentIndex];
2266 }
2267 }
2268}
2269
2270void Vector::value_ll(vector<uint64_t> *subsetIndex, vector<string> &b) const {
2271 uint64_t currentIndex;
2272
2273 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c) {
2274 for (uint64_t i = 0; i < subsetIndex->size(); ++i) {
2275 currentIndex = (*subsetIndex)[i];
2276 if (currentIndex > (uint64_t)length_ll()) {
2277 stringstream s;
2278 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is "
2279 << "outside the bounds of the internal storage [ length_ll()= " << length_ll() << " ] name: '"
2280 << name() << "'. ";
2281 throw Error(s.str());
2282 }
2283 b[i] = d_str[currentIndex];
2284 }
2285 }
2286}
2287
2288template <typename T> void Vector::value_worker(T *v) const {
2289 // Only copy if v is not null and the proto's type matches.
2290 // For Enums, use the element type since type == dods_enum_c.
2291 if (v && types_match(
2292 d_proto->type() == dods_enum_c ? static_cast<D4Enum *>(d_proto)->element_type() : d_proto->type(), v))
2293 memcpy(v, d_buf, length_ll() * sizeof(T));
2294}
2295void Vector::value(dods_byte *b) const { value_worker(b); }
2296void Vector::value(dods_int8 *b) const { value_worker(b); }
2297void Vector::value(dods_int16 *b) const { value_worker(b); }
2298void Vector::value(dods_uint16 *b) const { value_worker(b); }
2299void Vector::value(dods_int32 *b) const { value_worker(b); }
2300void Vector::value(dods_uint32 *b) const { value_worker(b); }
2301void Vector::value(dods_int64 *b) const { value_worker(b); }
2302void Vector::value(dods_uint64 *b) const { value_worker(b); }
2303void Vector::value(dods_float32 *b) const { value_worker(b); }
2304void Vector::value(dods_float64 *b) const { value_worker(b); }
2305
2306#if 0
2307template void Vector::value(dods_byte *v) const;
2308template void Vector::value(dods_int8 *v) const;
2309template void Vector::value(dods_int16 *v) const;
2310template void Vector::value(dods_uint16 *v) const;
2311template void Vector::value(dods_int32 *v) const;
2312template void Vector::value(dods_uint32 *v) const;
2313template void Vector::value(dods_int64 *v) const;
2314template void Vector::value(dods_uint64 *v) const;
2315template void Vector::value(dods_float32 *v) const;
2316template void Vector::value(dods_float64 *v) const;
2317#endif
2318
2320void Vector::value(vector<string> &b) const {
2321 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
2322 b = d_str;
2323}
2324
2328 void *buffer = new char[width_ll(true)];
2329
2330 memcpy(buffer, d_buf, width_ll(true));
2331
2332 return buffer;
2333}
2334
2335
2352#if 1
2353 if (v)
2355 else {
2356 delete d_proto;
2357 d_proto = nullptr;
2358 }
2359#else
2360 // Delete the current template variable
2361 if (d_proto) {
2362 delete d_proto;
2363 d_proto = 0;
2364 }
2365
2366 // if 'v' is null, just set _var to null and exit.
2367 if (!v) {
2368 d_proto = 0;
2369 } else {
2370 // Jose Garcia
2371 // By getting a copy of this object to be assigned to _var
2372 // we let the owner of 'v' to deallocate it as necessary.
2373 d_proto = v->ptr_duplicate();
2374
2375 // If 'v' has a name, use it as the name of the array. If v doesn't have
2376 // a name, then make sure to copy the array's name to it
2377 // so that software which uses the template's name will still work.
2378 if (!v->name().empty())
2379 set_name(v->name());
2380 else
2381 d_proto->set_name(name());
2382
2383 d_proto->set_parent(this); // Vector --> child
2384
2385 DBG(cerr << "Vector::add_var: Added variable " << v << " (" << v->name() << " " << v->type_name() << ")"
2386 << endl);
2387 }
2388#endif
2389}
2390
2392 // Delete the current template variable, if it exists
2393 delete d_proto;
2394 d_proto = nullptr;
2395
2396 // if 'v' is null, just set _var to null and exit.
2397 if (v) {
2398 d_proto = v;
2399
2400 // If 'v' has a name, use it as the name of the array. If it *is*
2401 // empty, then make sure to copy the array's name to the template
2402 // so that software which uses the template's name will still work.
2403 if (!v->name().empty())
2404 set_name(v->name());
2405 else
2406 d_proto->set_name(name());
2407
2408 d_proto->set_parent(this); // Vector is the parent; proto is the child
2409
2410 DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " (" << v->name() << " " << v->type_name() << ")"
2411 << endl);
2412 }
2413}
2414
2415bool Vector::check_semantics(string &msg, bool) { return BaseType::check_semantics(msg); }
2416
2424bool Vector::is_dap4_projected(std::vector<std::string> &inventory) {
2425 bool has_projected_dap4 = false;
2426 if (send_p()) {
2427 if (d_proto->is_constructor_type()) {
2428 has_projected_dap4 =
2429 d_proto->is_dap4_projected(inventory) || attributes()->has_dap4_types(FQN(), inventory);
2430 } else {
2431 has_projected_dap4 = prototype()->is_dap4();
2432 if (has_projected_dap4) {
2433 inventory.emplace_back(prototype()->type_name() + " " + FQN());
2434 }
2435 has_projected_dap4 |= attributes()->has_dap4_types(FQN(), inventory);
2436 }
2437 if (has_projected_dap4) {
2438 inventory.emplace_back(type_name() + " " + FQN());
2439 }
2440 }
2441 return has_projected_dap4;
2442}
2443
2452void Vector::dump(ostream &strm) const {
2453 strm << DapIndent::LMarg << "Vector::dump - (" << (void *)this << ")" << endl;
2455 BaseType::dump(strm);
2456 strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
2457 if (d_proto) {
2458 strm << DapIndent::LMarg << "base type:" << endl;
2460 d_proto->dump(strm);
2462 } else {
2463 strm << DapIndent::LMarg << "base type: not set" << endl;
2464 }
2465 strm << DapIndent::LMarg << "vector contents:" << endl;
2467 for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
2468 if (d_compound_buf[i])
2469 d_compound_buf[i]->dump(strm);
2470 else
2471 strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
2472 }
2474 strm << DapIndent::LMarg << "strings:" << endl;
2476 for (unsigned i = 0; i < d_str.size(); i++) {
2477 strm << DapIndent::LMarg << d_str[i] << endl;
2478 }
2480 if (d_buf) {
2481 switch (d_proto != 0 ? d_proto->type() : 0) {
2482 case dods_byte_c:
2483 case dods_char_c:
2484 strm << DapIndent::LMarg << "_buf: ";
2485 strm.write(d_buf, d_length);
2486 strm << endl;
2487 break;
2488
2489 case 0:
2490 default:
2491 strm << DapIndent::LMarg << "_buf: " << (void *)d_buf << endl;
2492 break;
2493 }
2494 } else {
2495 strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
2496 }
2497
2499}
2500
2501} // namespace libdap
Definition crc.h:43
void AddData(const uint8_t *pData, const uint32_t length)
Definition crc.h:64
The basic data type for the DODS DAP types.
Definition BaseType.h:118
BaseType & operator=(const BaseType &rhs)
Definition BaseType.cc:159
virtual string type_name() const
Returns the type of the class instance as a string.
Definition BaseType.cc:335
virtual bool read()
Read data into a local buffer.
Definition BaseType.cc:775
virtual string name() const
Returns the name of the class instance.
Definition BaseType.cc:296
virtual bool read_p()
Has this variable been read?
Definition BaseType.cc:410
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition BaseType.cc:442
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition BaseType.cc:326
void dump(ostream &strm) const override
dumps information about this object
Definition BaseType.cc:269
virtual bool is_dap4() const
Definition BaseType.h:181
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition BaseType.cc:314
virtual D4Attributes * attributes()
Definition BaseType.cc:507
virtual std::string FQN() const
Definition BaseType.cc:304
virtual bool send_p()
Should this variable be sent?
Definition BaseType.cc:478
virtual void set_send_p(bool state)
Definition BaseType.cc:488
virtual BaseType * ptr_duplicate()=0
virtual unsigned int val2buf(void *val, bool reuse=false)=0
Loads class data.
stack< BaseType * > btp_stack
Definition BaseType.h:149
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition BaseType.cc:1056
virtual int64_t width_ll(bool constrained=false) const
Definition BaseType.cc:1140
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition BaseType.cc:124
virtual Type type() const
Returns the type of the class instance.
Definition BaseType.cc:329
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 ...
bool has_dap4_types(const std::string &path, std::vector< std::string > &inventory) const
Holds a DAP4 enumeration.
Definition D4Enum.h:53
Type element_type()
Definition D4Enum.h:117
Marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using DAP4's receiv...
virtual void put_vector_float32(char *val, int64_t num_elem)
Write a fixed size vector.
virtual void put_str(const string &val)
virtual void put_vector(char *val, int64_t num_bytes)
Write a fixed size vector.
virtual void put_vector_float64(char *val, int64_t num_elem)
Write a fixed size vector of float64s.
Read data from the stream made by D4StreamMarshaller.
virtual void get_vector_float64(char *val, int64_t num_elem)
virtual void get_vector_float32(char *val, int64_t num_elem)
virtual void get_str(string &val)
virtual void get_vector(char **, unsigned int &, Vector &)
static ostream & LMarg(ostream &strm)
Definition DapIndent.cc:61
static void Indent()
Definition DapIndent.cc:44
static void UnIndent()
Definition DapIndent.cc:46
A class for error processing.
Definition Error.h:92
A class for software fault reporting.
Definition InternalErr.h:61
abstract base class used to marshal/serialize dap data objects
Definition Marshaller.h:50
virtual void put_str(const std::string &val)=0
virtual void put_int(int val)=0
virtual void put_vector(char *val, int num, Vector &vec)=0
abstract base class used to unmarshall/deserialize dap data objects
virtual void get_int(int &val)=0
virtual void get_vector(char **val, unsigned int &num, Vector &vec)=0
virtual void get_str(string &val)=0
Holds a one-dimensional collection of DAP2 data types.
Definition Vector.h:81
virtual void reserve_value_capacity_ll_byte(uint64_t numBytes)
Definition Vector.cc:1818
bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false) override
Receive data from the net.
Definition Vector.cc:831
void set_send_p(bool state) override
Indicates that the data is ready to send.
Definition Vector.cc:352
int64_t width_ll(bool constrained=false) const override
Return the number of bytes needed to hold the array data.
Definition Vector.h:203
void dump(ostream &strm) const override
dumps information about this object
Definition Vector.cc:2452
virtual uint64_t get_value_capacity_ll() const
Definition Vector.cc:1665
void compute_checksum(Crc32 &checksum) override
include the data for this variable in the checksum DAP4 includes a checksum with every data response....
Definition Vector.cc:939
virtual unsigned int get_value_capacity() const
Definition Vector.cc:1663
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:1571
Vector & operator=(const Vector &rhs)
Definition Vector.cc:315
void add_var_nocopy(BaseType *v, Part p=nil) override
Definition Vector.cc:2391
void add_var(BaseType *v, Part p=nil) override
Add the BaseType pointer to this constructor type instance.
Definition Vector.cc:2351
int length() const override
Returns the number of elements in the vector. Note that some child classes of Vector use the length o...
Definition Vector.h:210
int64_t val2buf_ll(void *val, bool reuse=false)
Definition Vector.cc:1309
virtual void value_ll(vector< uint64_t > *indices, dods_byte *b) const
Definition Vector.cc:2226
int64_t length_ll() const override
Get the number of elements in this Vector/Array This version of the function deprecates length() whic...
Definition Vector.h:218
void set_read_p(bool state) override
Indicates that the data is ready to send.
Definition Vector.cc:389
int element_count(bool leaves) override
Count the members of constructor types.
Definition Vector.cc:332
void set_length_ll(int64_t l) override
Set the number of elements in this Vector/Array This version of the function deprecates set_length() ...
Definition Vector.cc:432
void set_vec(unsigned int i, BaseType *val)
Sets element i to value val.
Definition Vector.cc:1556
bool is_dap4_projected(std::vector< std::string > &projected_dap4_inventory) override
Definition Vector.cc:2424
virtual ~Vector()
Definition Vector.cc:303
void set_value_capacity(uint64_t l)
Definition Vector.cc:442
void set_name(const std::string &name) override
Sets the name of the class instance.
Definition Vector.cc:323
bool check_semantics(string &msg, bool all=false) override
Compare an object's current state with the semantics of its type.
Definition Vector.cc:2415
void vec_resize_ll(int64_t l)
Definition Vector.cc:628
void intern_data() override
Read data into this variable.
Definition Vector.cc:980
virtual void reserve_value_capacity_ll()
Definition Vector.cc:1808
unsigned int val2buf(void *val, bool reuse=false) override
Reads data into the Vector buffer.
Definition Vector.cc:1303
int64_t buf2val_ll(void **val)
Definition Vector.cc:1479
virtual bool set_value_ll(dods_byte *val, int64_t sz)
Definition Vector.cc:2029
BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=nullptr) override
Definition Vector.cc:469
virtual uint64_t set_value_slice_from_row_major_vector(const Vector &rowMajorData, uint64_t startElement)
Definition Vector.cc:1847
virtual bool set_value(dods_byte *val, int sz)
Definition Vector.cc:2017
virtual void * value()
Definition Vector.cc:2327
bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true) override
Serialize a Vector.
Definition Vector.cc:726
void set_vec_nocopy_ll(uint64_t i, BaseType *val)
Definition Vector.cc:1599
void set_vec_ll(uint64_t i, BaseType *val)
Definition Vector.cc:1558
void vec_resize(int l)
Definition Vector.cc:613
virtual void reserve_value_capacity()
Definition Vector.cc:1735
virtual BaseType * prototype() const
Definition Vector.h:163
unsigned int buf2val(void **val) override
Copies data from the Vector buffer.
Definition Vector.cc:1422
void clear_local_data() override
Definition Vector.cc:1636
Vector(const string &n, BaseType *v, const Type &t, bool is_dap4=false)
The Vector constructor.
Definition Vector.cc:254
virtual BaseType * var_ll(uint64_t i)
Definition Vector.cc:567
void set_length(int64_t l) override
Sets the length of the vector. This function does not allocate any new space.
Definition Vector.cc:423
STL iterator class.
#define DBG(x)
Definition debug.h:58
#define DBG2(x)
Definition debug.h:74
#define DODS_UINT_MAX
Definition dods-limits.h:74
#define DODS_INT_MAX
Definition dods-limits.h:73
top level DAP object to house generic methods
Definition AISConnect.cc:30
Type
Identifies the data type.
Definition Type.h:94
@ dods_group_c
Definition Type.h:122
@ dods_sequence_c
Definition Type.h:108
@ dods_uint32_c
Definition Type.h:100
@ dods_int16_c
Definition Type.h:97
@ dods_byte_c
Definition Type.h:96
@ dods_int32_c
Definition Type.h:99
@ dods_url_c
Definition Type.h:104
@ dods_int8_c
Definition Type.h:115
@ dods_float32_c
Definition Type.h:101
@ dods_char_c
Definition Type.h:114
@ dods_int64_c
Definition Type.h:118
@ dods_uint64_c
Definition Type.h:119
@ dods_uint16_c
Definition Type.h:98
@ dods_float64_c
Definition Type.h:102
@ dods_null_c
Definition Type.h:95
@ dods_enum_c
Definition Type.h:120
@ dods_grid_c
Definition Type.h:111
@ dods_uint8_c
Definition Type.h:116
@ dods_str_c
Definition Type.h:103
@ dods_structure_c
Definition Type.h:106
@ dods_array_c
Definition Type.h:107
@ dods_opaque_c
Definition Type.h:121
string www2id(const string &in, const string &escape, const string &except)
Definition escaping.cc:202
uint64_t dods_uint64
uint32_t dods_uint32
Part
Names the parts of multi-section constructor data types.
Definition Type.h:48
uint16_t dods_uint16