libdap Updated for version 3.20.8
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 d_proto = v.d_proto->ptr_duplicate(); // use ptr_duplicate()
84 d_proto->set_parent(this); // ptr_duplicate does not set d_parent.
85 }
86 else {
87 d_proto = 0;
88 }
89
90 // d_compound_buf and d_buf (further down) hold the values of the Vector. The field
91 // d_compound_buf is used when the Vector holds non-numeric data (including strings
92 // although it used to be that was not the case jhrg 2/10/05) while d_buf
93 // holds numeric values.
94 if (v.d_compound_buf.empty()) {
95 d_compound_buf = v.d_compound_buf;
96 }
97 else {
98 // Failure to set the size will make the [] operator barf on the LHS
99 // of the assignment inside the loop.
100 d_compound_buf.resize(d_length);
101 for (int i = 0; i < d_length; ++i) {
102 // There's no need to call set_parent() for each element; we
103 // maintain the back pointer using the d_proto member. These
104 // instances are used to hold _values_ only while the d_proto
105 // field holds the type information for the elements.
106 d_compound_buf[i] = v.d_compound_buf[i]->ptr_duplicate();
107 }
108 }
109
110 // copy the strings. This copies the values.
111 d_str = v.d_str;
112
113 // copy numeric values if there are any.
114 d_buf = 0; // init to null
115 if (v.d_buf) // only copy if data present
116 val2buf(v.d_buf); // store v's value in this's _BUF.
117
118 d_capacity = v.d_capacity;
119}
120
126{
127 // Not cardinal if no d_proto at all!
128 if (!d_proto) {
129 return false;
130 }
131
132 switch (d_proto->type()) {
133 case dods_byte_c:
134 case dods_char_c:
135 case dods_int16_c:
136 case dods_uint16_c:
137 case dods_int32_c:
138 case dods_uint32_c:
139 case dods_float32_c:
140 case dods_float64_c:
141 // New cardinal types for DAP4
142 case dods_int8_c:
143 case dods_uint8_c:
144 case dods_int64_c:
145 case dods_uint64_c:
146
147 case dods_enum_c:
148 return true;
149
150 // These must be handled differently.
151 case dods_str_c:
152 case dods_url_c:
153 case dods_opaque_c:
154
155 case dods_array_c:
156
157 case dods_structure_c:
158 case dods_sequence_c:
159 case dods_grid_c:
160 return false;
161
162 default:
163 assert("Vector::var: Unrecognized type");
164 return false;
165 }
166}
167
180unsigned int Vector::m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
181{
182 // Make sure we HAVE a _var, or we cannot continue.
183 if (!d_proto) {
184 throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
185 }
186
187 // Make sure we only do this for the correct data types.
188 if (!m_is_cardinal_type()) {
189 throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
190 }
191
193
194 // Handle this special case where this is an array that holds no values
195 if (numEltsOfType == 0)
196 return 0;
197
198 // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
199 unsigned int bytesPerElt = d_proto->width();
200 unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
201 d_buf = new char[bytesNeeded];
202
203 d_capacity = numEltsOfType;
204 return bytesNeeded;
205}
206
209{
210 delete[] d_buf;
211 d_buf = 0;
212 d_capacity = 0;
213}
214
218template<class CardType>
219void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int numElts)
220{
221 if (numElts < 0) {
222 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
223 }
224 if (!fromArray) {
225 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
226 }
227 set_length(numElts);
229 memcpy(d_buf, fromArray, numElts * sizeof(CardType));
230 set_read_p(true);
231}
232
248Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
249 BaseType(n, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
250{
251 if (v)
252 add_var(v);
253
254 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
255 if (d_proto)
256 d_proto->set_parent(this);
257}
258
277Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
278 BaseType(n, d, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
279{
280 if (v)
281 add_var(v);
282
283 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
284 if (d_proto)
285 d_proto->set_parent(this);
286}
287
289Vector::Vector(const Vector & rhs) :
290 BaseType(rhs)
291{
292 DBG2(cerr << "Entering Vector const ctor for object: " << this <<
293 endl); DBG2(cerr << "RHS: " << &rhs << endl);
294
295 m_duplicate(rhs);
296}
297
298Vector::~Vector()
299{
300 DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
301
302 delete d_proto;
303 d_proto = 0;
304
305 // Clears all buffers
307
308 DBG2(cerr << "Exiting ~Vector" << endl);
309}
310
311Vector & Vector::operator=(const Vector & rhs)
312{
313 if (this == &rhs)
314 return *this;
315
316 dynamic_cast<BaseType &> (*this) = rhs;
317
318 m_duplicate(rhs);
319
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 assert 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 memcpy(d_buf, val, width(true));
1188 break;
1189
1190 case dods_str_c:
1191 case dods_url_c:
1192 // Assume val points to an array of C++ string objects. Copy
1193 // them into the vector<string> field of this object.
1194 // Note: d_length is the number of elements in the Vector
1195 d_str.resize(d_length);
1196 d_capacity = d_length;
1197 for (int i = 0; i < d_length; ++i)
1198 d_str[i] = *(static_cast<string *> (val) + i);
1199
1200 break;
1201
1202 default:
1203 throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1204
1205 }
1206
1207 return width(true);
1208}
1209
1248unsigned int Vector::buf2val(void **val)
1249{
1250 // Jose Garcia
1251 // The same comment in Vector::val2buf applies here!
1252 if (!val)
1253 throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1254
1255 unsigned int wid = static_cast<unsigned int> (width(true /* constrained */));
1256
1257 // This is the width computed using length(). The
1258 // length() property is changed when a projection
1259 // constraint is applied. Thus this is the number of
1260 // bytes in the buffer given the current constraint.
1261
1262 switch (d_proto->type()) {
1263 case dods_byte_c:
1264 case dods_char_c:
1265 case dods_int8_c:
1266 case dods_uint8_c:
1267 case dods_int16_c:
1268 case dods_uint16_c:
1269 case dods_int32_c:
1270 case dods_uint32_c:
1271 case dods_int64_c:
1272 case dods_uint64_c:
1273
1274 case dods_enum_c:
1275
1276 case dods_float32_c:
1277 case dods_float64_c:
1278 if (!d_buf)
1279 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1280 if (!*val)
1281 *val = new char[wid];
1282
1283 memcpy(*val, d_buf, wid);
1284 return wid;
1285
1286 case dods_str_c:
1287 case dods_url_c: {
1288 if (d_str.empty())
1289 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
1290 if (!*val)
1291 *val = new string[d_length];
1292
1293 for (int i = 0; i < d_length; ++i)
1294 *(static_cast<string *> (*val) + i) = d_str[i];
1295
1296 return width();
1297 }
1298
1299 default:
1300 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1301 }
1302
1303 //return wid;
1304}
1305
1326void Vector::set_vec(unsigned int i, BaseType * val)
1327{
1329}
1330
1342void Vector::set_vec_nocopy(unsigned int i, BaseType * val)
1343{
1344 // Jose Garcia
1345 // This is a public method which allows users to set the elements
1346 // of *this* vector. Passing an invalid index, a NULL pointer or
1347 // mismatching the vector type are internal errors.
1348 if (i >= static_cast<unsigned int> (d_length))
1349 throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1350 if (!val)
1351 throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1352 if (val->type() != d_proto->type())
1353 throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
1354
1355 // This code originally used capacity() instead of size(), but that was an error.
1356 // Use capacity() when using reserve() and size() when using resize(). Mixing
1357 // capacity() with resize() leaves holes in the data, where (pointer) values are
1358 // filled with nulls during successive calls to resize(). The resize() heuristic
1359 // remembers previous calls on a given vector<> and allocates larger than requested
1360 // blocks of memory on successive calls, which has the strange affect of erasing
1361 // values already in the vector in the parts just added.
1362 // jhrg 5/18/17
1363 if (i >= d_compound_buf.size()) {
1364 vec_resize(d_compound_buf.size() + 100);
1365 }
1366
1367 d_compound_buf[i] = val;
1368}
1369
1380{
1381 if (d_buf) {
1382 delete[] d_buf;
1383 d_buf = 0;
1384 }
1385
1386 for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
1387 delete d_compound_buf[i];
1388 d_compound_buf[i] = 0;
1389 }
1390
1391 // Force memory to be reclaimed.
1392 d_compound_buf.resize(0);
1393 d_str.resize(0);
1394
1395 d_capacity = 0;
1396 set_read_p(false);
1397}
1398
1406unsigned int Vector::get_value_capacity() const
1407{
1408 return d_capacity;
1409}
1410
1420void Vector::reserve_value_capacity(unsigned int numElements)
1421{
1422 if (!d_proto) {
1423 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1424 }
1425 switch (d_proto->type()) {
1426 case dods_byte_c:
1427 case dods_char_c:
1428 case dods_int8_c:
1429 case dods_uint8_c:
1430 case dods_int16_c:
1431 case dods_uint16_c:
1432 case dods_int32_c:
1433 case dods_uint32_c:
1434 case dods_int64_c:
1435 case dods_uint64_c:
1436
1437 case dods_enum_c:
1438
1439 case dods_float32_c:
1440 case dods_float64_c:
1441 // Make _buf be the right size and set _capacity
1443 break;
1444
1445 case dods_str_c:
1446 case dods_url_c:
1447 // Make sure the d_str has enough room for all the strings.
1448 // Technically not needed, but it will speed things up for large arrays.
1449 d_str.reserve(numElements);
1450 d_capacity = numElements;
1451 break;
1452
1453 case dods_array_c:
1454 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1455
1456 case dods_opaque_c:
1457 case dods_structure_c:
1458 case dods_sequence_c:
1459 case dods_grid_c:
1460 // not clear anyone will go this path, but best to be complete.
1461 d_compound_buf.reserve(numElements);
1462 d_capacity = numElements;
1463 break;
1464
1465 default:
1466 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1467 } // switch
1468
1469}
1470
1477{
1478 // Use the current length of the vector as the reserve amount.
1480}
1481
1510unsigned int
1511Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
1512{
1513 static const string funcName = "set_value_slice_from_row_major_vector:";
1514
1515 // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1516 Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
1517
1518 bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
1519 if (!typesMatch) {
1520 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
1521 }
1522
1523 // Make sure the data exists
1524 if (!rowMajorData.read_p()) {
1525 throw InternalErr(__FILE__, __LINE__,
1526 funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1527 }
1528
1529 // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1530 if (rowMajorData.length() < 0) {
1531 throw InternalErr(__FILE__, __LINE__,
1532 funcName
1533 + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
1534 }
1535
1536 // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
1537 // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
1538 if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
1539 throw InternalErr(__FILE__, __LINE__,
1540 funcName
1541 + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1542 }
1543
1544 // Make sure there's enough room in this Vector to store all the elements requested. Again,
1545 // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1546 if (d_capacity < (startElement + rowMajorData.length())) {
1547 throw InternalErr(__FILE__, __LINE__,
1548 funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1549 }
1550
1551 // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1552 switch (d_proto->type()) {
1553 case dods_int8_c:
1554 case dods_uint8_c:
1555 case dods_byte_c:
1556 case dods_char_c:
1557 case dods_int16_c:
1558 case dods_uint16_c:
1559 case dods_int32_c:
1560 case dods_uint32_c:
1561 case dods_int64_c:
1562 case dods_uint64_c:
1563
1564 case dods_enum_c:
1565
1566 case dods_float32_c:
1567 case dods_float64_c: {
1568 if (!d_buf) {
1569 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1570 }
1571 if (!rowMajorData.d_buf) {
1572 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1573 }
1574 // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1575 int varWidth = d_proto->width();
1576 char* pFromBuf = rowMajorData.d_buf;
1577 int numBytesToCopy = rowMajorData.width(true);
1578 char* pIntoBuf = d_buf + (startElement * varWidth);
1579 memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
1580 break;
1581 }
1582
1583 case dods_str_c:
1584 case dods_url_c:
1585 // Strings need to be copied directly
1586 for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
1587 d_str[startElement + i] = rowMajorData.d_str[i];
1588 }
1589 break;
1590
1591 case dods_array_c:
1592 case dods_opaque_c:
1593 case dods_structure_c:
1594 case dods_sequence_c:
1595 case dods_grid_c:
1596 // Not sure that this function will be used for these type of nested objects, so I will throw here.
1597 throw InternalErr(__FILE__, __LINE__,
1598 funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
1599
1600 default:
1601 throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1602 } // switch (_var->type())
1603
1604 // This is how many elements we copied.
1605 return (unsigned int) rowMajorData.length();
1606}
1607
1616template <typename T>
1617static bool types_match(Type t, T *cpp_var)
1618{
1619 switch (t) {
1620 case dods_byte_c:
1621 case dods_char_c:
1622 case dods_uint8_c:
1623 return typeid(cpp_var) == typeid(dods_byte*);
1624
1625 case dods_int8_c:
1626 return typeid(cpp_var) == typeid(dods_int8*);
1627 case dods_int16_c:
1628 return typeid(cpp_var) == typeid(dods_int16*);
1629 case dods_uint16_c:
1630 return typeid(cpp_var) == typeid(dods_uint16*);
1631 case dods_int32_c:
1632 return typeid(cpp_var) == typeid(dods_int32*);
1633 case dods_uint32_c:
1634 return typeid(cpp_var) == typeid(dods_uint32*);
1635 case dods_int64_c:
1636 return typeid(cpp_var) == typeid(dods_int64*);
1637 case dods_uint64_c:
1638 return typeid(cpp_var) == typeid(dods_uint64*);
1639
1640 case dods_float32_c:
1641 return typeid(cpp_var) == typeid(dods_float32*);
1642 case dods_float64_c:
1643 return typeid(cpp_var) == typeid(dods_float64*);
1644
1645 case dods_null_c:
1646 case dods_enum_c:
1647 case dods_str_c:
1648 case dods_url_c:
1649 case dods_opaque_c:
1650 case dods_array_c:
1651 case dods_structure_c:
1652 case dods_sequence_c:
1653 case dods_group_c:
1654 default:
1655 return false;
1656 }
1657}
1658
1660
1662template <typename T>
1663bool Vector::set_value_worker(T *v, int sz)
1664{
1665 if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1666 return false;
1667
1669 return true;
1670}
1671
1672bool Vector::set_value(dods_byte *val, int sz)
1673{
1674 return set_value_worker(val, sz);
1675}
1676bool Vector::set_value(dods_int8 *val, int sz)
1677{
1678 return set_value_worker(val, sz);
1679}
1680bool Vector::set_value(dods_int16 *val, int sz)
1681{
1682 return set_value_worker(val, sz);
1683}
1684bool Vector::set_value(dods_uint16 *val, int sz)
1685{
1686 return set_value_worker(val, sz);
1687}
1688bool Vector::set_value(dods_int32 *val, int sz)
1689{
1690 return set_value_worker(val, sz);
1691}
1692bool Vector::set_value(dods_uint32 *val, int sz)
1693{
1694 return set_value_worker(val, sz);
1695}
1696bool Vector::set_value(dods_int64 *val, int sz)
1697{
1698 return set_value_worker(val, sz);
1699}
1700bool Vector::set_value(dods_uint64 *val, int sz)
1701{
1702 return set_value_worker(val, sz);
1703}
1704bool Vector::set_value(dods_float32 *val, int sz)
1705{
1706 return set_value_worker(val, sz);
1707}
1708bool Vector::set_value(dods_float64 *val, int sz)
1709{
1710 return set_value_worker(val, sz);
1711}
1712
1720bool Vector::set_value(string *val, int sz)
1721{
1722 if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
1723 d_str.resize(sz);
1724 d_capacity = sz;
1725 for (int t = 0; t < sz; t++) {
1726 d_str[t] = val[t];
1727 }
1728 set_length(sz);
1729 set_read_p(true);
1730 return true;
1731 }
1732 else {
1733 return false;
1734 }
1735}
1736
1737template<typename T>
1738bool Vector::set_value_worker(vector<T> &v, int sz)
1739{
1740 return set_value(&v[0], sz);
1741}
1742
1743bool Vector::set_value(vector<dods_byte> &val, int sz)
1744{
1745 return set_value_worker(val, sz);
1746}
1747bool Vector::set_value(vector<dods_int8> &val, int sz)
1748{
1749 return set_value_worker(val, sz);
1750}
1751bool Vector::set_value(vector<dods_int16> &val, int sz)
1752{
1753 return set_value_worker(val, sz);
1754}
1755bool Vector::set_value(vector<dods_uint16> &val, int sz)
1756{
1757 return set_value_worker(val, sz);
1758}
1759bool Vector::set_value(vector<dods_int32> &val, int sz)
1760{
1761 return set_value_worker(val, sz);
1762}
1763bool Vector::set_value(vector<dods_uint32> &val, int sz)
1764{
1765 return set_value_worker(val, sz);
1766}
1767bool Vector::set_value(vector<dods_int64> &val, int sz)
1768{
1769 return set_value_worker(val, sz);
1770}
1771bool Vector::set_value(vector<dods_uint64> &val, int sz)
1772{
1773 return set_value_worker(val, sz);
1774}
1775bool Vector::set_value(vector<dods_float32> &val, int sz)
1776{
1777 return set_value_worker(val, sz);
1778}
1779bool Vector::set_value(vector<dods_float64> &val, int sz)
1780{
1781 return set_value_worker(val, sz);
1782}
1783
1784
1786bool Vector::set_value(vector<string> &val, int sz)
1787{
1788 if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
1789 d_str.resize(sz);
1790 d_capacity = sz;
1791 for (int t = 0; t < sz; t++) {
1792 d_str[t] = val[t];
1793 }
1794 set_length(sz);
1795 set_read_p(true);
1796 return true;
1797 }
1798 else {
1799 return false;
1800 }
1801}
1803
1805
1822template <typename T>
1823void Vector::value_worker(vector<unsigned int> *indices, T *b) const
1824{
1825 // unsigned long currentIndex;
1826#if 0
1827 // Iterator version. Not tested, jhrg 8/14/13
1828 for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
1829 unsigned long currentIndex = *i;
1830 if(currentIndex > (unsigned int)length()){
1831 stringstream s;
1832 s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
1833 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1834 throw Error(s.str());
1835 }
1836 b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
1837 }
1838#endif
1839 for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
1840 unsigned long currentIndex = (*indices)[i];
1841 if (currentIndex > (unsigned int)length()) {
1842 stringstream s;
1843 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1844 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1845 throw Error(s.str());
1846 }
1847 b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
1848 }
1849}
1850void Vector::value(vector<unsigned int> *indices, dods_byte *b) const { value_worker(indices, b); }
1851void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const { value_worker(indices, b); }
1852void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const { value_worker(indices, b); }
1853void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const { value_worker(indices, b); }
1854void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const { value_worker(indices, b); }
1855void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const { value_worker(indices, b); }
1856void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const { value_worker(indices, b); }
1857void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const { value_worker(indices, b); }
1858void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
1859void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
1860
1861#if 0
1862template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
1863template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
1864template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
1865template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
1866template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
1867template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
1868template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
1869template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
1870template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
1871template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
1872#endif
1873
1875void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const
1876{
1877 unsigned long currentIndex;
1878
1879 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
1880 for(unsigned long i=0; i<subsetIndex->size() ;++i){
1881 currentIndex = (*subsetIndex)[i] ;
1882 if(currentIndex > (unsigned int)length()){
1883 stringstream s;
1884 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1885 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1886 throw Error(s.str());
1887 }
1888 b[i] = d_str[currentIndex];
1889 }
1890 }
1891}
1892
1893template <typename T>
1894void Vector::value_worker(T *v) const
1895{
1896 // Only copy if v is not null and the proto's type matches.
1897 // For Enums, use the element type since type == dods_enum_c.
1898 if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1899 memcpy(v, d_buf, length() * sizeof(T));
1900}
1901void Vector::value(dods_byte *b) const { value_worker(b); }
1902void Vector::value(dods_int8 *b) const { value_worker(b); }
1903void Vector::value(dods_int16 *b) const { value_worker(b); }
1904void Vector::value(dods_uint16 *b) const { value_worker(b); }
1905void Vector::value(dods_int32 *b) const { value_worker(b); }
1906void Vector::value(dods_uint32 *b) const { value_worker(b); }
1907void Vector::value(dods_int64 *b) const { value_worker(b); }
1908void Vector::value(dods_uint64 *b) const { value_worker(b); }
1909void Vector::value(dods_float32 *b) const { value_worker(b); }
1910void Vector::value(dods_float64 *b) const { value_worker(b); }
1911
1912#if 0
1913template void Vector::value(dods_byte *v) const;
1914template void Vector::value(dods_int8 *v) const;
1915template void Vector::value(dods_int16 *v) const;
1916template void Vector::value(dods_uint16 *v) const;
1917template void Vector::value(dods_int32 *v) const;
1918template void Vector::value(dods_uint32 *v) const;
1919template void Vector::value(dods_int64 *v) const;
1920template void Vector::value(dods_uint64 *v) const;
1921template void Vector::value(dods_float32 *v) const;
1922template void Vector::value(dods_float64 *v) const;
1923#endif
1924
1925
1927void Vector::value(vector<string> &b) const
1928{
1929 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
1930 b = d_str;
1931}
1932
1936{
1937 void *buffer = new char[width(true)];
1938
1939 memcpy(buffer, d_buf, width(true));
1940
1941 return buffer;
1942}
1944
1961{
1962#if 0
1963 // Why doesn't this work? tried all 3 variants. jhrg 8/14/13
1964 Vector::add_var_nocopy(v->ptr_duplicate(), p);
1965 add_var_nocopy(v->ptr_duplicate(), p);
1966 add_var_nocopy(v->ptr_duplicate());
1967#else
1968 // Delete the current template variable
1969 if (d_proto) {
1970 delete d_proto;
1971 d_proto = 0;
1972 }
1973
1974 // if 'v' is null, just set _var to null and exit.
1975 if (!v) {
1976 d_proto = 0;
1977 }
1978 else {
1979 // Jose Garcia
1980 // By getting a copy of this object to be assigned to _var
1981 // we let the owner of 'v' to deallocate it as necessary.
1982 d_proto = v->ptr_duplicate();
1983
1984 // If 'v' has a name, use it as the name of the array. If v doesn't have
1985 // a name, then make sure to copy the array's name to it
1986 // so that software which uses the template's name will still work.
1987 if (!v->name().empty())
1988 set_name(v->name());
1989 else
1990 d_proto->set_name(name());
1991
1992 d_proto->set_parent(this); // Vector --> child
1993
1994 DBG(cerr << "Vector::add_var: Added variable " << v << " ("
1995 << v->name() << " " << v->type_name() << ")" << endl);
1996 }
1997#endif
1998}
1999
2000void Vector::add_var_nocopy(BaseType * v, Part)
2001{
2002 // Delete the current template variable
2003 if (d_proto) {
2004 delete d_proto;
2005 d_proto = 0;
2006 }
2007
2008 // if 'v' is null, just set _var to null and exit.
2009 if (!v) {
2010 d_proto = 0;
2011 }
2012 else {
2013 d_proto = v;
2014
2015 // If 'v' has a name, use it as the name of the array. If it *is*
2016 // empty, then make sure to copy the array's name to the template
2017 // so that software which uses the template's name will still work.
2018 if (!v->name().empty())
2019 set_name(v->name());
2020 else
2021 d_proto->set_name(name());
2022
2023 d_proto->set_parent(this); // Vector is the parent; proto is the child
2024
2025 DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " ("
2026 << v->name() << " " << v->type_name() << ")" << endl);
2027 }
2028}
2029
2030bool Vector::check_semantics(string & msg, bool)
2031{
2032 return BaseType::check_semantics(msg);
2033}
2034
2043void Vector::dump(ostream &strm) const
2044{
2045 strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
2046 DapIndent::Indent();
2047 BaseType::dump(strm);
2048 strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
2049 if (d_proto) {
2050 strm << DapIndent::LMarg << "base type:" << endl;
2051 DapIndent::Indent();
2052 d_proto->dump(strm);
2053 DapIndent::UnIndent();
2054 }
2055 else {
2056 strm << DapIndent::LMarg << "base type: not set" << endl;
2057 }
2058 strm << DapIndent::LMarg << "vector contents:" << endl;
2059 DapIndent::Indent();
2060 for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
2061 if (d_compound_buf[i])
2062 d_compound_buf[i]->dump(strm);
2063 else
2064 strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
2065 }
2066 DapIndent::UnIndent();
2067 strm << DapIndent::LMarg << "strings:" << endl;
2068 DapIndent::Indent();
2069 for (unsigned i = 0; i < d_str.size(); i++) {
2070 strm << DapIndent::LMarg << d_str[i] << endl;
2071 }
2072 DapIndent::UnIndent();
2073 if (d_buf) {
2074 switch (d_proto != 0 ? d_proto->type() : 0) {
2075 case dods_byte_c:
2076 case dods_char_c:
2077 strm << DapIndent::LMarg << "_buf: ";
2078 strm.write(d_buf, d_length);
2079 strm << endl;
2080 break;
2081
2082 case 0:
2083 default:
2084 strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl;
2085 break;
2086 }
2087 }
2088 else {
2089 strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
2090 }
2091
2092 DapIndent::UnIndent();
2093}
2094
2095} // namespace libdap
2096
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:379
virtual bool read()
Read data into a local buffer.
Definition: BaseType.cc:899
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:320
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:480
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:1299
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:516
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:358
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Returns a pointer to a member of a constructor class.
Definition: BaseType.cc:758
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:733
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: BaseType.cc:443
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition: BaseType.cc:344
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:412
virtual void set_send_p(bool state)
Definition: BaseType.cc:568
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 void dump(ostream &strm) const
dumps information about this object
Definition: BaseType.cc:291
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: BaseType.cc:1209
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition: BaseType.cc:126
virtual Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:365
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:62
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_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.
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
Definition: UnMarshaller.h:55
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:1960
virtual void set_length(int l)
Definition: Vector.cc:555
virtual unsigned int get_value_capacity() const
Definition: Vector.cc:1406
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:1342
void m_set_cardinal_values_internal(const CardType *fromArray, int numElts)
Definition: Vector.cc:219
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:1511
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:1326
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:2043
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:125
virtual void clear_local_data()
Definition: Vector.cc:1379
virtual void * value()
Definition: Vector.cc:1935
void vec_resize(int l)
Definition: Vector.cc:568
void m_delete_cardinal_data_buffer()
Definition: Vector.cc:208
virtual void reserve_value_capacity()
Definition: Vector.cc:1476
unsigned int m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
Definition: Vector.cc:180
virtual unsigned int buf2val(void **val)
Copies data from the Vector buffer.
Definition: Vector.cc:1248
Vector(const string &n, BaseType *v, const Type &t, bool is_dap4=false)
The Vector constructor.
Definition: Vector.cc:248
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: Vector.cc:2030
top level DAP object to house generic methods
Definition: AlarmHandler.h:36
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