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) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00024 00025 #include "config.h" 00026 00027 #include <algorithm> 00028 #include <string> 00029 #include <sstream> 00030 00031 //#define DODS_DEBUG 00032 //#define DODS_DEBUG2 00033 00034 #include "Byte.h" 00035 #include "Int16.h" 00036 #include "UInt16.h" 00037 #include "Int32.h" 00038 #include "UInt32.h" 00039 #include "Float32.h" 00040 #include "Float64.h" 00041 #include "Str.h" 00042 #include "Url.h" 00043 #include "Array.h" 00044 #include "Structure.h" 00045 #include "D4Sequence.h" 00046 00047 #include "D4StreamMarshaller.h" 00048 #include "D4StreamUnMarshaller.h" 00049 00050 #include "debug.h" 00051 #include "Error.h" 00052 #include "InternalErr.h" 00053 #include "util.h" 00054 #include "escaping.h" 00055 00056 #undef CLEAR_LOCAL_DATA 00057 00058 using namespace std; 00059 00060 namespace libdap { 00061 00062 #if 0 00063 // Keep this stuff around in case we decide to switch back to sentinels 00064 00065 static const unsigned char end_of_sequence = 0xA5;// binary pattern 1010 0101 00066 static const unsigned char start_of_instance = 0x5A;// binary pattern 0101 1010 00067 00068 static void 00069 write_end_of_sequence(Marshaller &m) 00070 { 00071 m.put_opaque( (char *)&end_of_sequence, 1 ); 00072 } 00073 00074 static void 00075 write_start_of_instance(Marshaller &m) 00076 { 00077 m.put_opaque( (char *)&start_of_instance, 1 ); 00078 } 00079 00080 static unsigned char 00081 read_marker(UnMarshaller &um) 00082 { 00083 unsigned char marker; 00084 um.get_opaque( (char *)&marker, 1 ); 00085 00086 return marker; 00087 } 00088 00089 static bool 00090 is_start_of_instance(unsigned char marker) 00091 { 00092 return (marker == start_of_instance); 00093 } 00094 00095 static bool 00096 is_end_of_sequence(unsigned char marker) 00097 { 00098 return (marker == end_of_sequence); 00099 } 00100 #endif 00101 00102 // Private member functions 00103 00104 // A reminder of these type defs 00105 // 00106 // typedef vector<BaseType *> D4SeqRow; 00107 // typedef vector<D4SeqRow *> D4SeqValues; 00108 // D4SeqValues d_values; 00109 00110 void D4Sequence::m_duplicate(const D4Sequence &s) 00111 { 00112 d_length = s.d_length; 00113 #if INDEX_SUBSETTING 00114 d_starting_row_number = s.d_starting_row_number; 00115 d_ending_row_number = s.d_ending_row_number; 00116 d_row_stride = s.d_row_stride; 00117 #endif 00118 // Deep copy for the values 00119 for (D4SeqValues::const_iterator i = s.d_values.begin(), e = s.d_values.end(); i != e; ++i) { 00120 D4SeqRow &row = **i; 00121 D4SeqRow *dest = new D4SeqRow; 00122 for (D4SeqRow::const_iterator j = row.begin(), e = row.end(); j != e; ++j) { 00123 // *j is a BaseType* 00124 dest->push_back((*j)->ptr_duplicate()); 00125 } 00126 00127 d_values.push_back(dest); 00128 } 00129 } 00130 00131 // Public member functions 00132 00141 D4Sequence::D4Sequence(const string &n) : 00142 Constructor(n, dods_sequence_c, true /* is dap4 */), d_length(0) // , d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(-1) 00143 { 00144 } 00145 00156 D4Sequence::D4Sequence(const string &n, const string &d) : 00157 Constructor(n, d, dods_sequence_c, true /* is dap4 */), d_length(0) //, d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(-1) 00158 { 00159 } 00160 00162 D4Sequence::D4Sequence(const D4Sequence &rhs) : 00163 Constructor(rhs) 00164 { 00165 m_duplicate(rhs); 00166 } 00167 00168 BaseType * 00169 D4Sequence::ptr_duplicate() 00170 { 00171 return new D4Sequence(*this); 00172 } 00173 00174 static inline void delete_bt(BaseType *bt_ptr) 00175 { 00176 delete bt_ptr; 00177 } 00178 00179 static inline void delete_rows(D4SeqRow *bt_row_ptr) 00180 { 00181 for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt); 00182 00183 delete bt_row_ptr; 00184 } 00185 00186 D4Sequence::~D4Sequence() 00187 { 00188 clear_local_data(); 00189 } 00190 00191 void D4Sequence::clear_local_data() 00192 { 00193 if (!d_values.empty()) { 00194 for_each(d_values.begin(), d_values.end(), delete_rows); 00195 d_values.resize(0); 00196 } 00197 00198 set_read_p(false); 00199 } 00200 00201 D4Sequence & 00202 D4Sequence::operator=(const D4Sequence &rhs) 00203 { 00204 if (this == &rhs) return *this; 00205 00206 dynamic_cast<Constructor &>(*this) = rhs; // run Constructor= 00207 00208 m_duplicate(rhs); 00209 00210 return *this; 00211 } 00212 00236 bool D4Sequence::read_next_instance(/*DMR &dmr, ConstraintEvaluator &eval,*/bool filter) 00237 { 00238 bool eof = false; 00239 bool done = false; 00240 00241 do { 00242 eof = read(); 00243 // Advance the row number if ce_eval is false (we're not supposed to 00244 // evaluate the selection) or both filter and the selection are 00245 // true. 00246 // FIXME CE's not supported for DAP4 yet. jhrg 10/11/13 00247 filter = false; 00248 if (!eof && (!filter /*|| eval.eval_selection(dmr, dataset()*/)) { 00249 d_length++; 00250 done = true; 00251 } 00252 } while (!eof && !done); 00253 00254 DBG(cerr << "D4Sequence::read_next_instance eof: " << eof << endl); 00255 return !eof; 00256 } 00257 00258 #if 0 00259 // Used the version in Constructor, which throws an exception because we should 00260 // not compute these for constructor types. In the case of Sequence, it requires 00261 // that the values all get read. 00269 void 00270 D4Sequence::compute_checksum(Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval) 00271 { 00272 // Read the data values, then serialize. 00273 while (read_next_instance(dmr, eval, true)) { 00274 for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) { 00275 if ((*i)->send_p()) { 00276 (*i)->compute_checksum(checksum); 00277 } 00278 } 00279 } 00280 } 00281 #endif 00282 00283 void D4Sequence::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/) 00284 { 00285 // Read the data values, then serialize. 00286 while (read_next_instance(/*dmr, eval,*/true /*filter*/)) { 00287 D4SeqRow *row = new D4SeqRow; 00288 for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) { 00289 if ((*i)->send_p()) { 00290 // store the variable's value. 00291 row->push_back((*i)->ptr_duplicate()); 00292 // the copy should have read_p true to prevent the serialize() call 00293 // below in the nested for loops from triggering a second call to 00294 // read(). 00295 row->back()->set_read_p(true); 00296 #if 0 00297 // Do not compute the checksum for constructor types; those 00298 // types will compute the checksum on the values they contain. 00299 // TODO Check on this 00300 if (!row->back()->is_constructor_type()) row->back()->compute_checksum(checksum); 00301 #endif 00302 } 00303 } 00304 d_values.push_back(row); 00305 } 00306 } 00307 00327 void D4Sequence::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter) 00328 { 00329 // Read the data values, then serialize. NB: read_next_instance sets d_length. 00330 while (read_next_instance(filter)) { 00331 D4SeqRow *row = new D4SeqRow; 00332 for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) { 00333 if ((*i)->send_p()) { 00334 // store the variable's value. 00335 row->push_back((*i)->ptr_duplicate()); 00336 // the copy should have read_p true to prevent the serialize() call 00337 // below in the nested for loops from triggering a second call to 00338 // read(). 00339 row->back()->set_read_p(true); 00340 } 00341 } 00342 d_values.push_back(row); 00343 DBG(cerr << "D4Sequence::serialize Added row" << endl); 00344 } 00345 00346 // write D4Sequecne::length(); don't include the length in the checksum 00347 m.put_count(d_length); 00348 DBG(cerr << "D4Sequence::serialize count: " << d_length << endl); 00349 00350 // By this point the d_values object holds all and only the values to be sent; 00351 // use the serialize methods to send them (but no need to test send_p). 00352 for (D4SeqValues::iterator i = d_values.begin(), e = d_values.end(); i != e; ++i) { 00353 for (D4SeqRow::iterator j = (*i)->begin(), f = (*i)->end(); j != f; ++j) { 00354 (*j)->serialize(m, dmr, /*eval,*/false); 00355 } 00356 } 00357 00358 #ifdef CLEAR_LOCAL_DATA 00359 clear_local_data(); 00360 #endif 00361 00362 } 00363 00364 #if 0 00365 void D4Sequence::serialize_no_release(D4StreamMarshaller &m, DMR &dmr, bool filter) 00366 { 00367 // Read the data values, then serialize. NB: read_next_instance sets d_length. 00368 while (read_next_instance(filter)) { 00369 D4SeqRow *row = new D4SeqRow; 00370 for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) { 00371 if ((*i)->send_p()) { 00372 // store the variable's value. 00373 row->push_back((*i)->ptr_duplicate()); 00374 // the copy should have read_p true to prevent the serialize() call 00375 // below in the nested for loops from triggering a second call to 00376 // read(). 00377 row->back()->set_read_p(true); 00378 } 00379 } 00380 d_values.push_back(row); 00381 DBG(cerr << "D4Sequence::serialize Added row" << endl); 00382 } 00383 00384 // write D4Sequecne::length(); don't include the length in the checksum 00385 m.put_count(d_length); 00386 DBG(cerr << "D4Sequence::serialize count: " << d_length << endl); 00387 00388 // By this point the d_values object holds all and only the values to be sent; 00389 // use the serialize methods to send them (but no need to test send_p). 00390 for (D4SeqValues::iterator i = d_values.begin(), e = d_values.end(); i != e; ++i) { 00391 for (D4SeqRow::iterator j = (*i)->begin(), f = (*i)->end(); j != f; ++j) { 00392 (*j)->serialize(m, dmr, /*eval,*/false); 00393 } 00394 } 00395 } 00396 #endif 00397 00398 void D4Sequence::deserialize(D4StreamUnMarshaller &um, DMR &dmr) 00399 { 00400 set_length(um.get_count()); 00401 DBG(cerr << "D4Sequence::deserialize count: " << d_length << endl); 00402 00403 for (int64_t i = 0; i < d_length; ++i) { 00404 D4SeqRow *row = new D4SeqRow; 00405 for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; ++i) { 00406 (*i)->deserialize(um, dmr); 00407 row->push_back((*i)->ptr_duplicate()); 00408 } 00409 d_values.push_back(row); 00410 } 00411 } 00412 00413 #if INDEX_SUBSETTING 00414 00422 virtual void set_row_number_constraint(int start, int stop, int stride) 00423 { 00424 if (stop < start) 00425 throw Error(malformed_expr, "Starting row number must precede the ending row number."); 00426 00427 d_starting_row_number = start; 00428 d_row_stride = stride; 00429 d_ending_row_number = stop; 00430 } 00431 #endif 00432 00437 D4SeqRow * 00438 D4Sequence::row_value(size_t row) 00439 { 00440 if (row >= d_values.size()) return 0; 00441 return d_values[row]; 00442 } 00443 00444 static bool base_type_name_eq(BaseType *btp, const string name) 00445 { 00446 return btp->name() == name; 00447 } 00448 00454 BaseType * 00455 D4Sequence::var_value(size_t row_num, const string &name) 00456 { 00457 D4SeqRow *row = row_value(row_num); 00458 if (!row) return 0; 00459 00460 D4SeqRow::iterator elem = find_if(row->begin(), row->end(), bind2nd(ptr_fun(base_type_name_eq), name)); 00461 return (elem != row->end()) ? *elem : 0; 00462 } 00463 00469 BaseType * 00470 D4Sequence::var_value(size_t row_num, size_t i) 00471 { 00472 D4SeqRow *row = row_value(row_num); 00473 if (!row) return 0; 00474 00475 if (i >= row->size()) return 0; 00476 00477 return (*row)[i]; 00478 } 00479 00480 void D4Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num) 00481 { 00482 if (print_row_num) out << "\n" << space << row << ": "; 00483 00484 out << "{ "; 00485 00486 int elements = element_count(); 00487 int j = 0; 00488 BaseType *bt_ptr = 0; 00489 00490 // This version of print_one_row() works for both data read with 00491 // deserialize(), where each variable is assumed to have valid data, and 00492 // intern_data(), where some/many variables do not. Because of that, it's 00493 // not correct to assume that all of the elements will be printed, which 00494 // is what the old code did. 00495 00496 // Print the first value 00497 while (j < elements && !bt_ptr) { 00498 bt_ptr = var_value(row, j++); 00499 if (bt_ptr) { // data 00500 if (bt_ptr->type() == dods_sequence_c) static_cast<D4Sequence*>(bt_ptr)->print_val_by_rows(out, 00501 space + " ", false, print_row_num); 00502 else 00503 bt_ptr->print_val(out, space, false); 00504 } 00505 } 00506 00507 // Print the remaining values 00508 while (j < elements) { 00509 bt_ptr = var_value(row, j++); 00510 if (bt_ptr) { // data 00511 out << ", "; 00512 if (bt_ptr->type() == dods_sequence_c) static_cast<D4Sequence*>(bt_ptr)->print_val_by_rows(out, 00513 space + " ", false, print_row_num); 00514 else 00515 bt_ptr->print_val(out, space, false); 00516 } 00517 } 00518 00519 out << " }"; 00520 } 00521 00522 void D4Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers) 00523 { 00524 if (print_decl_p) { 00525 print_decl(out, space, false); 00526 out << " = "; 00527 } 00528 00529 out << "{ "; 00530 00531 if (length() != 0) { 00532 int rows = length() - 1; // -1 because the last row is treated specially 00533 for (int i = 0; i < rows; ++i) { 00534 print_one_row(out, i, space, print_row_numbers); 00535 out << ", "; 00536 } 00537 print_one_row(out, rows, space, print_row_numbers); 00538 } 00539 00540 out << " }"; 00541 00542 if (print_decl_p) out << ";\n"; 00543 } 00544 00545 void D4Sequence::print_val(ostream &out, string space, bool print_decl_p) 00546 { 00547 print_val_by_rows(out, space, print_decl_p, false); 00548 } 00549 00558 void D4Sequence::dump(ostream &strm) const 00559 { 00560 strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl; 00561 DapIndent::Indent(); 00562 Constructor::dump(strm); 00563 strm << DapIndent::LMarg << "# rows deserialized: " << d_length << endl; 00564 strm << DapIndent::LMarg << "bracket notation information:" << endl; 00565 00566 DapIndent::Indent(); 00567 #if INDEX_SUBSETTING 00568 strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl; 00569 strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl; 00570 strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl; 00571 #endif 00572 DapIndent::UnIndent(); 00573 00574 DapIndent::UnIndent(); 00575 } 00576 00577 } // namespace libdap 00578