libdap  Updated for version 3.17.0
D4Sequence.cc
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