libdap++ Updated for version 3.8.2
|
00001 00002 // -*- mode: c++; c-basic-offset:4 -*- 00003 00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00005 // Access Protocol. 00006 00007 // Copyright (c) 2002,2003 OPeNDAP, Inc. 00008 // Author: James Gallagher <jgallagher@opendap.org> 00009 // 00010 // This library is free software; you can redistribute it and/or 00011 // modify it under the terms of the GNU Lesser General Public 00012 // License as published by the Free Software Foundation; either 00013 // version 2.1 of the License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00023 // 00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00025 00026 // (c) COPYRIGHT URI/MIT 1995-1999 00027 // Please read the full copyright statement in the file COPYRIGHT_URI. 00028 // 00029 // Authors: 00030 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00031 00032 // Implementation for class Vector. This class is the basis for all the 00033 // vector-type classes in libdap's <Array, List>. 00034 // 00035 // 11/21/95 jhrg 00036 00037 #include "config.h" 00038 00039 #include <cstring> 00040 00041 static char rcsid[] not_used = 00042 { "$Id: Vector.cc 21976 2010-01-12 17:16:22Z jimg $" 00043 }; 00044 00045 //#define DODS_DEBUG 00046 00047 #include <algorithm> 00048 00049 #include "Vector.h" 00050 #include "escaping.h" 00051 #include "util.h" 00052 #include "debug.h" 00053 #include "InternalErr.h" 00054 #include <sstream> 00055 00056 using std::cerr; 00057 using std::endl; 00058 00059 namespace libdap { 00060 00061 void Vector::_duplicate(const Vector & v) 00062 { 00063 _length = v._length; 00064 00065 // _var holds the type of the elements. That is, it holds a BaseType 00066 // which acts as a template for the type of each element. 00067 if (v._var) { 00068 _var = v._var->ptr_duplicate(); // use ptr_duplicate() 00069 _var->set_parent(this); // ptr_duplicate does not set d_parent. 00070 } 00071 else { 00072 _var = 0; 00073 } 00074 00075 // _vec and _buf (further down) hold the values of the Vector. The field 00076 // _vec is used when the Vector holds non-numeric data (including strings 00077 // although it used to be that was not the case jhrg 2/10/05) while _buf 00078 // holds numeric values. 00079 if (v._vec.empty()) { 00080 _vec = v._vec; 00081 } 00082 else { 00083 // Failure to set the size will make the [] operator barf on the LHS 00084 // of the assignment inside the loop. 00085 _vec.resize(_length); 00086 for (int i = 0; i < _length; ++i) { 00087 // There's no need to call set_parent() for each element; we 00088 // maintain the back pointer using the _var member. These 00089 // instances are used to hold _values_ only while the _var 00090 // field holds the type of the elements. 00091 _vec[i] = v._vec[i]->ptr_duplicate(); 00092 } 00093 } 00094 00095 // copy the strings. This copies the values. 00096 d_str = v.d_str; 00097 00098 // copy numeric values if there are any. 00099 _buf = 0; // init to null 00100 if (v._buf) // only copy if data present 00101 val2buf(v._buf); // store v's value in this's _BUF. 00102 00103 _capacity = v._capacity; 00104 } 00105 00110 bool 00111 Vector::is_cardinal_type() const 00112 { 00113 // Not cardinal if no _var at all! 00114 if (!_var) { 00115 return false; 00116 } 00117 00118 switch (_var->type()) { 00119 case dods_byte_c: 00120 case dods_int16_c: 00121 case dods_uint16_c: 00122 case dods_int32_c: 00123 case dods_uint32_c: 00124 case dods_float32_c: 00125 case dods_float64_c: { 00126 return true; 00127 break; 00128 } 00129 00130 // These must be handled differently. 00131 case dods_str_c: 00132 case dods_url_c: 00133 case dods_array_c: 00134 case dods_structure_c: 00135 case dods_sequence_c: 00136 case dods_grid_c: 00137 return false; 00138 break; 00139 00140 default: 00141 cerr << "Vector::var: Unrecognized type" << endl; 00142 return false; 00143 } // switch 00144 } 00145 00158 unsigned int 00159 Vector::create_cardinal_data_buffer_for_type(unsigned int numEltsOfType) 00160 { 00161 // Make sure we HAVE a _var, or we cannot continue. 00162 if (!_var) { 00163 throw InternalErr(__FILE__, __LINE__, 00164 "create_cardinal_data_buffer_for_type: Logic error: _var is null!"); 00165 } 00166 00167 // Make sure we only do this for the correct data types. 00168 if (!is_cardinal_type()) { 00169 throw InternalErr(__FILE__, __LINE__, 00170 "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types)."); 00171 } 00172 00173 delete_cardinal_data_buffer(); 00174 00175 // Actually new up the array with enough bytes to hold numEltsOfType of the actual type. 00176 unsigned int bytesPerElt = _var->width(); 00177 unsigned int bytesNeeded = bytesPerElt * numEltsOfType; 00178 _buf = new char[bytesNeeded]; 00179 if (!_buf) { 00180 ostringstream oss; 00181 oss << "create_cardinal_data_buffer_for_type: new char[] failed to allocate " << 00182 bytesNeeded << 00183 " bytes! Out of memory or too large a buffer required!"; 00184 throw InternalErr(__FILE__, __LINE__, oss.str()); 00185 } 00186 _capacity = numEltsOfType; 00187 return bytesNeeded; 00188 } 00189 00191 void 00192 Vector::delete_cardinal_data_buffer() 00193 { 00194 if (_buf) { 00195 delete[] _buf; 00196 _buf = 0; 00197 _capacity = 0; 00198 } 00199 } 00200 00204 template <class CardType> 00205 void 00206 Vector::set_cardinal_values_internal(const CardType* fromArray, int numElts) 00207 { 00208 if (numElts < 0) { 00209 throw InternalErr(__FILE__, __LINE__, 00210 "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!"); 00211 } 00212 if (!fromArray) { 00213 throw InternalErr(__FILE__, __LINE__, 00214 "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!"); 00215 } 00216 set_length(numElts); 00217 create_cardinal_data_buffer_for_type(numElts); 00218 memcpy(_buf, fromArray, numElts * sizeof(CardType) ); 00219 set_read_p(true); 00220 } 00221 00222 00239 Vector::Vector(const string & n, BaseType * v, const Type & t) 00240 : BaseType(n, t), _length(-1), _var(0), _buf(0), _vec(0), _capacity(0) 00241 { 00242 if (v) 00243 add_var(v); 00244 00245 DBG2(cerr << "Entering Vector ctor for object: " << this << endl); 00246 if (_var) 00247 _var->set_parent(this); 00248 } 00249 00269 Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t) 00270 : BaseType(n, d, t), _length(-1), _var(0), _buf(0), _vec(0), _capacity(0) 00271 { 00272 if (v) 00273 add_var(v); 00274 00275 DBG2(cerr << "Entering Vector ctor for object: " << this << endl); 00276 if (_var) 00277 _var->set_parent(this); 00278 } 00279 00281 Vector::Vector(const Vector & rhs): BaseType(rhs) 00282 { 00283 DBG2(cerr << "Entering Vector const ctor for object: " << this << 00284 endl); 00285 DBG2(cerr << "RHS: " << &rhs << endl); 00286 00287 _duplicate(rhs); 00288 } 00289 00290 Vector::~Vector() 00291 { 00292 DBG2(cerr << "Entering ~Vector (" << this << ")" << endl); 00293 00294 delete _var; 00295 _var = 0; 00296 00297 // Clears all buffers 00298 clear_local_data(); 00299 00300 DBG2(cerr << "Exiting ~Vector" << endl); 00301 } 00302 00303 Vector & Vector::operator=(const Vector & rhs) 00304 { 00305 if (this == &rhs) 00306 return *this; 00307 00308 dynamic_cast < BaseType & >(*this) = rhs; 00309 00310 _duplicate(rhs); 00311 00312 return *this; 00313 } 00314 00315 void 00316 Vector::set_name(const std::string& name) 00317 { 00318 BaseType::set_name(name); 00319 // We need to set the template variable name as well since 00320 // this is what gets output in the dds! Otherwise, there's a mismatch. 00321 if (_var) { 00322 _var->set_name(name); 00323 } 00324 } 00325 00326 int Vector::element_count(bool leaves) 00327 { 00328 if (!leaves) 00329 return 1; 00330 else 00331 // var() only works for simple types! 00332 return var(0)->element_count(leaves); 00333 } 00334 00335 // These mfuncs set the _send_p and _read_p fields of BaseType. They differ 00336 // from BaseType's version in that they set both the Vector object's copy of 00337 // _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR 00338 // is a scalar, but does matter when it is an aggregate. 00339 00346 void Vector::set_send_p(bool state) 00347 { 00348 _var->set_send_p(state); 00349 BaseType::set_send_p(state); 00350 } 00351 00358 void Vector::set_read_p(bool state) 00359 { 00360 if (_var) { 00361 _var->set_read_p(state); 00362 } 00363 BaseType::set_read_p(state); 00364 } 00365 00383 BaseType *Vector::var(const string & n, bool exact, btp_stack * s) 00384 { 00385 string name = www2id(n); 00386 DBG(cerr << "Vector::var: Looking for " << n << endl); 00387 00388 // Make sure to check for the case where name is the default (the empty 00389 // string). 9/1/98 jhrg 00390 if (_var->is_constructor_type()) { 00391 if (name == "" || _var->name() == name) { 00392 if (s) 00393 s->push(this); 00394 return _var; 00395 } 00396 else { 00397 BaseType * result = _var->var(name, exact, s); 00398 if (result && s) 00399 s->push(this); 00400 return result; 00401 } 00402 } 00403 else { 00404 return _var; // I don't see why this isn't return 0 *** jhrg 10/9/08 00405 } 00406 } 00407 00418 BaseType *Vector::var(const string & n, btp_stack & s) 00419 { 00420 string name = www2id(n); 00421 00422 if (_var->is_constructor_type()) 00423 return _var->var(name, s); 00424 else { 00425 s.push((BaseType *) this); 00426 return _var; 00427 } 00428 } 00429 00430 // Return a pointer the the BaseType object for element I. If the Vector is 00431 // of a cardinal type, store the ith element's value in the BaseType 00432 // object. If it is a Vector of a non-cardinal type, then this mfunc returns 00433 // _vec[i]. 00434 // 00435 // NB: I defaults to zero. 00436 // 00437 // Returns: A BaseType pointer to the ith element of the Vector. 00438 00454 BaseType *Vector::var(unsigned int i) 00455 { 00456 00457 switch (_var->type()) { 00458 case dods_byte_c: 00459 case dods_int16_c: 00460 case dods_uint16_c: 00461 case dods_int32_c: 00462 case dods_uint32_c: 00463 case dods_float32_c: 00464 case dods_float64_c: { 00465 // Transfer the ith value to the BaseType *_var; There are more 00466 // efficient ways to get a whole array using buf2val() but this is 00467 // an OK way to get a single value or several non-contiguous values. 00468 unsigned int sz = _var->width(); 00469 _var->val2buf((char *) _buf + (i * sz)); 00470 return _var; 00471 break; 00472 } 00473 00474 case dods_str_c: 00475 case dods_url_c: 00476 _var->val2buf(&d_str[i]); 00477 return _var; 00478 break; 00479 00480 case dods_array_c: 00481 case dods_structure_c: 00482 case dods_sequence_c: 00483 case dods_grid_c: 00484 return _vec[i]; 00485 break; 00486 00487 default: 00488 cerr << "Vector::var: Unrecognized type" << endl; 00489 } 00490 00491 return 0; 00492 } 00493 00494 // Return: The number of bytes required to store the vector `in a C 00495 // program'. For an array of cardinal types this is the same as the storage 00496 // used by _BUF. For anything else, it is the product of length() and the 00497 // element width(). It turns out that both values can be computed the same 00498 // way. 00499 // 00500 // Returns: The number of bytes used to store the vector. 00501 00507 unsigned int Vector::width() 00508 { 00509 // Jose Garcia 00510 if (!_var) { 00511 throw InternalErr(__FILE__, __LINE__, 00512 "Cannot get width since *this* object is not holding data."); 00513 } 00514 00515 return length() * _var->width(); 00516 } 00517 00518 // Returns: the number of elements in the vector. 00519 00524 int Vector::length() const 00525 { 00526 return _length; 00527 } 00528 00529 // set the number of elements in the vector. 00530 // 00531 // Returns: void 00532 00535 void Vector::set_length(int l) 00536 { 00537 _length = l; 00538 } 00539 00540 // \e l is the number of elements the vector can hold (e.g., if l == 20, then 00541 // the vector can hold elements 0, .., 19). 00542 00548 void Vector::vec_resize(int l) 00549 { 00550 _vec.resize((l > 0) ? l : 0, 0); // Fill with NULLs 00551 _capacity = l; // capacity in terms of number of elements. 00552 } 00553 00569 void 00570 Vector::intern_data(ConstraintEvaluator &eval, DDS &dds) 00571 { 00572 DBG(cerr << "Vector::intern_data: " << name() << endl); 00573 if (!read_p()) 00574 read(); // read() throws Error and InternalErr 00575 00576 // length() is not capacity; it must be set explicitly in read(). 00577 int num = length(); 00578 00579 switch (_var->type()) { 00580 case dods_byte_c: 00581 case dods_int16_c: 00582 case dods_uint16_c: 00583 case dods_int32_c: 00584 case dods_uint32_c: 00585 case dods_float32_c: 00586 case dods_float64_c: 00587 // For these cases, read() puts the data into _buf, which is what we 00588 // need to do 'stuff' with the data. 00589 break; 00590 00591 case dods_str_c: 00592 case dods_url_c: 00593 // For these cases, read() will put the data into d_str[], which is 00594 // what the transformation classes need. 00595 break; 00596 00597 case dods_array_c: 00598 // I think this is an error since there can never be an Array of 00599 // Array. 00600 throw InternalErr(__FILE__, __LINE__, "Array of Array not supported."); 00601 break; 00602 00603 case dods_structure_c: 00604 case dods_sequence_c: 00605 case dods_grid_c: 00606 DBG(cerr << "Vector::intern_data: found ctor" << endl); 00607 // For these cases, we need to call read() for each of the 'num' 00608 // elements in the '_vec[]' array of BaseType object pointers. 00609 if (_vec.capacity() == 0) 00610 throw InternalErr(__FILE__, __LINE__, 00611 "The capacity of *this* vector is 0."); 00612 00613 for (int i = 0; i < num; ++i) 00614 _vec[i]->intern_data(eval, dds); 00615 00616 break; 00617 00618 default: 00619 throw InternalErr(__FILE__, __LINE__, "Unknown datatype."); 00620 break; 00621 } 00622 } 00623 00636 bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, 00637 Marshaller &m, bool ce_eval) 00638 { 00639 int i = 0; 00640 00641 dds.timeout_on(); 00642 00643 if (!read_p()) 00644 read(); // read() throws Error and InternalErr 00645 00646 #if EVAL 00647 if (ce_eval && !eval.eval_selection(dds, dataset())) 00648 return true; 00649 #endif 00650 00651 dds.timeout_off(); 00652 00653 // length() is not capacity; it must be set explicitly in read(). 00654 int num = length(); 00655 00656 switch (_var->type()) { 00657 case dods_byte_c: 00658 m.put_vector( _buf, num, *this ) ; 00659 break ; 00660 case dods_int16_c: 00661 case dods_uint16_c: 00662 case dods_int32_c: 00663 case dods_uint32_c: 00664 case dods_float32_c: 00665 case dods_float64_c: 00666 m.put_vector( _buf, num, _var->width(), *this ) ; 00667 break; 00668 00669 case dods_str_c: 00670 case dods_url_c: 00671 if (d_str.capacity() == 0) 00672 throw InternalErr(__FILE__, __LINE__, 00673 "The capacity of the string vector is 0"); 00674 00675 m.put_int( num ) ; 00676 00677 for (i = 0; i < num; ++i) 00678 m.put_str( d_str[i] ) ; 00679 00680 break; 00681 00682 case dods_array_c: 00683 case dods_structure_c: 00684 case dods_sequence_c: 00685 case dods_grid_c: 00686 //Jose Garcia 00687 // Not setting the capacity of _vec is an internal error. 00688 if (_vec.capacity() == 0) 00689 throw InternalErr(__FILE__, __LINE__, 00690 "The capacity of *this* vector is 0."); 00691 00692 m.put_int( num ) ; 00693 00694 for (i = 0; i < num; ++i) 00695 _vec[i]->serialize(eval, dds, m, false); 00696 00697 break; 00698 00699 default: 00700 throw InternalErr(__FILE__, __LINE__, "Unknown datatype."); 00701 break; 00702 } 00703 00704 return true; 00705 } 00706 00707 // Read an object from the network and internalize it. For a Vector this is 00708 // handled differently for a `cardinal' type. Vectors of Cardinals are 00709 // stored using the `C' representations because these objects often are used 00710 // to build huge arrays (e.g., an array of 1024 by 1024 bytes). However, 00711 // arrays of non-cardinal types are stored as Vectors of the C++ objects or 00712 // DAP2 objects (Str and Url are vectors of the string class, Structure, ..., 00713 // Grid are vectors of the libdap Structure, ... classes). 00714 // 00715 // The boolean parameter REUSE determines whether internal storage is reused 00716 // or not. If true, the _buf member is assumed to be large enough to hold the 00717 // incoming cardinal data and is *not* reallocated. If false, new storage is 00718 // allocated. If the internal buffer has not yet been allocated, then this 00719 // parameter has no effect (i.e., storage is allocated). This parameter 00720 // effects storage for cardinal data only. 00721 // 00722 // Returns: True is successful, false otherwise. 00723 00724 bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse) 00725 { 00726 unsigned int num; 00727 unsigned i = 0; 00728 00729 switch (_var->type()) { 00730 case dods_byte_c: 00731 case dods_int16_c: 00732 case dods_uint16_c: 00733 case dods_int32_c: 00734 case dods_uint32_c: 00735 case dods_float32_c: 00736 case dods_float64_c: 00737 if (_buf && !reuse) { 00738 delete_cardinal_data_buffer(); 00739 } 00740 00741 um.get_int( (int &)num ) ; 00742 00743 DBG(cerr << "Vector::deserialize: num = " << num << endl); 00744 DBG(cerr << "Vector::deserialize: length = " << length() << endl); 00745 00746 if (length() == -1) 00747 set_length(num); 00748 00749 if (num != (unsigned int) length()) 00750 throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes."); 00751 00752 if (!_buf) { 00753 // Make _buf be large enough for length() elements of _var->type() 00754 create_cardinal_data_buffer_for_type(length()); 00755 DBG(cerr << "Vector::deserialize: allocating " 00756 << width() << " bytes for an array of " 00757 << length() << " " << _var->type_name() << endl); 00758 } 00759 00760 if (_var->type() == dods_byte_c) 00761 um.get_vector( (char **)&_buf, num, *this ) ; 00762 else 00763 um.get_vector( (char **)&_buf, num, _var->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__, 00778 "The client sent declarations and data with mismatched sizes."); 00779 00780 d_str.resize((num > 0) ? num : 0); // Fill with NULLs 00781 _capacity = num; // capacity is number of strings we can fit. 00782 00783 for (i = 0; i < num; ++i) { 00784 string str; 00785 um.get_str( str ) ; 00786 d_str[i] = str; 00787 00788 } 00789 00790 break; 00791 00792 case dods_array_c: 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 _vec[i] = _var->ptr_duplicate(); 00808 _vec[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 00848 unsigned int Vector::val2buf(void *val, bool reuse) 00849 { 00850 // Jose Garcia 00851 00852 // I *think* this method has been mainly designed to be use by read which 00853 // is implemented in the surrogate library. Passing NULL as a pointer to 00854 // this method will be an error of the creator of the surrogate library. 00855 // Even though I recognize the fact that some methods inside libdap++ can 00856 // call val2buf, I think by now no coding bugs such as misusing val2buf 00857 // will be in libdap++, so it will be an internal error from the 00858 // surrogate library. 00859 if (!val) 00860 throw InternalErr(__FILE__, __LINE__, 00861 "The incoming pointer does not contain any data."); 00862 00863 switch (_var->type()) { 00864 case dods_byte_c: 00865 case dods_int16_c: 00866 case dods_uint16_c: 00867 case dods_int32_c: 00868 case dods_uint32_c: 00869 case dods_float32_c: 00870 case dods_float64_c: { 00871 // width() returns the size given the constraint 00872 unsigned int array_wid = width(); 00873 if (_buf && !reuse) { 00874 delete_cardinal_data_buffer(); 00875 } 00876 00877 if (!_buf) { // First time or no reuse (free'd above) 00878 create_cardinal_data_buffer_for_type(length()); 00879 } 00880 00881 memcpy(_buf, val, array_wid); 00882 break; 00883 } 00884 00885 case dods_str_c: 00886 case dods_url_c: { 00887 // Assume val points to an array of C++ string objects. Copy 00888 // them into the vector<string> field of this object. 00889 d_str.resize(_length); 00890 _capacity = _length; 00891 for (int i = 0; i < _length; ++i) 00892 d_str[i] = *(static_cast < string * >(val) + i); 00893 00894 break; 00895 } 00896 00897 default: 00898 throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type"); 00899 00900 } 00901 00902 return width(); 00903 } 00904 00935 unsigned int Vector::buf2val(void **val) 00936 { 00937 // Jose Garcia 00938 // The same comment in Vector::val2buf applies here! 00939 if (!val) 00940 throw InternalErr(__FILE__, __LINE__, "NULL pointer."); 00941 00942 unsigned int wid = static_cast<unsigned int>(width()); 00943 // This is the width computed using length(). The 00944 // length() property is changed when a projection 00945 // constraint is applied. Thus this is the number of 00946 // bytes in the buffer given the current constraint. 00947 00948 switch (_var->type()) { 00949 case dods_byte_c: 00950 case dods_int16_c: 00951 case dods_uint16_c: 00952 case dods_int32_c: 00953 case dods_uint32_c: 00954 case dods_float32_c: 00955 case dods_float64_c: 00956 if (!*val) { 00957 *val = new char[wid]; 00958 } 00959 // avoid bus error if _buf is null and this is called improperly. 00960 if (!_buf) { 00961 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when _buf was null!"); 00962 } 00963 00964 (void) memcpy(*val, _buf, wid); 00965 00966 break; 00967 00968 case dods_str_c: 00969 case dods_url_c: { 00970 if (!*val) 00971 *val = new string[_length]; 00972 00973 for (int i = 0; i < _length; ++i) 00974 *(static_cast < string * >(*val) + i) = d_str[i]; 00975 00976 break; 00977 } 00978 00979 default: 00980 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type"); 00981 return 0; 00982 } 00983 00984 return wid; 00985 } 00986 01007 void Vector::set_vec(unsigned int i, BaseType * val) 01008 { 01009 // Jose Garcia 01010 // This is a public method which allows users to set the elements 01011 // of *this* vector. Passing an invalid index, a NULL pointer or 01012 // mismatching the vector type are internal errors. 01013 if (i >= static_cast < unsigned int >(_length)) 01014 throw InternalErr(__FILE__, __LINE__, 01015 "Invalid data: index too large."); 01016 if (!val) 01017 throw InternalErr(__FILE__, __LINE__, 01018 "Invalid data: null pointer to BaseType object."); 01019 if (val->type() != _var->type()) 01020 throw InternalErr(__FILE__, __LINE__, 01021 "invalid data: type of incoming object does not match *this* vector type."); 01022 01023 if (i >= _vec.capacity()) 01024 vec_resize(i + 10); 01025 01026 _vec[i] = val->ptr_duplicate(); 01027 } 01028 01038 void 01039 Vector::clear_local_data() 01040 { 01041 if (_buf) { 01042 delete[]_buf; 01043 _buf = 0; 01044 } 01045 01046 for (unsigned int i = 0; i < _vec.size(); ++i) { 01047 delete _vec[i]; 01048 _vec[i] = 0; 01049 } 01050 01051 // Force memory to be reclaimed. 01052 _vec.resize(0); 01053 d_str.resize(0); 01054 01055 _capacity = 0; 01056 set_read_p(false); 01057 } 01058 01059 01067 unsigned int 01068 Vector::get_value_capacity() const 01069 { 01070 return _capacity; 01071 } 01072 01073 01083 void 01084 Vector::reserve_value_capacity(unsigned int numElements) 01085 { 01086 if (!_var) { 01087 throw InternalErr(__FILE__, __LINE__, 01088 "reserve_value_capacity: Logic error: _var is null!"); 01089 } 01090 switch (_var->type()) { 01091 case dods_byte_c: 01092 case dods_int16_c: 01093 case dods_uint16_c: 01094 case dods_int32_c: 01095 case dods_uint32_c: 01096 case dods_float32_c: 01097 case dods_float64_c: { 01098 // Make _buf be the right size and set _capacity 01099 create_cardinal_data_buffer_for_type(numElements); 01100 } 01101 break; 01102 01103 case dods_str_c: 01104 case dods_url_c: { 01105 // Make sure the d_str has enough room for all the strings. 01106 // Technically not needed, but it will speed things up for large arrays. 01107 d_str.reserve(numElements); 01108 _capacity = numElements; 01109 } 01110 break; 01111 01112 01113 case dods_array_c: 01114 case dods_structure_c: 01115 case dods_sequence_c: 01116 case dods_grid_c: { 01117 // not clear anyone will go this path, but best to be complete. 01118 _vec.reserve(numElements); 01119 _capacity = numElements; 01120 } 01121 break; 01122 01123 default: { 01124 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!"); 01125 } 01126 break; 01127 01128 } // switch 01129 01130 } 01131 01137 void 01138 Vector::reserve_value_capacity() 01139 { 01140 // Use the current length of the vector as the reserve amount. 01141 reserve_value_capacity(length()); 01142 } 01143 01172 unsigned int 01173 Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement) 01174 { 01175 static const string funcName = "set_value_slice_from_row_major_vector:"; 01176 01177 // semantically const from the caller's viewpoint, but some calls are not syntactic const. 01178 Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC); 01179 01180 bool typesMatch = rowMajorData.var() && _var && (rowMajorData.var()->type() == _var->type()); 01181 if (!typesMatch) { 01182 throw InternalErr(__FILE__, __LINE__, 01183 funcName + "Logic error: types do not match so cannot be copied!"); 01184 } 01185 01186 // Make sure the data exists 01187 if (!rowMajorData.read_p()) { 01188 throw InternalErr(__FILE__, __LINE__, 01189 funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!"); 01190 } 01191 01192 // Check this otherwise the static_cast<unsigned int> below will do the wrong thing. 01193 if (rowMajorData.length() < 0) { 01194 throw InternalErr(__FILE__, __LINE__, 01195 funcName + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!"); 01196 } 01197 01198 // The read-in capacity had better be at least the length (the amountt we will copy) or we'll memcpy into bad memory 01199 // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed. 01200 if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) { 01201 throw InternalErr(__FILE__, __LINE__, 01202 funcName + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!"); 01203 } 01204 01205 // Make sure there's enough room in this Vector to store all the elements requested. Again, 01206 // better to throw than just copy what we can since it implies a logic error that needs to be solved. 01207 if (_capacity < (startElement + rowMajorData.length())) { 01208 throw InternalErr(__FILE__, __LINE__, 01209 funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!"); 01210 } 01211 01212 // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type. 01213 switch (_var->type()) { 01214 case dods_byte_c: 01215 case dods_int16_c: 01216 case dods_uint16_c: 01217 case dods_int32_c: 01218 case dods_uint32_c: 01219 case dods_float32_c: 01220 case dods_float64_c: { 01221 if (!_buf) { 01222 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!"); 01223 } 01224 if (!rowMajorData._buf) { 01225 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!"); 01226 } 01227 // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element) 01228 int varWidth = _var->width(); 01229 char* pFromBuf = rowMajorData._buf; 01230 int numBytesToCopy = rowMajorData.width(); 01231 char* pIntoBuf = _buf + (startElement * varWidth); 01232 memcpy(pIntoBuf, 01233 pFromBuf, 01234 numBytesToCopy ); 01235 } 01236 break; 01237 01238 case dods_str_c: 01239 case dods_url_c: { 01240 // Strings need to be copied directly 01241 for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) { 01242 d_str[startElement + i] = rowMajorData.d_str[i]; 01243 } 01244 } 01245 break; 01246 01247 case dods_array_c: 01248 case dods_structure_c: 01249 case dods_sequence_c: 01250 case dods_grid_c: { 01251 // Not sure that this function will be used for these type of nested objects, so I will throw here. 01252 // TODO impl and test this path if it's ever needed. 01253 throw InternalErr(__FILE__, __LINE__, 01254 funcName + "Unimplemented method for Vectors of type: dods_array_c, dods_structure_c, dods_sequence_c and dods_grid_c."); 01255 } 01256 break; 01257 01258 default: { 01259 throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!"); 01260 } 01261 break; 01262 01263 } // switch (_var->type()) 01264 01265 // This is how many elements we copied. 01266 return (unsigned int)rowMajorData.length(); 01267 } 01268 01270 01271 bool 01272 Vector::set_value(dods_byte *val, int sz) 01273 { 01274 if (var()->type() == dods_byte_c && val) { 01275 set_cardinal_values_internal<dods_byte>(val, sz); 01276 return true; 01277 } 01278 else { 01279 return false; 01280 } 01281 } 01282 01284 bool 01285 Vector::set_value(vector<dods_byte> &val, int sz) 01286 { 01287 return set_value(&val[0], sz); 01288 } 01289 01291 bool 01292 Vector::set_value(dods_int16 *val, int sz) 01293 { 01294 if (var()->type() == dods_int16_c && val) { 01295 set_cardinal_values_internal<dods_int16>(val, sz); 01296 return true; 01297 } 01298 else { 01299 return false; 01300 } 01301 } 01302 01304 bool 01305 Vector::set_value(vector<dods_int16> &val, int sz) 01306 { 01307 return set_value(&val[0], sz); 01308 } 01309 01311 bool 01312 Vector::set_value(dods_int32 *val, int sz) 01313 { 01314 if (var()->type() == dods_int32_c && val) { 01315 set_cardinal_values_internal<dods_int32>(val, sz); 01316 return true; 01317 } 01318 else { 01319 return false; 01320 } 01321 } 01322 01324 bool 01325 Vector::set_value(vector<dods_int32> &val, int sz) 01326 { 01327 return set_value(&val[0], sz); 01328 } 01329 01331 bool 01332 Vector::set_value(dods_uint16 *val, int sz) 01333 { 01334 if (var()->type() == dods_uint16_c && val) { 01335 set_cardinal_values_internal<dods_uint16>(val, sz); 01336 return true; 01337 } 01338 else { 01339 return false; 01340 } 01341 } 01342 01344 bool 01345 Vector::set_value(vector<dods_uint16> &val, int sz) 01346 { 01347 return set_value(&val[0], sz); 01348 } 01349 01351 bool 01352 Vector::set_value(dods_uint32 *val, int sz) 01353 { 01354 if (var()->type() == dods_uint32_c && val) { 01355 set_cardinal_values_internal<dods_uint32>(val, sz); 01356 return true; 01357 } 01358 else { 01359 return false; 01360 } 01361 } 01362 01364 bool 01365 Vector::set_value(vector<dods_uint32> &val, int sz) 01366 { 01367 return set_value(&val[0], sz); 01368 } 01369 01371 bool 01372 Vector::set_value(dods_float32 *val, int sz) 01373 { 01374 if (var()->type() == dods_float32_c && val) { 01375 set_cardinal_values_internal<dods_float32>(val, sz); 01376 return true; 01377 } 01378 else { 01379 return false; 01380 } 01381 } 01382 01384 bool 01385 Vector::set_value(vector<dods_float32> &val, int sz) 01386 { 01387 return set_value(&val[0], sz); 01388 } 01389 01391 bool 01392 Vector::set_value(dods_float64 *val, int sz) 01393 { 01394 if (var()->type() == dods_float64_c && val) { 01395 set_cardinal_values_internal<dods_float64>(val, sz); 01396 return true; 01397 } 01398 else { 01399 return false; 01400 } 01401 } 01402 01404 bool 01405 Vector::set_value(vector<dods_float64> &val, int sz) 01406 { 01407 return set_value(&val[0], sz); 01408 } 01409 01411 bool 01412 Vector::set_value(string *val, int sz) 01413 { 01414 if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) { 01415 d_str.resize(sz); 01416 _capacity = sz; 01417 for (register int t = 0; t < sz; t++) { 01418 d_str[t] = val[t] ; 01419 } 01420 set_length(sz) ; 01421 set_read_p(true); 01422 return true; 01423 } 01424 else { 01425 return false; 01426 } 01427 } 01428 01430 bool 01431 Vector::set_value(vector<string> &val, int sz) 01432 { 01433 if (var()->type() == dods_str_c || var()->type() == dods_url_c) { 01434 d_str.resize(sz); 01435 _capacity = sz; 01436 for (register int t = 0; t < sz; t++) { 01437 d_str[t] = val[t] ; 01438 } 01439 set_length(sz) ; 01440 set_read_p(true); 01441 return true; 01442 } 01443 else { 01444 return false; 01445 } 01446 } 01448 01450 01457 void Vector::value(dods_byte *b) const 01458 { 01459 if (b && _var->type() == dods_byte_c) { 01460 memcpy(b, _buf, length() * sizeof(dods_byte)); 01461 } 01462 } 01463 01465 void Vector::value(dods_uint16 *b) const 01466 { 01467 if (b && _var->type() == dods_uint16_c) { 01468 memcpy(b, _buf, length() * sizeof(dods_uint16)); 01469 } 01470 } 01471 01473 void Vector::value(dods_int16 *b) const 01474 { 01475 if (b && _var->type() == dods_int16_c) { 01476 memcpy(b, _buf, length() * sizeof(dods_int16)); 01477 } 01478 } 01479 01481 void Vector::value(dods_uint32 *b) const 01482 { 01483 if (b && _var->type() == dods_uint32_c) { 01484 memcpy(b, _buf, length() * sizeof(dods_uint32)); 01485 } 01486 } 01487 01489 void Vector::value(dods_int32 *b) const 01490 { 01491 if (b && _var->type() == dods_int32_c) { 01492 memcpy(b, _buf, length() * sizeof(dods_int32)); 01493 } 01494 } 01495 01497 void Vector::value(dods_float32 *b) const 01498 { 01499 if (b && _var->type() == dods_float32_c) { 01500 memcpy(b, _buf, length() * sizeof(dods_float32)); 01501 } 01502 } 01503 01505 void Vector::value(dods_float64 *b) const 01506 { 01507 if (b && _var->type() == dods_float64_c) { 01508 memcpy(b, _buf, length() * sizeof(dods_float64)); 01509 } 01510 } 01511 01513 void Vector::value(vector<string> &b) const 01514 { 01515 if (_var->type() == dods_byte_c || _var->type() == dods_url_c) 01516 b = d_str; 01517 } 01518 01521 void *Vector::value() 01522 { 01523 void *buffer = new char[width()]; 01524 01525 memcpy(buffer, _buf, width()); 01526 01527 return buffer; 01528 } 01530 01543 void Vector::add_var(BaseType * v, Part) 01544 { 01545 // Delete the current template variable 01546 if( _var ) 01547 { 01548 delete _var; 01549 _var = 0 ; 01550 } 01551 01552 // if 'v' is null, just set _var to null and exit. 01553 if (!v) { 01554 _var = 0; 01555 } 01556 else { 01557 // Jose Garcia 01558 // By getting a copy of this object to be assigned to _var 01559 // we let the owner of 'v' to deallocate it as necessary. 01560 _var = v->ptr_duplicate(); 01561 01562 // If 'v' has a name, use it as the name of the array. If it *is* 01563 // empty, then make sure to copy the array's name to the template 01564 // so that software which uses the template's name will still work. 01565 if (!v->name().empty()) 01566 set_name(v->name()); 01567 else 01568 _var->set_name(name()); 01569 01570 _var->set_parent(this); // Vector --> child 01571 01572 DBG(cerr << "Vector::add_var: Added variable " << v << " (" 01573 << v->name() << " " << v->type_name() << ")" << endl); 01574 } 01575 } 01576 01577 bool Vector::check_semantics(string & msg, bool) 01578 { 01579 return BaseType::check_semantics(msg); 01580 } 01581 01590 void 01591 Vector::dump(ostream &strm) const 01592 { 01593 strm << DapIndent::LMarg << "Vector::dump - (" 01594 << (void *)this << ")" << endl ; 01595 DapIndent::Indent() ; 01596 BaseType::dump(strm) ; 01597 strm << DapIndent::LMarg << "# elements in vector: " << _length << endl ; 01598 if (_var) { 01599 strm << DapIndent::LMarg << "base type:" << endl ; 01600 DapIndent::Indent() ; 01601 _var->dump(strm) ; 01602 DapIndent::UnIndent() ; 01603 } 01604 else { 01605 strm << DapIndent::LMarg << "base type: not set" << endl ; 01606 } 01607 strm << DapIndent::LMarg << "vector contents:" << endl ; 01608 DapIndent::Indent() ; 01609 for (unsigned i = 0; i < _vec.size(); ++i) { 01610 if (_vec[i]) 01611 _vec[i]->dump(strm) ; 01612 else 01613 strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl ; 01614 } 01615 DapIndent::UnIndent() ; 01616 strm << DapIndent::LMarg << "strings:" << endl ; 01617 DapIndent::Indent() ; 01618 for (unsigned i = 0; i < d_str.size(); i++) { 01619 strm << DapIndent::LMarg << d_str[i] << endl ; 01620 } 01621 DapIndent::UnIndent() ; 01622 if( _buf ) 01623 { 01624 switch( _var->type() ) 01625 { 01626 case dods_byte_c: 01627 { 01628 strm << DapIndent::LMarg << "_buf: " ; 01629 strm.write( _buf, _length ) ; 01630 strm << endl ; 01631 } 01632 break ; 01633 default: 01634 { 01635 strm << DapIndent::LMarg << "_buf: " << (void *)_buf << endl ; 01636 } 01637 break ; 01638 } 01639 } 01640 else 01641 { 01642 strm << DapIndent::LMarg << "_buf: EMPTY" << endl ; 01643 } 01644 DapIndent::UnIndent() ; 01645 } 01646 01647 } // namespace libdap 01648