libdap
Updated for version 3.17.0
|
00001 // -*- mode: c++; c-basic-offset:4 -*- 00002 00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00004 // Access Protocol. 00005 00006 // Copyright (c) 2002,2003 OPeNDAP, Inc. 00007 // Author: James Gallagher <jgallagher@opendap.org> 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 // 00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00024 00025 // (c) COPYRIGHT URI/MIT 1995-1999 00026 // Please read the full copyright statement in the file COPYRIGHT_URI. 00027 // 00028 // Authors: 00029 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00030 00031 // Implementation for class Vector. This class is the basis for all the 00032 // vector-type classes in libdap's <Array, List>. 00033 // 00034 // 11/21/95 jhrg 00035 00036 #include "config.h" 00037 00038 #include <cstring> 00039 #include <cassert> 00040 00041 //#define DODS_DEBUG 1 00042 00043 #include <sstream> 00044 #include <vector> 00045 #include <algorithm> 00046 #include <typeinfo> 00047 00048 #include <stdint.h> 00049 00050 #include "crc.h" 00051 00052 #include "Vector.h" 00053 #include "Marshaller.h" 00054 #include "UnMarshaller.h" 00055 00056 #include "D4StreamMarshaller.h" 00057 #include "D4StreamUnMarshaller.h" 00058 00059 #include "D4Enum.h" 00060 00061 #include "Type.h" 00062 #include "dods-datatypes.h" 00063 #include "escaping.h" 00064 #include "util.h" 00065 #include "debug.h" 00066 #include "InternalErr.h" 00067 00068 #undef CLEAR_LOCAL_DATA 00069 00070 using std::cerr; 00071 using std::endl; 00072 00073 namespace libdap { 00074 00075 void Vector::m_duplicate(const Vector & v) 00076 { 00077 d_length = v.d_length; 00078 00079 // _var holds the type of the elements. That is, it holds a BaseType 00080 // which acts as a template for the type of each element. 00081 if (v.d_proto) { 00082 d_proto = v.d_proto->ptr_duplicate(); // use ptr_duplicate() 00083 d_proto->set_parent(this); // ptr_duplicate does not set d_parent. 00084 } 00085 else { 00086 d_proto = 0; 00087 } 00088 00089 // d_compound_buf and d_buf (further down) hold the values of the Vector. The field 00090 // d_compound_buf is used when the Vector holds non-numeric data (including strings 00091 // although it used to be that was not the case jhrg 2/10/05) while d_buf 00092 // holds numeric values. 00093 if (v.d_compound_buf.empty()) { 00094 d_compound_buf = v.d_compound_buf; 00095 } 00096 else { 00097 // Failure to set the size will make the [] operator barf on the LHS 00098 // of the assignment inside the loop. 00099 d_compound_buf.resize(d_length); 00100 for (int i = 0; i < d_length; ++i) { 00101 // There's no need to call set_parent() for each element; we 00102 // maintain the back pointer using the d_proto member. These 00103 // instances are used to hold _values_ only while the d_proto 00104 // field holds the type information for the elements. 00105 d_compound_buf[i] = v.d_compound_buf[i]->ptr_duplicate(); 00106 } 00107 } 00108 00109 // copy the strings. This copies the values. 00110 d_str = v.d_str; 00111 00112 // copy numeric values if there are any. 00113 d_buf = 0; // init to null 00114 if (v.d_buf) // only copy if data present 00115 val2buf(v.d_buf); // store v's value in this's _BUF. 00116 00117 d_capacity = v.d_capacity; 00118 } 00119 00124 bool Vector::m_is_cardinal_type() const 00125 { 00126 // Not cardinal if no d_proto at all! 00127 if (!d_proto) { 00128 return false; 00129 } 00130 00131 switch (d_proto->type()) { 00132 case dods_byte_c: 00133 case dods_char_c: 00134 case dods_int16_c: 00135 case dods_uint16_c: 00136 case dods_int32_c: 00137 case dods_uint32_c: 00138 case dods_float32_c: 00139 case dods_float64_c: 00140 // New cardinal types for DAP4 00141 case dods_int8_c: 00142 case dods_uint8_c: 00143 case dods_int64_c: 00144 case dods_uint64_c: 00145 00146 case dods_enum_c: 00147 return true; 00148 break; 00149 00150 // These must be handled differently. 00151 case dods_str_c: 00152 case dods_url_c: 00153 case dods_opaque_c: 00154 00155 case dods_array_c: 00156 00157 case dods_structure_c: 00158 case dods_sequence_c: 00159 case dods_grid_c: 00160 return false; 00161 break; 00162 00163 default: 00164 assert("Vector::var: Unrecognized type"); 00165 return false; 00166 } 00167 } 00168 00181 unsigned int Vector::m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType) 00182 { 00183 // Make sure we HAVE a _var, or we cannot continue. 00184 if (!d_proto) { 00185 throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!"); 00186 } 00187 00188 // Make sure we only do this for the correct data types. 00189 if (!m_is_cardinal_type()) { 00190 throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types)."); 00191 } 00192 00193 m_delete_cardinal_data_buffer(); 00194 00195 // Handle this special case where this is an array that holds no values 00196 if (numEltsOfType == 0) 00197 return 0; 00198 00199 // Actually new up the array with enough bytes to hold numEltsOfType of the actual type. 00200 unsigned int bytesPerElt = d_proto->width(); 00201 unsigned int bytesNeeded = bytesPerElt * numEltsOfType; 00202 d_buf = new char[bytesNeeded]; 00203 00204 d_capacity = numEltsOfType; 00205 return bytesNeeded; 00206 } 00207 00209 void Vector::m_delete_cardinal_data_buffer() 00210 { 00211 delete[] d_buf; 00212 d_buf = 0; 00213 d_capacity = 0; 00214 } 00215 00219 template<class CardType> 00220 void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int numElts) 00221 { 00222 if (numElts < 0) { 00223 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!"); 00224 } 00225 if (!fromArray) { 00226 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!"); 00227 } 00228 set_length(numElts); 00229 m_create_cardinal_data_buffer_for_type(numElts); 00230 memcpy(d_buf, fromArray, numElts * sizeof(CardType)); 00231 set_read_p(true); 00232 } 00233 00249 Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) : 00250 BaseType(n, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0) 00251 { 00252 if (v) 00253 add_var(v); 00254 00255 DBG2(cerr << "Entering Vector ctor for object: " << this << endl); 00256 if (d_proto) 00257 d_proto->set_parent(this); 00258 } 00259 00278 Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) : 00279 BaseType(n, d, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0) 00280 { 00281 if (v) 00282 add_var(v); 00283 00284 DBG2(cerr << "Entering Vector ctor for object: " << this << endl); 00285 if (d_proto) 00286 d_proto->set_parent(this); 00287 } 00288 00290 Vector::Vector(const Vector & rhs) : 00291 BaseType(rhs) 00292 { 00293 DBG2(cerr << "Entering Vector const ctor for object: " << this << 00294 endl); DBG2(cerr << "RHS: " << &rhs << endl); 00295 00296 m_duplicate(rhs); 00297 } 00298 00299 Vector::~Vector() 00300 { 00301 DBG2(cerr << "Entering ~Vector (" << this << ")" << endl); 00302 00303 delete d_proto; 00304 d_proto = 0; 00305 00306 // Clears all buffers 00307 clear_local_data(); 00308 00309 DBG2(cerr << "Exiting ~Vector" << endl); 00310 } 00311 00312 Vector & Vector::operator=(const Vector & rhs) 00313 { 00314 if (this == &rhs) 00315 return *this; 00316 00317 dynamic_cast<BaseType &> (*this) = rhs; 00318 00319 m_duplicate(rhs); 00320 00321 return *this; 00322 } 00323 00324 void Vector::set_name(const std::string& name) 00325 { 00326 BaseType::set_name(name); 00327 // We need to set the prototype name as well since 00328 // this is what gets output in the dds! Otherwise, there's a mismatch. 00329 if (d_proto) { 00330 d_proto->set_name(name); 00331 } 00332 } 00333 00334 int Vector::element_count(bool leaves) 00335 { 00336 if (!leaves) 00337 return 1; 00338 else 00339 return d_proto->element_count(leaves); 00340 // var() only works for simple types! 00341 // jhrg 8/19/13 return var(0)->element_count(leaves); 00342 } 00343 00344 // These mfuncs set the _send_p and _read_p fields of BaseType. They differ 00345 // from BaseType's version in that they set both the Vector object's copy of 00346 // _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR 00347 // is a scalar, but does matter when it is an aggregate. 00348 00355 void Vector::set_send_p(bool state) 00356 { 00357 d_proto->set_send_p(state); 00358 BaseType::set_send_p(state); 00359 } 00360 00367 void Vector::set_read_p(bool state) 00368 { 00369 if (d_proto) { 00370 d_proto->set_read_p(state); 00371 } 00372 BaseType::set_read_p(state); 00373 } 00374 00392 BaseType *Vector::var(const string &n, bool exact, btp_stack *s) 00393 { 00394 string name = www2id(n); 00395 DBG2(cerr << "Vector::var: Looking for " << name << endl); 00396 00397 // If this is a Vector of constructor types, look for 'name' recursively. 00398 // Make sure to check for the case where name is the default (the empty 00399 // string). 9/1/98 jhrg 00400 if (d_proto->is_constructor_type()) { 00401 if (name == "" || d_proto->name() == name) { 00402 if (s) 00403 s->push(this); 00404 return d_proto; 00405 } 00406 else { 00407 BaseType * result = d_proto->var(name, exact, s); 00408 if (result && s) 00409 s->push(this); 00410 return result; 00411 } 00412 } 00413 else { 00414 return d_proto; 00415 } 00416 } 00417 00428 BaseType *Vector::var(const string & n, btp_stack & s) 00429 { 00430 string name = www2id(n); 00431 00432 if (d_proto->is_constructor_type()) 00433 return d_proto->var(name, s); 00434 else { 00435 s.push((BaseType *) this); 00436 return d_proto; 00437 } 00438 } 00439 00451 BaseType *Vector::var(unsigned int i) 00452 { 00453 00454 switch (d_proto->type()) { 00455 case dods_byte_c: 00456 case dods_char_c: 00457 case dods_int8_c: 00458 case dods_uint8_c: 00459 case dods_int16_c: 00460 case dods_uint16_c: 00461 case dods_int32_c: 00462 case dods_uint32_c: 00463 case dods_int64_c: 00464 case dods_uint64_c: 00465 00466 case dods_enum_c: 00467 00468 case dods_float32_c: 00469 case dods_float64_c: 00470 // Transfer the ith value to the BaseType *d_proto 00471 d_proto->val2buf(d_buf + (i * d_proto->width())); 00472 return d_proto; 00473 break; 00474 00475 case dods_str_c: 00476 case dods_url_c: 00477 d_proto->val2buf(&d_str[i]); 00478 return d_proto; 00479 break; 00480 00481 case dods_opaque_c: 00482 case dods_array_c: 00483 case dods_structure_c: 00484 case dods_sequence_c: 00485 case dods_grid_c: 00486 return d_compound_buf[i]; 00487 break; 00488 00489 default: 00490 throw Error ("Vector::var: Unrecognized type"); 00491 break; 00492 } 00493 00494 return 0; 00495 } 00496 00503 unsigned int Vector::width(bool constrained) const 00504 { 00505 // Jose Garcia 00506 assert(d_proto); 00507 00508 return length() * d_proto->width(constrained); 00509 } 00510 00515 int Vector::length() const 00516 { 00517 return d_length; 00518 } 00519 00522 void Vector::set_length(int l) 00523 { 00524 d_length = l; 00525 } 00526 00535 void Vector::vec_resize(int l) 00536 { 00537 // I added this check, which alters the behavior of the method. jhrg 8/14/13 00538 if (m_is_cardinal_type()) 00539 throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only"); 00540 00541 d_compound_buf.resize((l > 0) ? l : 0, 0); // Fill with NULLs 00542 d_capacity = l; // capacity in terms of number of elements. 00543 } 00544 00561 void Vector::intern_data(ConstraintEvaluator &eval, DDS &dds) 00562 { 00563 DBG(cerr << "Vector::intern_data: " << name() << endl); 00564 if (!read_p()) 00565 read(); // read() throws Error and InternalErr 00566 00567 // length() is not capacity; it must be set explicitly in read(). 00568 int num = length(); 00569 00570 switch (d_proto->type()) { 00571 case dods_byte_c: 00572 case dods_int16_c: 00573 case dods_uint16_c: 00574 case dods_int32_c: 00575 case dods_uint32_c: 00576 case dods_float32_c: 00577 case dods_float64_c: 00578 // For these cases, read() puts the data into d_buf, 00579 // which is what we need. 00580 break; 00581 00582 case dods_str_c: 00583 case dods_url_c: 00584 // For these cases, read() will put the data into d_str[], 00585 // which is also what we need. 00586 break; 00587 00588 case dods_array_c: 00589 // This is an error since there can never be an Array of Array. 00590 throw InternalErr(__FILE__, __LINE__, "Array of Array not supported."); 00591 break; 00592 00593 case dods_structure_c: 00594 case dods_sequence_c: 00595 case dods_grid_c: 00596 DBG(cerr << "Vector::intern_data: found ctor" << endl); 00597 // For these cases, we need to call read() for each of the 'num' 00598 // elements in the 'd_compound_buf[]' array of BaseType object pointers. 00599 // 00600 // I changed the test here from '... = 0' to '... < num' to accommodate 00601 // the case where the array is zero-length. 00602 if (d_compound_buf.capacity() < (unsigned)num) 00603 throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements."); 00604 00605 for (int i = 0; i < num; ++i) 00606 d_compound_buf[i]->intern_data(eval, dds); 00607 00608 break; 00609 00610 default: 00611 throw InternalErr(__FILE__, __LINE__, "Unknown datatype."); 00612 break; 00613 } 00614 } 00615 00627 bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval) 00628 { 00629 #if 0 00630 dds.timeout_on(); 00631 #endif 00632 if (!read_p()) 00633 read(); // read() throws Error and InternalErr 00634 00635 if (ce_eval && !eval.eval_selection(dds, dataset())) 00636 return true; 00637 #if 0 00638 dds.timeout_off(); 00639 #endif 00640 // length() is not capacity; it must be set explicitly in read(). 00641 int num = length(); 00642 00643 bool status = false; 00644 00645 switch (d_proto->type()) { 00646 case dods_byte_c: 00647 m.put_vector(d_buf, num, *this); 00648 status = true; 00649 break; 00650 00651 case dods_int16_c: 00652 case dods_uint16_c: 00653 case dods_int32_c: 00654 case dods_uint32_c: 00655 case dods_float32_c: 00656 case dods_float64_c: 00657 m.put_vector(d_buf, num, d_proto->width(), *this); 00658 status = true; 00659 00660 break; 00661 00662 case dods_str_c: 00663 case dods_url_c: 00664 if (d_str.capacity() == 0) 00665 throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0"); 00666 00667 m.put_int(num); 00668 00669 for (int i = 0; i < num; ++i) 00670 m.put_str(d_str[i]); 00671 00672 status = true; 00673 break; 00674 00675 case dods_array_c: 00676 case dods_structure_c: 00677 case dods_sequence_c: 00678 case dods_grid_c: 00679 //Jose Garcia 00680 // Not setting the capacity of d_compound_buf is an internal error. 00681 if (d_compound_buf.capacity() == 0) 00682 throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0."); 00683 00684 m.put_int(num); 00685 status = true; 00686 for (int i = 0; i < num && status; ++i) 00687 status = status && d_compound_buf[i]->serialize(eval, dds, m, false); 00688 00689 break; 00690 00691 default: 00692 throw InternalErr(__FILE__, __LINE__, "Unknown datatype."); 00693 break; 00694 } 00695 00696 #ifdef CLEAR_LOCAL_DATA 00697 clear_local_data(); 00698 #endif 00699 00700 return status; 00701 } 00702 00703 // Read an object from the network and internalize it. For a Vector this is 00704 // handled differently for a `cardinal' type. Vectors of Cardinals are 00705 // stored using the `C' representations because these objects often are used 00706 // to build huge arrays (e.g., an array of 1024 by 1024 bytes). However, 00707 // arrays of non-cardinal types are stored as Vectors of the C++ objects or 00708 // DAP2 objects (Str and Url are vectors of the string class, Structure, ..., 00709 // Grid are vectors of the libdap Structure, ... classes). 00710 // 00711 // The boolean parameter REUSE determines whether internal storage is reused 00712 // or not. If true, the _buf member is assumed to be large enough to hold the 00713 // incoming cardinal data and is *not* reallocated. If false, new storage is 00714 // allocated. If the internal buffer has not yet been allocated, then this 00715 // parameter has no effect (i.e., storage is allocated). This parameter 00716 // effects storage for cardinal data only. 00717 // 00718 // Returns: True is successful, false otherwise. 00719 00720 bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse) 00721 { 00722 unsigned int num; 00723 unsigned i = 0; 00724 00725 switch (d_proto->type()) { 00726 case dods_byte_c: 00727 case dods_int16_c: 00728 case dods_uint16_c: 00729 case dods_int32_c: 00730 case dods_uint32_c: 00731 case dods_float32_c: 00732 case dods_float64_c: 00733 um.get_int((int &) num); 00734 00735 DBG(cerr << "Vector::deserialize: num = " << num << endl); 00736 DBG(cerr << "Vector::deserialize: length = " << length() << endl); 00737 00738 if (length() == -1) 00739 set_length(num); 00740 00741 if (num != (unsigned int) length()) 00742 throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes for the variable '" + name() + "'."); 00743 00744 if (!d_buf || !reuse) { 00745 // Make d_buf be large enough for length() elements of _var->type() 00746 // m_create...() deletes the old buffer. 00747 m_create_cardinal_data_buffer_for_type(length()); 00748 DBG(cerr << "Vector::deserialize: allocating " 00749 << width() << " bytes for an array of " 00750 << length() << " " << d_proto->type_name() << endl); 00751 } 00752 00753 // Added to accommodate zero-length arrays. 00754 // Note that the rest of the cases will just send the size without data 00755 // but that these calls trigger error testing in the UnMarshaller code. 00756 // jhrg 1/28/16 00757 if (num == 0) 00758 return true; 00759 00760 if (d_proto->type() == dods_byte_c) 00761 um.get_vector((char **) &d_buf, num, *this); 00762 else 00763 um.get_vector((char **) &d_buf, num, d_proto->width(), *this); 00764 00765 DBG(cerr << "Vector::deserialize: read " << num << " elements\n"); 00766 00767 break; 00768 00769 case dods_str_c: 00770 case dods_url_c: 00771 um.get_int((int &) num); 00772 00773 if (length() == -1) 00774 set_length(num); 00775 00776 if (num != (unsigned int) length()) 00777 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes."); 00778 00779 d_str.resize((num > 0) ? num : 0); // Fill with NULLs 00780 d_capacity = num; // capacity is number of strings we can fit. 00781 00782 for (i = 0; i < num; ++i) { 00783 string str; 00784 um.get_str(str); 00785 d_str[i] = str; 00786 00787 } 00788 00789 break; 00790 00791 case dods_array_c: 00792 // TODO 00793 case dods_structure_c: 00794 case dods_sequence_c: 00795 case dods_grid_c: 00796 um.get_int((int &) num); 00797 00798 if (length() == -1) 00799 set_length(num); 00800 00801 if (num != (unsigned int) length()) 00802 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes."); 00803 00804 vec_resize(num); 00805 00806 for (i = 0; i < num; ++i) { 00807 d_compound_buf[i] = d_proto->ptr_duplicate(); 00808 d_compound_buf[i]->deserialize(um, dds); 00809 } 00810 00811 break; 00812 00813 default: 00814 throw InternalErr(__FILE__, __LINE__, "Unknown type!"); 00815 break; 00816 } 00817 00818 return false; 00819 } 00820 00821 void Vector::compute_checksum(Crc32 &checksum) 00822 { 00823 switch (d_proto->type()) { 00824 case dods_byte_c: 00825 case dods_char_c: 00826 case dods_int8_c: 00827 case dods_uint8_c: 00828 00829 case dods_int16_c: 00830 case dods_uint16_c: 00831 00832 case dods_int32_c: 00833 case dods_uint32_c: 00834 case dods_float32_c: 00835 00836 case dods_int64_c: 00837 case dods_uint64_c: 00838 case dods_float64_c: 00839 00840 case dods_enum_c: 00841 checksum.AddData(reinterpret_cast<uint8_t*>(d_buf), length() * d_proto->width()); 00842 break; 00843 00844 case dods_str_c: 00845 case dods_url_c: 00846 for (int64_t i = 0, e = length(); i < e; ++i) 00847 checksum.AddData(reinterpret_cast<const uint8_t*>(d_str[i].data()), d_str[i].length()); 00848 break; 00849 00850 case dods_opaque_c: 00851 case dods_structure_c: 00852 case dods_sequence_c: 00853 d_proto->compute_checksum(checksum); 00854 break; 00855 00856 case dods_array_c: // No array of array 00857 case dods_grid_c: // No grids in DAP4 00858 default: 00859 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ")."); 00860 break; 00861 } 00862 } 00863 00864 void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/) 00865 { 00866 if (!read_p()) 00867 read(); // read() throws Error and InternalErr 00868 00869 switch (d_proto->type()) { 00870 case dods_byte_c: 00871 case dods_char_c: 00872 case dods_int8_c: 00873 case dods_uint8_c: 00874 case dods_int16_c: 00875 case dods_uint16_c: 00876 case dods_int32_c: 00877 case dods_uint32_c: 00878 case dods_int64_c: 00879 case dods_uint64_c: 00880 00881 case dods_enum_c: 00882 00883 case dods_float32_c: 00884 case dods_float64_c: 00885 00886 case dods_str_c: 00887 case dods_url_c: 00888 #if 0 00889 compute_checksum(checksum); 00890 #endif 00891 break; 00892 00893 case dods_opaque_c: 00894 case dods_structure_c: 00895 case dods_sequence_c: 00896 // Modified the assert here from '... != 0' to '... >= length()) 00897 // to accommodate the case of a zero-length array. jhrg 1/28/16 00898 assert(d_compound_buf.capacity() >= (unsigned)length()); 00899 00900 for (int i = 0, e = length(); i < e; ++i) 00901 d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/); 00902 break; 00903 00904 case dods_array_c: // No Array of Array in DAP4 either... 00905 case dods_grid_c: 00906 default: 00907 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ")."); 00908 break; 00909 } 00910 } 00911 00912 void 00913 Vector::serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter /*= false*/) 00914 { 00915 if (!read_p()) 00916 read(); // read() throws Error and InternalErr 00917 #if 0 00918 if (filter && !eval.eval_selection(dmr, dataset())) 00919 return true; 00920 #endif 00921 int64_t num = length(); // The constrained length in elements 00922 00923 DBG(cerr << __PRETTY_FUNCTION__ << ", num: " << num << endl); 00924 00925 // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16 00926 if (num == 0) 00927 return; 00928 00929 switch (d_proto->type()) { 00930 case dods_byte_c: 00931 case dods_char_c: 00932 case dods_int8_c: 00933 case dods_uint8_c: 00934 m.put_vector(d_buf, num); 00935 break; 00936 00937 case dods_int16_c: 00938 case dods_uint16_c: 00939 case dods_int32_c: 00940 case dods_uint32_c: 00941 case dods_int64_c: 00942 case dods_uint64_c: 00943 m.put_vector(d_buf, num, d_proto->width()); 00944 break; 00945 00946 case dods_enum_c: 00947 if (d_proto->width() == 1) 00948 m.put_vector(d_buf, num); 00949 else 00950 m.put_vector(d_buf, num, d_proto->width()); 00951 break; 00952 00953 case dods_float32_c: 00954 m.put_vector_float32(d_buf, num); 00955 break; 00956 00957 case dods_float64_c: 00958 m.put_vector_float64(d_buf, num); 00959 break; 00960 00961 case dods_str_c: 00962 case dods_url_c: 00963 assert((int64_t)d_str.capacity() >= num); 00964 00965 for (int64_t i = 0; i < num; ++i) 00966 m.put_str(d_str[i]); 00967 00968 break; 00969 00970 case dods_array_c: 00971 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed."); 00972 00973 case dods_opaque_c: 00974 case dods_structure_c: 00975 case dods_sequence_c: 00976 assert(d_compound_buf.capacity() >= 0); 00977 00978 for (int64_t i = 0; i < num; ++i) 00979 d_compound_buf[i]->serialize(m, dmr, /*eval,*/ filter); 00980 00981 break; 00982 00983 case dods_grid_c: 00984 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4."); 00985 00986 default: 00987 throw InternalErr(__FILE__, __LINE__, "Unknown datatype."); 00988 break; 00989 } 00990 00991 #ifdef CLEAR_LOCAL_DATA 00992 clear_local_data(); 00993 #endif 00994 } 00995 00996 void 00997 Vector::deserialize(D4StreamUnMarshaller &um, DMR &dmr) 00998 { 00999 if (m_is_cardinal_type()) { 01000 if (d_buf) 01001 m_delete_cardinal_data_buffer(); 01002 if (!d_buf) 01003 m_create_cardinal_data_buffer_for_type(length()); 01004 } 01005 01006 DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl); 01007 01008 // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16 01009 if (length() == 0) 01010 return; 01011 01012 switch (d_proto->type()) { 01013 case dods_byte_c: 01014 case dods_char_c: 01015 case dods_int8_c: 01016 case dods_uint8_c: 01017 um.get_vector((char *)d_buf, length()); 01018 break; 01019 01020 case dods_int16_c: 01021 case dods_uint16_c: 01022 case dods_int32_c: 01023 case dods_uint32_c: 01024 case dods_int64_c: 01025 case dods_uint64_c: 01026 um.get_vector((char *)d_buf, length(), d_proto->width()); 01027 break; 01028 01029 case dods_enum_c: 01030 if (d_proto->width() == 1) 01031 um.get_vector((char *)d_buf, length()); 01032 else 01033 um.get_vector((char *)d_buf, length(), d_proto->width()); 01034 break; 01035 01036 case dods_float32_c: 01037 um.get_vector_float32((char *)d_buf, length()); 01038 break; 01039 01040 case dods_float64_c: 01041 um.get_vector_float64((char *)d_buf, length()); 01042 break; 01043 01044 case dods_str_c: 01045 case dods_url_c: { 01046 int64_t len = length(); 01047 d_str.resize((len > 0) ? len : 0); // Fill with NULLs 01048 d_capacity = len; // capacity is number of strings we can fit. 01049 01050 for (int64_t i = 0; i < len; ++i) { 01051 um.get_str(d_str[i]); 01052 } 01053 01054 break; 01055 } 01056 01057 case dods_array_c: 01058 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed."); 01059 01060 case dods_opaque_c: 01061 case dods_structure_c: 01062 case dods_sequence_c: { 01063 vec_resize(length()); 01064 01065 for (int64_t i = 0, end = length(); i < end; ++i) { 01066 d_compound_buf[i] = d_proto->ptr_duplicate(); 01067 d_compound_buf[i]->deserialize(um, dmr); 01068 } 01069 01070 break; 01071 } 01072 01073 case dods_grid_c: 01074 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4."); 01075 01076 default: 01077 throw InternalErr(__FILE__, __LINE__, "Unknown type."); 01078 break; 01079 } 01080 } 01081 01109 unsigned int Vector::val2buf(void *val, bool reuse) 01110 { 01111 // Jose Garcia 01112 01113 // Added for zero-length arrays - support in the handlers. jhrg 1/29/16 01114 if (!val && length() == 0) 01115 return 0; 01116 01117 // I *think* this method has been mainly designed to be use by read which 01118 // is implemented in the surrogate library. Passing NULL as a pointer to 01119 // this method will be an error of the creator of the surrogate library. 01120 // Even though I recognize the fact that some methods inside libdap++ can 01121 // call val2buf, I think by now no coding bugs such as misusing val2buf 01122 // will be in libdap++, so it will be an internal error from the 01123 // surrogate library. 01124 if (!val) 01125 throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data."); 01126 01127 switch (d_proto->type()) { 01128 case dods_byte_c: 01129 case dods_char_c: 01130 case dods_int8_c: 01131 case dods_uint8_c: 01132 case dods_int16_c: 01133 case dods_uint16_c: 01134 case dods_int32_c: 01135 case dods_uint32_c: 01136 case dods_int64_c: 01137 case dods_uint64_c: 01138 01139 case dods_enum_c: 01140 01141 case dods_float32_c: 01142 case dods_float64_c: 01143 #if 0 01144 if (d_buf && !reuse) 01145 m_delete_cardinal_data_buffer(); 01146 #endif 01147 // First time or no reuse (free'd above) 01148 if (!d_buf || !reuse) 01149 m_create_cardinal_data_buffer_for_type(length()); 01150 01151 // width(true) returns the size in bytes given the constraint 01152 memcpy(d_buf, val, width(true)); 01153 break; 01154 01155 case dods_str_c: 01156 case dods_url_c: 01157 // Assume val points to an array of C++ string objects. Copy 01158 // them into the vector<string> field of this object. 01159 // Note: d_length is the number of elements in the Vector 01160 d_str.resize(d_length); 01161 d_capacity = d_length; 01162 for (int i = 0; i < d_length; ++i) 01163 d_str[i] = *(static_cast<string *> (val) + i); 01164 01165 break; 01166 01167 default: 01168 throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type"); 01169 01170 } 01171 01172 return width(true); 01173 } 01174 01205 unsigned int Vector::buf2val(void **val) 01206 { 01207 // Jose Garcia 01208 // The same comment in Vector::val2buf applies here! 01209 if (!val) 01210 throw InternalErr(__FILE__, __LINE__, "NULL pointer."); 01211 01212 unsigned int wid = static_cast<unsigned int> (width(true /* constrained */)); 01213 01214 // This is the width computed using length(). The 01215 // length() property is changed when a projection 01216 // constraint is applied. Thus this is the number of 01217 // bytes in the buffer given the current constraint. 01218 01219 switch (d_proto->type()) { 01220 case dods_byte_c: 01221 case dods_char_c: 01222 case dods_int8_c: 01223 case dods_uint8_c: 01224 case dods_int16_c: 01225 case dods_uint16_c: 01226 case dods_int32_c: 01227 case dods_uint32_c: 01228 case dods_int64_c: 01229 case dods_uint64_c: 01230 01231 case dods_enum_c: 01232 01233 case dods_float32_c: 01234 case dods_float64_c: 01235 if (!d_buf) 01236 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!"); 01237 if (!*val) 01238 *val = new char[wid]; 01239 01240 memcpy(*val, d_buf, wid); 01241 return wid; 01242 break; 01243 01244 case dods_str_c: 01245 case dods_url_c: { 01246 if (d_str.empty()) 01247 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!"); 01248 if (!*val) 01249 *val = new string[d_length]; 01250 01251 for (int i = 0; i < d_length; ++i) 01252 *(static_cast<string *> (*val) + i) = d_str[i]; 01253 01254 return width(); 01255 break; 01256 } 01257 01258 default: 01259 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type"); 01260 } 01261 01262 //return wid; 01263 } 01264 01285 void Vector::set_vec(unsigned int i, BaseType * val) 01286 { 01287 Vector::set_vec_nocopy(i, val->ptr_duplicate()); 01288 } 01289 01296 void Vector::set_vec_nocopy(unsigned int i, BaseType * val) 01297 { 01298 // Jose Garcia 01299 // This is a public method which allows users to set the elements 01300 // of *this* vector. Passing an invalid index, a NULL pointer or 01301 // mismatching the vector type are internal errors. 01302 if (i >= static_cast<unsigned int> (d_length)) 01303 throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large."); 01304 if (!val) 01305 throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object."); 01306 if (val->type() != d_proto->type()) 01307 throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type."); 01308 01309 if (i >= d_compound_buf.capacity()) 01310 vec_resize(i + 10); 01311 01312 d_compound_buf[i] = val; 01313 } 01314 01324 void Vector::clear_local_data() 01325 { 01326 if (d_buf) { 01327 delete[] d_buf; 01328 d_buf = 0; 01329 } 01330 01331 for (unsigned int i = 0; i < d_compound_buf.size(); ++i) { 01332 delete d_compound_buf[i]; 01333 d_compound_buf[i] = 0; 01334 } 01335 01336 // Force memory to be reclaimed. 01337 d_compound_buf.resize(0); 01338 d_str.resize(0); 01339 01340 d_capacity = 0; 01341 set_read_p(false); 01342 } 01343 01351 unsigned int Vector::get_value_capacity() const 01352 { 01353 return d_capacity; 01354 } 01355 01365 void Vector::reserve_value_capacity(unsigned int numElements) 01366 { 01367 if (!d_proto) { 01368 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!"); 01369 } 01370 switch (d_proto->type()) { 01371 case dods_byte_c: 01372 case dods_char_c: 01373 case dods_int8_c: 01374 case dods_uint8_c: 01375 case dods_int16_c: 01376 case dods_uint16_c: 01377 case dods_int32_c: 01378 case dods_uint32_c: 01379 case dods_int64_c: 01380 case dods_uint64_c: 01381 01382 case dods_enum_c: 01383 01384 case dods_float32_c: 01385 case dods_float64_c: 01386 // Make _buf be the right size and set _capacity 01387 m_create_cardinal_data_buffer_for_type(numElements); 01388 break; 01389 01390 case dods_str_c: 01391 case dods_url_c: 01392 // Make sure the d_str has enough room for all the strings. 01393 // Technically not needed, but it will speed things up for large arrays. 01394 d_str.reserve(numElements); 01395 d_capacity = numElements; 01396 break; 01397 01398 case dods_array_c: 01399 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!"); 01400 break; 01401 01402 case dods_opaque_c: 01403 case dods_structure_c: 01404 case dods_sequence_c: 01405 case dods_grid_c: 01406 // not clear anyone will go this path, but best to be complete. 01407 d_compound_buf.reserve(numElements); 01408 d_capacity = numElements; 01409 break; 01410 01411 default: 01412 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!"); 01413 break; 01414 01415 } // switch 01416 01417 } 01418 01424 void Vector::reserve_value_capacity() 01425 { 01426 // Use the current length of the vector as the reserve amount. 01427 reserve_value_capacity(length()); 01428 } 01429 01458 unsigned int 01459 Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement) 01460 { 01461 static const string funcName = "set_value_slice_from_row_major_vector:"; 01462 01463 // semantically const from the caller's viewpoint, but some calls are not syntactic const. 01464 Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC); 01465 01466 bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type()); 01467 if (!typesMatch) { 01468 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!"); 01469 } 01470 01471 // Make sure the data exists 01472 if (!rowMajorData.read_p()) { 01473 throw InternalErr(__FILE__, __LINE__, 01474 funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!"); 01475 } 01476 01477 // Check this otherwise the static_cast<unsigned int> below will do the wrong thing. 01478 if (rowMajorData.length() < 0) { 01479 throw InternalErr(__FILE__, __LINE__, 01480 funcName 01481 + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!"); 01482 } 01483 01484 // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory 01485 // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed. 01486 if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) { 01487 throw InternalErr(__FILE__, __LINE__, 01488 funcName 01489 + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!"); 01490 } 01491 01492 // Make sure there's enough room in this Vector to store all the elements requested. Again, 01493 // better to throw than just copy what we can since it implies a logic error that needs to be solved. 01494 if (d_capacity < (startElement + rowMajorData.length())) { 01495 throw InternalErr(__FILE__, __LINE__, 01496 funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!"); 01497 } 01498 01499 // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type. 01500 switch (d_proto->type()) { 01501 case dods_int8_c: 01502 case dods_uint8_c: 01503 case dods_byte_c: 01504 case dods_char_c: 01505 case dods_int16_c: 01506 case dods_uint16_c: 01507 case dods_int32_c: 01508 case dods_uint32_c: 01509 case dods_int64_c: 01510 case dods_uint64_c: 01511 01512 case dods_enum_c: 01513 01514 case dods_float32_c: 01515 case dods_float64_c: { 01516 if (!d_buf) { 01517 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!"); 01518 } 01519 if (!rowMajorData.d_buf) { 01520 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!"); 01521 } 01522 // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element) 01523 int varWidth = d_proto->width(); 01524 char* pFromBuf = rowMajorData.d_buf; 01525 int numBytesToCopy = rowMajorData.width(true); 01526 char* pIntoBuf = d_buf + (startElement * varWidth); 01527 memcpy(pIntoBuf, pFromBuf, numBytesToCopy); 01528 break; 01529 } 01530 01531 case dods_str_c: 01532 case dods_url_c: 01533 // Strings need to be copied directly 01534 for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) { 01535 d_str[startElement + i] = rowMajorData.d_str[i]; 01536 } 01537 break; 01538 01539 case dods_array_c: 01540 case dods_opaque_c: 01541 case dods_structure_c: 01542 case dods_sequence_c: 01543 case dods_grid_c: 01544 // Not sure that this function will be used for these type of nested objects, so I will throw here. 01545 throw InternalErr(__FILE__, __LINE__, 01546 funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid."); 01547 break; 01548 01549 default: 01550 throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!"); 01551 break; 01552 01553 } // switch (_var->type()) 01554 01555 // This is how many elements we copied. 01556 return (unsigned int) rowMajorData.length(); 01557 } 01558 01567 template <typename T> 01568 static bool types_match(Type t, T *cpp_var) 01569 { 01570 switch (t) { 01571 case dods_byte_c: 01572 case dods_char_c: 01573 case dods_uint8_c: 01574 return typeid(cpp_var) == typeid(dods_byte*); 01575 01576 case dods_int8_c: 01577 return typeid(cpp_var) == typeid(dods_int8*); 01578 case dods_int16_c: 01579 return typeid(cpp_var) == typeid(dods_int16*); 01580 case dods_uint16_c: 01581 return typeid(cpp_var) == typeid(dods_uint16*); 01582 case dods_int32_c: 01583 return typeid(cpp_var) == typeid(dods_int32*); 01584 case dods_uint32_c: 01585 return typeid(cpp_var) == typeid(dods_uint32*); 01586 case dods_int64_c: 01587 return typeid(cpp_var) == typeid(dods_int64*); 01588 case dods_uint64_c: 01589 return typeid(cpp_var) == typeid(dods_uint64*); 01590 01591 case dods_float32_c: 01592 return typeid(cpp_var) == typeid(dods_float32*); 01593 case dods_float64_c: 01594 return typeid(cpp_var) == typeid(dods_float64*); 01595 01596 case dods_null_c: 01597 case dods_enum_c: 01598 case dods_str_c: 01599 case dods_url_c: 01600 case dods_opaque_c: 01601 case dods_array_c: 01602 case dods_structure_c: 01603 case dods_sequence_c: 01604 case dods_group_c: 01605 default: 01606 return false; 01607 } 01608 } 01609 01611 01613 template <typename T> 01614 bool Vector::set_value_worker(T *v, int sz) 01615 { 01616 if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v)) 01617 return false; 01618 01619 m_set_cardinal_values_internal(v, sz); 01620 return true; 01621 } 01622 01623 bool Vector::set_value(dods_byte *val, int sz) 01624 { 01625 return set_value_worker(val, sz); 01626 } 01627 bool Vector::set_value(dods_int8 *val, int sz) 01628 { 01629 return set_value_worker(val, sz); 01630 } 01631 bool Vector::set_value(dods_int16 *val, int sz) 01632 { 01633 return set_value_worker(val, sz); 01634 } 01635 bool Vector::set_value(dods_uint16 *val, int sz) 01636 { 01637 return set_value_worker(val, sz); 01638 } 01639 bool Vector::set_value(dods_int32 *val, int sz) 01640 { 01641 return set_value_worker(val, sz); 01642 } 01643 bool Vector::set_value(dods_uint32 *val, int sz) 01644 { 01645 return set_value_worker(val, sz); 01646 } 01647 bool Vector::set_value(dods_int64 *val, int sz) 01648 { 01649 return set_value_worker(val, sz); 01650 } 01651 bool Vector::set_value(dods_uint64 *val, int sz) 01652 { 01653 return set_value_worker(val, sz); 01654 } 01655 bool Vector::set_value(dods_float32 *val, int sz) 01656 { 01657 return set_value_worker(val, sz); 01658 } 01659 bool Vector::set_value(dods_float64 *val, int sz) 01660 { 01661 return set_value_worker(val, sz); 01662 } 01663 01665 bool Vector::set_value(string *val, int sz) 01666 { 01667 if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) { 01668 d_str.resize(sz); 01669 d_capacity = sz; 01670 for (register int t = 0; t < sz; t++) { 01671 d_str[t] = val[t]; 01672 } 01673 set_length(sz); 01674 set_read_p(true); 01675 return true; 01676 } 01677 else { 01678 return false; 01679 } 01680 } 01681 01682 template<typename T> 01683 bool Vector::set_value_worker(vector<T> &v, int sz) 01684 { 01685 return set_value(&v[0], sz); 01686 } 01687 01688 bool Vector::set_value(vector<dods_byte> &val, int sz) 01689 { 01690 return set_value_worker(val, sz); 01691 } 01692 bool Vector::set_value(vector<dods_int8> &val, int sz) 01693 { 01694 return set_value_worker(val, sz); 01695 } 01696 bool Vector::set_value(vector<dods_int16> &val, int sz) 01697 { 01698 return set_value_worker(val, sz); 01699 } 01700 bool Vector::set_value(vector<dods_uint16> &val, int sz) 01701 { 01702 return set_value_worker(val, sz); 01703 } 01704 bool Vector::set_value(vector<dods_int32> &val, int sz) 01705 { 01706 return set_value_worker(val, sz); 01707 } 01708 bool Vector::set_value(vector<dods_uint32> &val, int sz) 01709 { 01710 return set_value_worker(val, sz); 01711 } 01712 bool Vector::set_value(vector<dods_int64> &val, int sz) 01713 { 01714 return set_value_worker(val, sz); 01715 } 01716 bool Vector::set_value(vector<dods_uint64> &val, int sz) 01717 { 01718 return set_value_worker(val, sz); 01719 } 01720 bool Vector::set_value(vector<dods_float32> &val, int sz) 01721 { 01722 return set_value_worker(val, sz); 01723 } 01724 bool Vector::set_value(vector<dods_float64> &val, int sz) 01725 { 01726 return set_value_worker(val, sz); 01727 } 01728 01729 01731 bool Vector::set_value(vector<string> &val, int sz) 01732 { 01733 if (var()->type() == dods_str_c || var()->type() == dods_url_c) { 01734 d_str.resize(sz); 01735 d_capacity = sz; 01736 for (register int t = 0; t < sz; t++) { 01737 d_str[t] = val[t]; 01738 } 01739 set_length(sz); 01740 set_read_p(true); 01741 return true; 01742 } 01743 else { 01744 return false; 01745 } 01746 } 01748 01750 01767 template <typename T> 01768 void Vector::value_worker(vector<unsigned int> *indices, T *b) const 01769 { 01770 // unsigned long currentIndex; 01771 #if 0 01772 // Iterator version. Not tested, jhrg 8/14/13 01773 for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) { 01774 unsigned long currentIndex = *i; 01775 if(currentIndex > (unsigned int)length()){ 01776 stringstream s; 01777 s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " << 01778 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. "; 01779 throw Error(s.str()); 01780 } 01781 b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex]; 01782 } 01783 #endif 01784 for (unsigned long i = 0, e = indices->size(); i < e; ++i) { 01785 unsigned long currentIndex = (*indices)[i]; 01786 if (currentIndex > (unsigned int)length()) { 01787 stringstream s; 01788 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " << 01789 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. "; 01790 throw Error(s.str()); 01791 } 01792 b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works! 01793 } 01794 } 01795 void Vector::value(vector<unsigned int> *indices, dods_byte *b) const { value_worker(indices, b); } 01796 void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const { value_worker(indices, b); } 01797 void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const { value_worker(indices, b); } 01798 void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const { value_worker(indices, b); } 01799 void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const { value_worker(indices, b); } 01800 void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const { value_worker(indices, b); } 01801 void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const { value_worker(indices, b); } 01802 void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const { value_worker(indices, b); } 01803 void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); } 01804 void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); } 01805 01806 #if 0 01807 template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const; 01808 template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const; 01809 template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const; 01810 template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const; 01811 template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const; 01812 template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const; 01813 template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const; 01814 template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const; 01815 template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const; 01816 template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const; 01817 #endif 01818 01820 void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const 01821 { 01822 unsigned long currentIndex; 01823 01824 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){ 01825 for(unsigned long i=0; i<subsetIndex->size() ;++i){ 01826 currentIndex = (*subsetIndex)[i] ; 01827 if(currentIndex > (unsigned int)length()){ 01828 stringstream s; 01829 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " << 01830 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. "; 01831 throw Error(s.str()); 01832 } 01833 b[i] = d_str[currentIndex]; 01834 } 01835 } 01836 } 01837 01838 template <typename T> 01839 void Vector::value_worker(T *v) const 01840 { 01841 // Only copy if v is not null and the proto's type matches. 01842 // For Enums, use the element type since type == dods_enum_c. 01843 if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v)) 01844 memcpy(v, d_buf, length() * sizeof(T)); 01845 } 01846 void Vector::value(dods_byte *b) const { value_worker(b); } 01847 void Vector::value(dods_int8 *b) const { value_worker(b); } 01848 void Vector::value(dods_int16 *b) const { value_worker(b); } 01849 void Vector::value(dods_uint16 *b) const { value_worker(b); } 01850 void Vector::value(dods_int32 *b) const { value_worker(b); } 01851 void Vector::value(dods_uint32 *b) const { value_worker(b); } 01852 void Vector::value(dods_int64 *b) const { value_worker(b); } 01853 void Vector::value(dods_uint64 *b) const { value_worker(b); } 01854 void Vector::value(dods_float32 *b) const { value_worker(b); } 01855 void Vector::value(dods_float64 *b) const { value_worker(b); } 01856 01857 #if 0 01858 template void Vector::value(dods_byte *v) const; 01859 template void Vector::value(dods_int8 *v) const; 01860 template void Vector::value(dods_int16 *v) const; 01861 template void Vector::value(dods_uint16 *v) const; 01862 template void Vector::value(dods_int32 *v) const; 01863 template void Vector::value(dods_uint32 *v) const; 01864 template void Vector::value(dods_int64 *v) const; 01865 template void Vector::value(dods_uint64 *v) const; 01866 template void Vector::value(dods_float32 *v) const; 01867 template void Vector::value(dods_float64 *v) const; 01868 #endif 01869 01870 01872 void Vector::value(vector<string> &b) const 01873 { 01874 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c) 01875 b = d_str; 01876 } 01877 01880 void *Vector::value() 01881 { 01882 void *buffer = new char[width(true)]; 01883 01884 memcpy(buffer, d_buf, width(true)); 01885 01886 return buffer; 01887 } 01889 01905 void Vector::add_var(BaseType * v, Part /*p*/) 01906 { 01907 #if 0 01908 // Why doesn't this work? tried all 3 variants. jhrg 8/14/13 01909 Vector::add_var_nocopy(v->ptr_duplicate(), p); 01910 add_var_nocopy(v->ptr_duplicate(), p); 01911 add_var_nocopy(v->ptr_duplicate()); 01912 #else 01913 // Delete the current template variable 01914 if (d_proto) { 01915 delete d_proto; 01916 d_proto = 0; 01917 } 01918 01919 // if 'v' is null, just set _var to null and exit. 01920 if (!v) { 01921 d_proto = 0; 01922 } 01923 else { 01924 // Jose Garcia 01925 // By getting a copy of this object to be assigned to _var 01926 // we let the owner of 'v' to deallocate it as necessary. 01927 d_proto = v->ptr_duplicate(); 01928 01929 // If 'v' has a name, use it as the name of the array. If v doesn't have 01930 // a name, then make sure to copy the array's name to it 01931 // so that software which uses the template's name will still work. 01932 if (!v->name().empty()) 01933 set_name(v->name()); 01934 else 01935 d_proto->set_name(name()); 01936 01937 d_proto->set_parent(this); // Vector --> child 01938 01939 DBG(cerr << "Vector::add_var: Added variable " << v << " (" 01940 << v->name() << " " << v->type_name() << ")" << endl); 01941 } 01942 #endif 01943 } 01944 01945 void Vector::add_var_nocopy(BaseType * v, Part) 01946 { 01947 // Delete the current template variable 01948 if (d_proto) { 01949 delete d_proto; 01950 d_proto = 0; 01951 } 01952 01953 // if 'v' is null, just set _var to null and exit. 01954 if (!v) { 01955 d_proto = 0; 01956 } 01957 else { 01958 d_proto = v; 01959 01960 // If 'v' has a name, use it as the name of the array. If it *is* 01961 // empty, then make sure to copy the array's name to the template 01962 // so that software which uses the template's name will still work. 01963 if (!v->name().empty()) 01964 set_name(v->name()); 01965 else 01966 d_proto->set_name(name()); 01967 01968 d_proto->set_parent(this); // Vector is the parent; proto is the child 01969 01970 DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " (" 01971 << v->name() << " " << v->type_name() << ")" << endl); 01972 } 01973 } 01974 01975 bool Vector::check_semantics(string & msg, bool) 01976 { 01977 return BaseType::check_semantics(msg); 01978 } 01979 01988 void Vector::dump(ostream &strm) const 01989 { 01990 strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl; 01991 DapIndent::Indent(); 01992 BaseType::dump(strm); 01993 strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl; 01994 if (d_proto) { 01995 strm << DapIndent::LMarg << "base type:" << endl; 01996 DapIndent::Indent(); 01997 d_proto->dump(strm); 01998 DapIndent::UnIndent(); 01999 } 02000 else { 02001 strm << DapIndent::LMarg << "base type: not set" << endl; 02002 } 02003 strm << DapIndent::LMarg << "vector contents:" << endl; 02004 DapIndent::Indent(); 02005 for (unsigned i = 0; i < d_compound_buf.size(); ++i) { 02006 if (d_compound_buf[i]) 02007 d_compound_buf[i]->dump(strm); 02008 else 02009 strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl; 02010 } 02011 DapIndent::UnIndent(); 02012 strm << DapIndent::LMarg << "strings:" << endl; 02013 DapIndent::Indent(); 02014 for (unsigned i = 0; i < d_str.size(); i++) { 02015 strm << DapIndent::LMarg << d_str[i] << endl; 02016 } 02017 DapIndent::UnIndent(); 02018 if (d_buf) { 02019 switch (d_proto != 0 ? d_proto->type() : 0) { 02020 case dods_byte_c: 02021 case dods_char_c: 02022 strm << DapIndent::LMarg << "_buf: "; 02023 strm.write(d_buf, d_length); 02024 strm << endl; 02025 break; 02026 02027 case 0: 02028 default: 02029 strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl; 02030 break; 02031 } 02032 } 02033 else { 02034 strm << DapIndent::LMarg << "_buf: EMPTY" << endl; 02035 } 02036 02037 DapIndent::UnIndent(); 02038 } 02039 02040 } // namespace libdap 02041