libdap Updated for version 3.18.1
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
68#undef CLEAR_LOCAL_DATA
69
70using std::cerr;
71using std::endl;
72
73namespace libdap {
74
75void Vector::m_duplicate(const Vector & v)
76{
77 d_length = v.d_length;
78
79 // _var holds the type of the elements. That is, it holds a BaseType
80 // which acts as a template for the type of each element.
81 if (v.d_proto) {
82 d_proto = v.d_proto->ptr_duplicate(); // use ptr_duplicate()
83 d_proto->set_parent(this); // ptr_duplicate does not set d_parent.
84 }
85 else {
86 d_proto = 0;
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 }
96 else {
97 // Failure to set the size will make the [] operator barf on the LHS
98 // of the assignment inside the loop.
99 d_compound_buf.resize(d_length);
100 for (int i = 0; i < d_length; ++i) {
101 // There's no need to call set_parent() for each element; we
102 // maintain the back pointer using the d_proto member. These
103 // instances are used to hold _values_ only while the d_proto
104 // field holds the type information for the elements.
105 d_compound_buf[i] = v.d_compound_buf[i]->ptr_duplicate();
106 }
107 }
108
109 // copy the strings. This copies the values.
110 d_str = v.d_str;
111
112 // copy numeric values if there are any.
113 d_buf = 0; // init to null
114 if (v.d_buf) // only copy if data present
115 val2buf(v.d_buf); // store v's value in this's _BUF.
116
117 d_capacity = v.d_capacity;
118}
119
125{
126 // Not cardinal if no d_proto at all!
127 if (!d_proto) {
128 return false;
129 }
130
131 switch (d_proto->type()) {
132 case dods_byte_c:
133 case dods_char_c:
134 case dods_int16_c:
135 case dods_uint16_c:
136 case dods_int32_c:
137 case dods_uint32_c:
138 case dods_float32_c:
139 case dods_float64_c:
140 // New cardinal types for DAP4
141 case dods_int8_c:
142 case dods_uint8_c:
143 case dods_int64_c:
144 case dods_uint64_c:
145
146 case dods_enum_c:
147 return true;
148 break;
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 break;
162
163 default:
164 assert("Vector::var: Unrecognized type");
165 return false;
166 }
167}
168
181unsigned int Vector::m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
182{
183 // Make sure we HAVE a _var, or we cannot continue.
184 if (!d_proto) {
185 throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
186 }
187
188 // Make sure we only do this for the correct data types.
189 if (!m_is_cardinal_type()) {
190 throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
191 }
192
194
195 // Handle this special case where this is an array that holds no values
196 if (numEltsOfType == 0)
197 return 0;
198
199 // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
200 unsigned int bytesPerElt = d_proto->width();
201 unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
202 d_buf = new char[bytesNeeded];
203
204 d_capacity = numEltsOfType;
205 return bytesNeeded;
206}
207
210{
211 delete[] d_buf;
212 d_buf = 0;
213 d_capacity = 0;
214}
215
219template<class CardType>
220void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int numElts)
221{
222 if (numElts < 0) {
223 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
224 }
225 if (!fromArray) {
226 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
227 }
228 set_length(numElts);
230 memcpy(d_buf, fromArray, numElts * sizeof(CardType));
231 set_read_p(true);
232}
233
249Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
250 BaseType(n, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
251{
252 if (v)
253 add_var(v);
254
255 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
256 if (d_proto)
257 d_proto->set_parent(this);
258}
259
278Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
279 BaseType(n, d, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
280{
281 if (v)
282 add_var(v);
283
284 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
285 if (d_proto)
286 d_proto->set_parent(this);
287}
288
290Vector::Vector(const Vector & rhs) :
291 BaseType(rhs)
292{
293 DBG2(cerr << "Entering Vector const ctor for object: " << this <<
294 endl); DBG2(cerr << "RHS: " << &rhs << endl);
295
296 m_duplicate(rhs);
297}
298
299Vector::~Vector()
300{
301 DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
302
303 delete d_proto;
304 d_proto = 0;
305
306 // Clears all buffers
308
309 DBG2(cerr << "Exiting ~Vector" << endl);
310}
311
312Vector & Vector::operator=(const Vector & rhs)
313{
314 if (this == &rhs)
315 return *this;
316
317 dynamic_cast<BaseType &> (*this) = rhs;
318
319 m_duplicate(rhs);
320
321 return *this;
322}
323
324void Vector::set_name(const std::string& name)
325{
327 // We need to set the prototype name as well since
328 // this is what gets output in the dds! Otherwise, there's a mismatch.
329 if (d_proto) {
330 d_proto->set_name(name);
331 }
332}
333
334int Vector::element_count(bool leaves)
335{
336 if (!leaves)
337 return 1;
338 else
339 return d_proto->element_count(leaves);
340 // var() only works for simple types!
341 // jhrg 8/19/13 return var(0)->element_count(leaves);
342}
343
344// These mfuncs set the _send_p and _read_p fields of BaseType. They differ
345// from BaseType's version in that they set both the Vector object's copy of
346// _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
347// is a scalar, but does matter when it is an aggregate.
348
355void Vector::set_send_p(bool state)
356{
357 if (d_proto) {
358 d_proto->set_send_p(state);
359
360 // because some code may depend on the BaseType*s held in d_compound_buf
361 // behaving as if they are 'ordinary' DAP variables, make sure their send_p
362 // flag is set if they exist. Because space in the vector is allocated
363 // before values (BaseType*s) are added, check for nulls and limit the
364 // iteration to only those elements actually in the object including any
365 // constraints that may have been applied - these are values not declarations.
366 // jhrg 5/13/16
367 switch (d_proto->type()) {
368 case dods_structure_c:
369 case dods_sequence_c:
370 case dods_grid_c:
371 if (d_compound_buf.size() > 0) {
372 for (unsigned long long i = 0; i < (unsigned) d_length; ++i) {
373 if (d_compound_buf[i]) d_compound_buf[i]->set_send_p(state);
374 }
375 }
376 break;
377
378 default:
379 break;
380 }
381 }
382
384}
385
392void Vector::set_read_p(bool state)
393{
394 if (d_proto) {
395 d_proto->set_read_p(state);
396
397 // See comment above.
398 switch (d_proto->type()) {
399 case dods_structure_c:
400 case dods_sequence_c:
401 case dods_grid_c:
402 if (d_compound_buf.size() > 0) {
403 for (unsigned long long i = 0; i < (unsigned)d_length; ++i) {
404 if (d_compound_buf[i]) d_compound_buf[i]->set_read_p(state);
405 }
406 }
407 break;
408
409 default:
410 break;
411 }
412 }
413
415}
416
434BaseType *Vector::var(const string &n, bool exact, btp_stack *s)
435{
436 string name = www2id(n);
437 DBG2(cerr << "Vector::var: Looking for " << name << endl);
438
439 // If this is a Vector of constructor types, look for 'name' recursively.
440 // Make sure to check for the case where name is the default (the empty
441 // string). 9/1/98 jhrg
442 if (d_proto->is_constructor_type()) {
443 if (name == "" || d_proto->name() == name) {
444 if (s)
445 s->push(this);
446 return d_proto;
447 }
448 else {
449 BaseType * result = d_proto->var(name, exact, s);
450 if (result && s)
451 s->push(this);
452 return result;
453 }
454 }
455 else {
456 return d_proto;
457 }
458}
459
470BaseType *Vector::var(const string & n, btp_stack & s)
471{
472 string name = www2id(n);
473
474 if (d_proto->is_constructor_type())
475 return d_proto->var(name, s);
476 else {
477 s.push((BaseType *) this);
478 return d_proto;
479 }
480}
481
493BaseType *Vector::var(unsigned int i)
494{
495
496 switch (d_proto->type()) {
497 case dods_byte_c:
498 case dods_char_c:
499 case dods_int8_c:
500 case dods_uint8_c:
501 case dods_int16_c:
502 case dods_uint16_c:
503 case dods_int32_c:
504 case dods_uint32_c:
505 case dods_int64_c:
506 case dods_uint64_c:
507
508 case dods_enum_c:
509
510 case dods_float32_c:
511 case dods_float64_c:
512 // Transfer the ith value to the BaseType *d_proto
513 d_proto->val2buf(d_buf + (i * d_proto->width()));
514 return d_proto;
515 break;
516
517 case dods_str_c:
518 case dods_url_c:
519 d_proto->val2buf(&d_str[i]);
520 return d_proto;
521 break;
522
523 case dods_opaque_c:
524 case dods_array_c:
525 case dods_structure_c:
526 case dods_sequence_c:
527 case dods_grid_c:
528 return d_compound_buf[i];
529 break;
530
531 default:
532 throw Error ("Vector::var: Unrecognized type");
533 break;
534 }
535
536 return 0;
537}
538
545unsigned int Vector::width(bool constrained) const
546{
547 // Jose Garcia
548 assert(d_proto);
549
550 return length() * d_proto->width(constrained);
551}
552
557int Vector::length() const
558{
559 return d_length;
560}
561
565{
566 d_length = l;
567}
568
578{
579 // I added this check, which alters the behavior of the method. jhrg 8/14/13
580 if (m_is_cardinal_type())
581 throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
582
583 d_compound_buf.resize((l > 0) ? l : 0, 0); // Fill with NULLs
584 d_capacity = l; // capacity in terms of number of elements.
585}
586
604{
605 DBG(cerr << "Vector::intern_data: " << name() << endl);
606 if (!read_p())
607 read(); // read() throws Error and InternalErr
608
609 // length() is not capacity; it must be set explicitly in read().
610 int num = length();
611
612 switch (d_proto->type()) {
613 case dods_byte_c:
614 case dods_int16_c:
615 case dods_uint16_c:
616 case dods_int32_c:
617 case dods_uint32_c:
618 case dods_float32_c:
619 case dods_float64_c:
620 // For these cases, read() puts the data into d_buf,
621 // which is what we need.
622 break;
623
624 case dods_str_c:
625 case dods_url_c:
626 // For these cases, read() will put the data into d_str[],
627 // which is also what we need.
628 break;
629
630 case dods_array_c:
631 // This is an error since there can never be an Array of Array.
632 throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
633 break;
634
635 case dods_structure_c:
636 case dods_sequence_c:
637 case dods_grid_c:
638 DBG(cerr << "Vector::intern_data: found ctor" << endl);
639 // For these cases, we need to call read() for each of the 'num'
640 // elements in the 'd_compound_buf[]' array of BaseType object pointers.
641 //
642 // I changed the test here from '... = 0' to '... < num' to accommodate
643 // the case where the array is zero-length.
644 if (d_compound_buf.capacity() < (unsigned)num)
645 throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements.");
646
647 for (int i = 0; i < num; ++i)
648 d_compound_buf[i]->intern_data(eval, dds);
649
650 break;
651
652 default:
653 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
654 break;
655 }
656}
657
669bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
670{
671#if 0
672 dds.timeout_on();
673#endif
674 // Added to streamline zero-length arrays. Not needed for correct function,
675 // but explicitly handling this case here makes the code easier to follow.
676 // In libdap::Vector::val2buf() there is a test that will catch the zero-length
677 // case as well. We still need to call serialize since it will write size
678 // information that the client depends on. jhrg 2/17/16
679 if (length() == 0)
680 set_read_p(true);
681 else if (!read_p())
682 read(); // read() throws Error and InternalErr
683
684 if (ce_eval && !eval.eval_selection(dds, dataset()))
685 return true;
686#if 0
687 dds.timeout_off();
688#endif
689 // length() is not capacity; it must be set explicitly in read().
690 int num = length();
691
692 bool status = false;
693
694 switch (d_proto->type()) {
695 case dods_byte_c:
696 m.put_vector(d_buf, num, *this);
697 status = true;
698 break;
699
700 case dods_int16_c:
701 case dods_uint16_c:
702 case dods_int32_c:
703 case dods_uint32_c:
704 case dods_float32_c:
705 case dods_float64_c:
706 m.put_vector(d_buf, num, d_proto->width(), *this);
707 status = true;
708
709 break;
710
711 case dods_str_c:
712 case dods_url_c:
713 if (d_str.capacity() == 0)
714 throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
715
716 m.put_int(num);
717
718 for (int i = 0; i < num; ++i)
719 m.put_str(d_str[i]);
720
721 status = true;
722 break;
723
724 case dods_array_c:
725 case dods_structure_c:
726 case dods_sequence_c:
727 case dods_grid_c:
728 //Jose Garcia
729 // Not setting the capacity of d_compound_buf is an internal error.
730 if (d_compound_buf.capacity() == 0)
731 throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
732
733 m.put_int(num);
734 status = true;
735 for (int i = 0; i < num && status; ++i)
736 status = status && d_compound_buf[i]->serialize(eval, dds, m, false);
737
738 break;
739
740 default:
741 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
742 break;
743 }
744
745#ifdef CLEAR_LOCAL_DATA
747#endif
748
749 return status;
750}
751
752// Read an object from the network and internalize it. For a Vector this is
753// handled differently for a `cardinal' type. Vectors of Cardinals are
754// stored using the `C' representations because these objects often are used
755// to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
756// arrays of non-cardinal types are stored as Vectors of the C++ objects or
757// DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
758// Grid are vectors of the libdap Structure, ... classes).
759//
760// The boolean parameter REUSE determines whether internal storage is reused
761// or not. If true, the _buf member is assumed to be large enough to hold the
762// incoming cardinal data and is *not* reallocated. If false, new storage is
763// allocated. If the internal buffer has not yet been allocated, then this
764// parameter has no effect (i.e., storage is allocated). This parameter
765// effects storage for cardinal data only.
766//
767// Returns: True is successful, false otherwise.
768
769bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
770{
771 unsigned int num;
772 unsigned i = 0;
773
774 switch (d_proto->type()) {
775 case dods_byte_c:
776 case dods_int16_c:
777 case dods_uint16_c:
778 case dods_int32_c:
779 case dods_uint32_c:
780 case dods_float32_c:
781 case dods_float64_c:
782 um.get_int((int &) num);
783
784 DBG(cerr << "Vector::deserialize: num = " << num << endl);
785 DBG(cerr << "Vector::deserialize: length = " << length() << endl);
786
787 if (length() == -1)
788 set_length(num);
789
790 if (num != (unsigned int) length())
791 throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes for the variable '" + name() + "'.");
792
793 if (!d_buf || !reuse) {
794 // Make d_buf be large enough for length() elements of _var->type()
795 // m_create...() deletes the old buffer.
797 DBG(cerr << "Vector::deserialize: allocating "
798 << width() << " bytes for an array of "
799 << length() << " " << d_proto->type_name() << endl);
800 }
801
802 // Added to accommodate zero-length arrays.
803 // Note that the rest of the cases will just send the size without data
804 // but that these calls trigger error testing in the UnMarshaller code.
805 // jhrg 1/28/16
806 if (num == 0)
807 return true;
808
809 if (d_proto->type() == dods_byte_c)
810 um.get_vector((char **) &d_buf, num, *this);
811 else
812 um.get_vector((char **) &d_buf, num, d_proto->width(), *this);
813
814 DBG(cerr << "Vector::deserialize: read " << num << " elements\n");
815
816 break;
817
818 case dods_str_c:
819 case dods_url_c:
820 um.get_int((int &) num);
821
822 if (length() == -1)
823 set_length(num);
824
825 if (num != (unsigned int) length())
826 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
827
828 d_str.resize((num > 0) ? num : 0); // Fill with NULLs
829 d_capacity = num; // capacity is number of strings we can fit.
830
831 for (i = 0; i < num; ++i) {
832 string str;
833 um.get_str(str);
834 d_str[i] = str;
835
836 }
837
838 break;
839
840 case dods_array_c:
841 // TODO
842 case dods_structure_c:
843 case dods_sequence_c:
844 case dods_grid_c:
845 um.get_int((int &) num);
846
847 if (length() == -1)
848 set_length(num);
849
850 if (num != (unsigned int) length())
851 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
852
853 vec_resize(num);
854
855 for (i = 0; i < num; ++i) {
856 d_compound_buf[i] = d_proto->ptr_duplicate();
857 d_compound_buf[i]->deserialize(um, dds);
858 }
859
860 break;
861
862 default:
863 throw InternalErr(__FILE__, __LINE__, "Unknown type!");
864 break;
865 }
866
867 return false;
868}
869
871{
872 switch (d_proto->type()) {
873 case dods_byte_c:
874 case dods_char_c:
875 case dods_int8_c:
876 case dods_uint8_c:
877
878 case dods_int16_c:
879 case dods_uint16_c:
880
881 case dods_int32_c:
882 case dods_uint32_c:
883 case dods_float32_c:
884
885 case dods_int64_c:
886 case dods_uint64_c:
887 case dods_float64_c:
888
889 case dods_enum_c:
890 checksum.AddData(reinterpret_cast<uint8_t*>(d_buf), length() * d_proto->width());
891 break;
892
893 case dods_str_c:
894 case dods_url_c:
895 for (int64_t i = 0, e = length(); i < e; ++i)
896 checksum.AddData(reinterpret_cast<const uint8_t*>(d_str[i].data()), d_str[i].length());
897 break;
898
899 case dods_opaque_c:
900 case dods_structure_c:
901 case dods_sequence_c:
902 d_proto->compute_checksum(checksum);
903 break;
904
905 case dods_array_c: // No array of array
906 case dods_grid_c: // No grids in DAP4
907 default:
908 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
909 break;
910 }
911}
912
913void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
914{
915 if (!read_p())
916 read(); // read() throws Error and InternalErr
917
918 switch (d_proto->type()) {
919 case dods_byte_c:
920 case dods_char_c:
921 case dods_int8_c:
922 case dods_uint8_c:
923 case dods_int16_c:
924 case dods_uint16_c:
925 case dods_int32_c:
926 case dods_uint32_c:
927 case dods_int64_c:
928 case dods_uint64_c:
929
930 case dods_enum_c:
931
932 case dods_float32_c:
933 case dods_float64_c:
934
935 case dods_str_c:
936 case dods_url_c:
937#if 0
938 compute_checksum(checksum);
939#endif
940 break;
941
942 case dods_opaque_c:
943 case dods_structure_c:
944 case dods_sequence_c:
945 // Modified the assert here from '... != 0' to '... >= length())
946 // to accommodate the case of a zero-length array. jhrg 1/28/16
947 assert(d_compound_buf.capacity() >= (unsigned)length());
948
949 for (int i = 0, e = length(); i < e; ++i)
950 d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/);
951 break;
952
953 case dods_array_c: // No Array of Array in DAP4 either...
954 case dods_grid_c:
955 default:
956 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
957 break;
958 }
959}
960
961void
962Vector::serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter /*= false*/)
963{
964 if (!read_p())
965 read(); // read() throws Error and InternalErr
966#if 0
967 if (filter && !eval.eval_selection(dmr, dataset()))
968 return true;
969#endif
970 int64_t num = length(); // The constrained length in elements
971
972 DBG(cerr << __PRETTY_FUNCTION__ << ", num: " << num << endl);
973
974 // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16
975 if (num == 0)
976 return;
977
978 switch (d_proto->type()) {
979 case dods_byte_c:
980 case dods_char_c:
981 case dods_int8_c:
982 case dods_uint8_c:
983 m.put_vector(d_buf, num);
984 break;
985
986 case dods_int16_c:
987 case dods_uint16_c:
988 case dods_int32_c:
989 case dods_uint32_c:
990 case dods_int64_c:
991 case dods_uint64_c:
992 m.put_vector(d_buf, num, d_proto->width());
993 break;
994
995 case dods_enum_c:
996 if (d_proto->width() == 1)
997 m.put_vector(d_buf, num);
998 else
999 m.put_vector(d_buf, num, d_proto->width());
1000 break;
1001
1002 case dods_float32_c:
1003 m.put_vector_float32(d_buf, num);
1004 break;
1005
1006 case dods_float64_c:
1007 m.put_vector_float64(d_buf, num);
1008 break;
1009
1010 case dods_str_c:
1011 case dods_url_c:
1012 assert((int64_t)d_str.capacity() >= num);
1013
1014 for (int64_t i = 0; i < num; ++i)
1015 m.put_str(d_str[i]);
1016
1017 break;
1018
1019 case dods_array_c:
1020 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1021
1022 case dods_opaque_c:
1023 case dods_structure_c:
1024 case dods_sequence_c:
1025 assert(d_compound_buf.capacity() >= 0);
1026
1027 for (int64_t i = 0; i < num; ++i)
1028 d_compound_buf[i]->serialize(m, dmr, /*eval,*/ filter);
1029
1030 break;
1031
1032 case dods_grid_c:
1033 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1034
1035 default:
1036 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
1037 break;
1038 }
1039
1040#ifdef CLEAR_LOCAL_DATA
1042#endif
1043}
1044
1045void
1047{
1048 if (m_is_cardinal_type()) {
1049 if (d_buf)
1051 if (!d_buf)
1053 }
1054
1055 DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl);
1056
1057 // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16
1058 if (length() == 0)
1059 return;
1060
1061 switch (d_proto->type()) {
1062 case dods_byte_c:
1063 case dods_char_c:
1064 case dods_int8_c:
1065 case dods_uint8_c:
1066 um.get_vector((char *)d_buf, length());
1067 break;
1068
1069 case dods_int16_c:
1070 case dods_uint16_c:
1071 case dods_int32_c:
1072 case dods_uint32_c:
1073 case dods_int64_c:
1074 case dods_uint64_c:
1075 um.get_vector((char *)d_buf, length(), d_proto->width());
1076 break;
1077
1078 case dods_enum_c:
1079 if (d_proto->width() == 1)
1080 um.get_vector((char *)d_buf, length());
1081 else
1082 um.get_vector((char *)d_buf, length(), d_proto->width());
1083 break;
1084
1085 case dods_float32_c:
1086 um.get_vector_float32((char *)d_buf, length());
1087 break;
1088
1089 case dods_float64_c:
1090 um.get_vector_float64((char *)d_buf, length());
1091 break;
1092
1093 case dods_str_c:
1094 case dods_url_c: {
1095 int64_t len = length();
1096 d_str.resize((len > 0) ? len : 0); // Fill with NULLs
1097 d_capacity = len; // capacity is number of strings we can fit.
1098
1099 for (int64_t i = 0; i < len; ++i) {
1100 um.get_str(d_str[i]);
1101 }
1102
1103 break;
1104 }
1105
1106 case dods_array_c:
1107 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1108
1109 case dods_opaque_c:
1110 case dods_structure_c:
1111 case dods_sequence_c: {
1112 vec_resize(length());
1113
1114 for (int64_t i = 0, end = length(); i < end; ++i) {
1115 d_compound_buf[i] = d_proto->ptr_duplicate();
1116 d_compound_buf[i]->deserialize(um, dmr);
1117 }
1118
1119 break;
1120 }
1121
1122 case dods_grid_c:
1123 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1124
1125 default:
1126 throw InternalErr(__FILE__, __LINE__, "Unknown type.");
1127 break;
1128 }
1129}
1130
1158unsigned int Vector::val2buf(void *val, bool reuse)
1159{
1160 // Jose Garcia
1161
1162 // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
1163 if (!val && length() == 0)
1164 return 0;
1165
1166 // I *think* this method has been mainly designed to be use by read which
1167 // is implemented in the surrogate library. Passing NULL as a pointer to
1168 // this method will be an error of the creator of the surrogate library.
1169 // Even though I recognize the fact that some methods inside libdap++ can
1170 // call val2buf, I think by now no coding bugs such as misusing val2buf
1171 // will be in libdap++, so it will be an internal error from the
1172 // surrogate library.
1173 if (!val)
1174 throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
1175
1176 switch (d_proto->type()) {
1177 case dods_byte_c:
1178 case dods_char_c:
1179 case dods_int8_c:
1180 case dods_uint8_c:
1181 case dods_int16_c:
1182 case dods_uint16_c:
1183 case dods_int32_c:
1184 case dods_uint32_c:
1185 case dods_int64_c:
1186 case dods_uint64_c:
1187
1188 case dods_enum_c:
1189
1190 case dods_float32_c:
1191 case dods_float64_c:
1192#if 0
1193 if (d_buf && !reuse)
1195#endif
1196 // First time or no reuse (free'd above)
1197 if (!d_buf || !reuse)
1199
1200 // width(true) returns the size in bytes given the constraint
1201 memcpy(d_buf, val, width(true));
1202 break;
1203
1204 case dods_str_c:
1205 case dods_url_c:
1206 // Assume val points to an array of C++ string objects. Copy
1207 // them into the vector<string> field of this object.
1208 // Note: d_length is the number of elements in the Vector
1209 d_str.resize(d_length);
1210 d_capacity = d_length;
1211 for (int i = 0; i < d_length; ++i)
1212 d_str[i] = *(static_cast<string *> (val) + i);
1213
1214 break;
1215
1216 default:
1217 throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1218
1219 }
1220
1221 return width(true);
1222}
1223
1254unsigned int Vector::buf2val(void **val)
1255{
1256 // Jose Garcia
1257 // The same comment in Vector::val2buf applies here!
1258 if (!val)
1259 throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1260
1261 unsigned int wid = static_cast<unsigned int> (width(true /* constrained */));
1262
1263 // This is the width computed using length(). The
1264 // length() property is changed when a projection
1265 // constraint is applied. Thus this is the number of
1266 // bytes in the buffer given the current constraint.
1267
1268 switch (d_proto->type()) {
1269 case dods_byte_c:
1270 case dods_char_c:
1271 case dods_int8_c:
1272 case dods_uint8_c:
1273 case dods_int16_c:
1274 case dods_uint16_c:
1275 case dods_int32_c:
1276 case dods_uint32_c:
1277 case dods_int64_c:
1278 case dods_uint64_c:
1279
1280 case dods_enum_c:
1281
1282 case dods_float32_c:
1283 case dods_float64_c:
1284 if (!d_buf)
1285 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1286 if (!*val)
1287 *val = new char[wid];
1288
1289 memcpy(*val, d_buf, wid);
1290 return wid;
1291 break;
1292
1293 case dods_str_c:
1294 case dods_url_c: {
1295 if (d_str.empty())
1296 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
1297 if (!*val)
1298 *val = new string[d_length];
1299
1300 for (int i = 0; i < d_length; ++i)
1301 *(static_cast<string *> (*val) + i) = d_str[i];
1302
1303 return width();
1304 break;
1305 }
1306
1307 default:
1308 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1309 }
1310
1311 //return wid;
1312}
1313
1334void Vector::set_vec(unsigned int i, BaseType * val)
1335{
1337}
1338
1345void Vector::set_vec_nocopy(unsigned int i, BaseType * val)
1346{
1347 // Jose Garcia
1348 // This is a public method which allows users to set the elements
1349 // of *this* vector. Passing an invalid index, a NULL pointer or
1350 // mismatching the vector type are internal errors.
1351 if (i >= static_cast<unsigned int> (d_length))
1352 throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1353 if (!val)
1354 throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1355 if (val->type() != d_proto->type())
1356 throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
1357
1358 if (i >= d_compound_buf.capacity())
1359 vec_resize(i + 10);
1360
1361 d_compound_buf[i] = val;
1362}
1363
1374{
1375 if (d_buf) {
1376 delete[] d_buf;
1377 d_buf = 0;
1378 }
1379
1380 for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
1381 delete d_compound_buf[i];
1382 d_compound_buf[i] = 0;
1383 }
1384
1385 // Force memory to be reclaimed.
1386 d_compound_buf.resize(0);
1387 d_str.resize(0);
1388
1389 d_capacity = 0;
1390 set_read_p(false);
1391}
1392
1400unsigned int Vector::get_value_capacity() const
1401{
1402 return d_capacity;
1403}
1404
1414void Vector::reserve_value_capacity(unsigned int numElements)
1415{
1416 if (!d_proto) {
1417 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1418 }
1419 switch (d_proto->type()) {
1420 case dods_byte_c:
1421 case dods_char_c:
1422 case dods_int8_c:
1423 case dods_uint8_c:
1424 case dods_int16_c:
1425 case dods_uint16_c:
1426 case dods_int32_c:
1427 case dods_uint32_c:
1428 case dods_int64_c:
1429 case dods_uint64_c:
1430
1431 case dods_enum_c:
1432
1433 case dods_float32_c:
1434 case dods_float64_c:
1435 // Make _buf be the right size and set _capacity
1437 break;
1438
1439 case dods_str_c:
1440 case dods_url_c:
1441 // Make sure the d_str has enough room for all the strings.
1442 // Technically not needed, but it will speed things up for large arrays.
1443 d_str.reserve(numElements);
1444 d_capacity = numElements;
1445 break;
1446
1447 case dods_array_c:
1448 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1449 break;
1450
1451 case dods_opaque_c:
1452 case dods_structure_c:
1453 case dods_sequence_c:
1454 case dods_grid_c:
1455 // not clear anyone will go this path, but best to be complete.
1456 d_compound_buf.reserve(numElements);
1457 d_capacity = numElements;
1458 break;
1459
1460 default:
1461 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1462 break;
1463
1464 } // switch
1465
1466}
1467
1474{
1475 // Use the current length of the vector as the reserve amount.
1477}
1478
1507unsigned int
1508Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
1509{
1510 static const string funcName = "set_value_slice_from_row_major_vector:";
1511
1512 // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1513 Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
1514
1515 bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
1516 if (!typesMatch) {
1517 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
1518 }
1519
1520 // Make sure the data exists
1521 if (!rowMajorData.read_p()) {
1522 throw InternalErr(__FILE__, __LINE__,
1523 funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1524 }
1525
1526 // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1527 if (rowMajorData.length() < 0) {
1528 throw InternalErr(__FILE__, __LINE__,
1529 funcName
1530 + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
1531 }
1532
1533 // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
1534 // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
1535 if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
1536 throw InternalErr(__FILE__, __LINE__,
1537 funcName
1538 + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1539 }
1540
1541 // Make sure there's enough room in this Vector to store all the elements requested. Again,
1542 // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1543 if (d_capacity < (startElement + rowMajorData.length())) {
1544 throw InternalErr(__FILE__, __LINE__,
1545 funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1546 }
1547
1548 // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1549 switch (d_proto->type()) {
1550 case dods_int8_c:
1551 case dods_uint8_c:
1552 case dods_byte_c:
1553 case dods_char_c:
1554 case dods_int16_c:
1555 case dods_uint16_c:
1556 case dods_int32_c:
1557 case dods_uint32_c:
1558 case dods_int64_c:
1559 case dods_uint64_c:
1560
1561 case dods_enum_c:
1562
1563 case dods_float32_c:
1564 case dods_float64_c: {
1565 if (!d_buf) {
1566 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1567 }
1568 if (!rowMajorData.d_buf) {
1569 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1570 }
1571 // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1572 int varWidth = d_proto->width();
1573 char* pFromBuf = rowMajorData.d_buf;
1574 int numBytesToCopy = rowMajorData.width(true);
1575 char* pIntoBuf = d_buf + (startElement * varWidth);
1576 memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
1577 break;
1578 }
1579
1580 case dods_str_c:
1581 case dods_url_c:
1582 // Strings need to be copied directly
1583 for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
1584 d_str[startElement + i] = rowMajorData.d_str[i];
1585 }
1586 break;
1587
1588 case dods_array_c:
1589 case dods_opaque_c:
1590 case dods_structure_c:
1591 case dods_sequence_c:
1592 case dods_grid_c:
1593 // Not sure that this function will be used for these type of nested objects, so I will throw here.
1594 throw InternalErr(__FILE__, __LINE__,
1595 funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
1596 break;
1597
1598 default:
1599 throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1600 break;
1601
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
1714bool Vector::set_value(string *val, int sz)
1715{
1716 if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
1717 d_str.resize(sz);
1718 d_capacity = sz;
1719 for (register int t = 0; t < sz; t++) {
1720 d_str[t] = val[t];
1721 }
1722 set_length(sz);
1723 set_read_p(true);
1724 return true;
1725 }
1726 else {
1727 return false;
1728 }
1729}
1730
1731template<typename T>
1732bool Vector::set_value_worker(vector<T> &v, int sz)
1733{
1734 return set_value(&v[0], sz);
1735}
1736
1737bool Vector::set_value(vector<dods_byte> &val, int sz)
1738{
1739 return set_value_worker(val, sz);
1740}
1741bool Vector::set_value(vector<dods_int8> &val, int sz)
1742{
1743 return set_value_worker(val, sz);
1744}
1745bool Vector::set_value(vector<dods_int16> &val, int sz)
1746{
1747 return set_value_worker(val, sz);
1748}
1749bool Vector::set_value(vector<dods_uint16> &val, int sz)
1750{
1751 return set_value_worker(val, sz);
1752}
1753bool Vector::set_value(vector<dods_int32> &val, int sz)
1754{
1755 return set_value_worker(val, sz);
1756}
1757bool Vector::set_value(vector<dods_uint32> &val, int sz)
1758{
1759 return set_value_worker(val, sz);
1760}
1761bool Vector::set_value(vector<dods_int64> &val, int sz)
1762{
1763 return set_value_worker(val, sz);
1764}
1765bool Vector::set_value(vector<dods_uint64> &val, int sz)
1766{
1767 return set_value_worker(val, sz);
1768}
1769bool Vector::set_value(vector<dods_float32> &val, int sz)
1770{
1771 return set_value_worker(val, sz);
1772}
1773bool Vector::set_value(vector<dods_float64> &val, int sz)
1774{
1775 return set_value_worker(val, sz);
1776}
1777
1778
1780bool Vector::set_value(vector<string> &val, int sz)
1781{
1782 if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
1783 d_str.resize(sz);
1784 d_capacity = sz;
1785 for (register int t = 0; t < sz; t++) {
1786 d_str[t] = val[t];
1787 }
1788 set_length(sz);
1789 set_read_p(true);
1790 return true;
1791 }
1792 else {
1793 return false;
1794 }
1795}
1797
1799
1816template <typename T>
1817void Vector::value_worker(vector<unsigned int> *indices, T *b) const
1818{
1819 // unsigned long currentIndex;
1820#if 0
1821 // Iterator version. Not tested, jhrg 8/14/13
1822 for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
1823 unsigned long currentIndex = *i;
1824 if(currentIndex > (unsigned int)length()){
1825 stringstream s;
1826 s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
1827 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1828 throw Error(s.str());
1829 }
1830 b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
1831 }
1832#endif
1833 for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
1834 unsigned long currentIndex = (*indices)[i];
1835 if (currentIndex > (unsigned int)length()) {
1836 stringstream s;
1837 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1838 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1839 throw Error(s.str());
1840 }
1841 b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
1842 }
1843}
1844void Vector::value(vector<unsigned int> *indices, dods_byte *b) const { value_worker(indices, b); }
1845void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const { value_worker(indices, b); }
1846void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const { value_worker(indices, b); }
1847void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const { value_worker(indices, b); }
1848void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const { value_worker(indices, b); }
1849void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const { value_worker(indices, b); }
1850void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const { value_worker(indices, b); }
1851void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const { value_worker(indices, b); }
1852void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
1853void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
1854
1855#if 0
1856template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
1857template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
1858template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
1859template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
1860template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
1861template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
1862template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
1863template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
1864template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
1865template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
1866#endif
1867
1869void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const
1870{
1871 unsigned long currentIndex;
1872
1873 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
1874 for(unsigned long i=0; i<subsetIndex->size() ;++i){
1875 currentIndex = (*subsetIndex)[i] ;
1876 if(currentIndex > (unsigned int)length()){
1877 stringstream s;
1878 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1879 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1880 throw Error(s.str());
1881 }
1882 b[i] = d_str[currentIndex];
1883 }
1884 }
1885}
1886
1887template <typename T>
1888void Vector::value_worker(T *v) const
1889{
1890 // Only copy if v is not null and the proto's type matches.
1891 // For Enums, use the element type since type == dods_enum_c.
1892 if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1893 memcpy(v, d_buf, length() * sizeof(T));
1894}
1895void Vector::value(dods_byte *b) const { value_worker(b); }
1896void Vector::value(dods_int8 *b) const { value_worker(b); }
1897void Vector::value(dods_int16 *b) const { value_worker(b); }
1898void Vector::value(dods_uint16 *b) const { value_worker(b); }
1899void Vector::value(dods_int32 *b) const { value_worker(b); }
1900void Vector::value(dods_uint32 *b) const { value_worker(b); }
1901void Vector::value(dods_int64 *b) const { value_worker(b); }
1902void Vector::value(dods_uint64 *b) const { value_worker(b); }
1903void Vector::value(dods_float32 *b) const { value_worker(b); }
1904void Vector::value(dods_float64 *b) const { value_worker(b); }
1905
1906#if 0
1907template void Vector::value(dods_byte *v) const;
1908template void Vector::value(dods_int8 *v) const;
1909template void Vector::value(dods_int16 *v) const;
1910template void Vector::value(dods_uint16 *v) const;
1911template void Vector::value(dods_int32 *v) const;
1912template void Vector::value(dods_uint32 *v) const;
1913template void Vector::value(dods_int64 *v) const;
1914template void Vector::value(dods_uint64 *v) const;
1915template void Vector::value(dods_float32 *v) const;
1916template void Vector::value(dods_float64 *v) const;
1917#endif
1918
1919
1921void Vector::value(vector<string> &b) const
1922{
1923 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
1924 b = d_str;
1925}
1926
1930{
1931 void *buffer = new char[width(true)];
1932
1933 memcpy(buffer, d_buf, width(true));
1934
1935 return buffer;
1936}
1938
1955{
1956#if 0
1957 // Why doesn't this work? tried all 3 variants. jhrg 8/14/13
1958 Vector::add_var_nocopy(v->ptr_duplicate(), p);
1959 add_var_nocopy(v->ptr_duplicate(), p);
1960 add_var_nocopy(v->ptr_duplicate());
1961#else
1962 // Delete the current template variable
1963 if (d_proto) {
1964 delete d_proto;
1965 d_proto = 0;
1966 }
1967
1968 // if 'v' is null, just set _var to null and exit.
1969 if (!v) {
1970 d_proto = 0;
1971 }
1972 else {
1973 // Jose Garcia
1974 // By getting a copy of this object to be assigned to _var
1975 // we let the owner of 'v' to deallocate it as necessary.
1976 d_proto = v->ptr_duplicate();
1977
1978 // If 'v' has a name, use it as the name of the array. If v doesn't have
1979 // a name, then make sure to copy the array's name to it
1980 // so that software which uses the template's name will still work.
1981 if (!v->name().empty())
1982 set_name(v->name());
1983 else
1984 d_proto->set_name(name());
1985
1986 d_proto->set_parent(this); // Vector --> child
1987
1988 DBG(cerr << "Vector::add_var: Added variable " << v << " ("
1989 << v->name() << " " << v->type_name() << ")" << endl);
1990 }
1991#endif
1992}
1993
1994void Vector::add_var_nocopy(BaseType * v, Part)
1995{
1996 // Delete the current template variable
1997 if (d_proto) {
1998 delete d_proto;
1999 d_proto = 0;
2000 }
2001
2002 // if 'v' is null, just set _var to null and exit.
2003 if (!v) {
2004 d_proto = 0;
2005 }
2006 else {
2007 d_proto = v;
2008
2009 // If 'v' has a name, use it as the name of the array. If it *is*
2010 // empty, then make sure to copy the array's name to the template
2011 // so that software which uses the template's name will still work.
2012 if (!v->name().empty())
2013 set_name(v->name());
2014 else
2015 d_proto->set_name(name());
2016
2017 d_proto->set_parent(this); // Vector is the parent; proto is the child
2018
2019 DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " ("
2020 << v->name() << " " << v->type_name() << ")" << endl);
2021 }
2022}
2023
2024bool Vector::check_semantics(string & msg, bool)
2025{
2026 return BaseType::check_semantics(msg);
2027}
2028
2037void Vector::dump(ostream &strm) const
2038{
2039 strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
2040 DapIndent::Indent();
2041 BaseType::dump(strm);
2042 strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
2043 if (d_proto) {
2044 strm << DapIndent::LMarg << "base type:" << endl;
2045 DapIndent::Indent();
2046 d_proto->dump(strm);
2047 DapIndent::UnIndent();
2048 }
2049 else {
2050 strm << DapIndent::LMarg << "base type: not set" << endl;
2051 }
2052 strm << DapIndent::LMarg << "vector contents:" << endl;
2053 DapIndent::Indent();
2054 for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
2055 if (d_compound_buf[i])
2056 d_compound_buf[i]->dump(strm);
2057 else
2058 strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
2059 }
2060 DapIndent::UnIndent();
2061 strm << DapIndent::LMarg << "strings:" << endl;
2062 DapIndent::Indent();
2063 for (unsigned i = 0; i < d_str.size(); i++) {
2064 strm << DapIndent::LMarg << d_str[i] << endl;
2065 }
2066 DapIndent::UnIndent();
2067 if (d_buf) {
2068 switch (d_proto != 0 ? d_proto->type() : 0) {
2069 case dods_byte_c:
2070 case dods_char_c:
2071 strm << DapIndent::LMarg << "_buf: ";
2072 strm.write(d_buf, d_length);
2073 strm << endl;
2074 break;
2075
2076 case 0:
2077 default:
2078 strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl;
2079 break;
2080 }
2081 }
2082 else {
2083 strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
2084 }
2085
2086 DapIndent::UnIndent();
2087}
2088
2089} // namespace libdap
2090
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:324
virtual bool read()
Read data into a local buffer.
Definition: BaseType.cc:820
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:265
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:425
virtual unsigned int width(bool constrained=false) const
How many bytes does this use Return the number of bytes of storage this variable uses....
Definition: BaseType.cc:1222
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:461
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:303
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:679
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:654
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: BaseType.cc:388
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition: BaseType.cc:289
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:357
virtual void set_send_p(bool state)
Definition: BaseType.cc:513
virtual BaseType * ptr_duplicate()=0
virtual unsigned int val2buf(void *val, bool reuse=false)=0
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:236
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: BaseType.cc:1130
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition: BaseType.cc:125
virtual Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:310
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:91
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:1954
virtual void set_length(int l)
Definition: Vector.cc:564
virtual unsigned int get_value_capacity() const
Definition: Vector.cc:1400
void set_vec_nocopy(unsigned int i, BaseType *val)
Sets element i to value val.
Definition: Vector.cc:1345
void m_set_cardinal_values_internal(const CardType *fromArray, int numElts)
Definition: Vector.cc:220
virtual int length() const
Definition: Vector.cc:557
virtual unsigned int set_value_slice_from_row_major_vector(const Vector &rowMajorData, unsigned int startElement)
Definition: Vector.cc:1508
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:392
virtual void set_send_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:355
void set_vec(unsigned int i, BaseType *val)
Sets element i to value val.
Definition: Vector.cc:1334
virtual unsigned int width(bool constrained=false) const
Returns the width of the data, in bytes.
Definition: Vector.cc:545
virtual unsigned int val2buf(void *val, bool reuse=false)
Reads data into the Vector buffer.
Definition: Vector.cc:1158
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Serialize a Vector.
Definition: Vector.cc:669
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:870
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Vector.cc:2037
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition: Vector.cc:434
virtual void set_name(const std::string &name)
Sets the name of the class instance.
Definition: Vector.cc:324
virtual int element_count(bool leaves)
Count the members of constructor types.
Definition: Vector.cc:334
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: Vector.cc:769
virtual void intern_data()
Read data into this variable.
Definition: Vector.cc:913
bool m_is_cardinal_type() const
Definition: Vector.cc:124
virtual void clear_local_data()
Definition: Vector.cc:1373
virtual void * value()
Definition: Vector.cc:1929
void vec_resize(int l)
Definition: Vector.cc:577
void m_delete_cardinal_data_buffer()
Definition: Vector.cc:209
virtual void reserve_value_capacity()
Definition: Vector.cc:1473
unsigned int m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
Definition: Vector.cc:181
virtual unsigned int buf2val(void **val)
Definition: Vector.cc:1254
Vector(const string &n, BaseType *v, const Type &t, bool is_dap4=false)
The Vector constructor.
Definition: Vector.cc:249
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: Vector.cc:2024
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