|
Packit |
a4aae4 |
// -*- mode: c++; c-basic-offset:4 -*-
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
|
|
Packit |
a4aae4 |
// Access Protocol.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Copyright (c) 2002,2003 OPeNDAP, Inc.
|
|
Packit |
a4aae4 |
// Author: James Gallagher <jgallagher@opendap.org>
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is free software; you can redistribute it and/or
|
|
Packit |
a4aae4 |
// modify it under the terms of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License as published by the Free Software Foundation; either
|
|
Packit |
a4aae4 |
// version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is distributed in the hope that it will be useful,
|
|
Packit |
a4aae4 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a4aae4 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
a4aae4 |
// Lesser General Public License for more details.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You should have received a copy of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License along with this library; if not, write to the Free Software
|
|
Packit |
a4aae4 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// (c) COPYRIGHT URI/MIT 1994-1999
|
|
Packit |
a4aae4 |
// Please read the full copyright statement in the file COPYRIGHT_URI.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Authors:
|
|
Packit |
a4aae4 |
// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Interface for the class Sequence. A sequence contains a single set
|
|
Packit |
a4aae4 |
// of variables, all at the same lexical level just like a structure
|
|
Packit |
a4aae4 |
// (and like a structure, it may contain other ctor types...). Unlike
|
|
Packit |
a4aae4 |
// a structure, a sequence defines a pattern that is repeated N times
|
|
Packit |
a4aae4 |
// for a sequence of N elements. Thus, Sequence { String name; Int32
|
|
Packit |
a4aae4 |
// age; } person; means a sequence of N persons where each contain a
|
|
Packit |
a4aae4 |
// name and age. The sequence can be arbitrarily long (i.e., you don't
|
|
Packit |
a4aae4 |
// know N by looking at the sequence declaration.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// jhrg 9/14/94
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifndef _sequence_h
|
|
Packit |
a4aae4 |
#define _sequence_h 1
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <stack>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "Constructor.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifndef S_XDRUtils_h
|
|
Packit |
a4aae4 |
#include "XDRUtils.h"
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
class BaseType;
|
|
Packit |
a4aae4 |
class ConstraintEvaluator;
|
|
Packit |
a4aae4 |
class D4Group;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The type BaseTypeRow is used to store single rows of values in an
|
|
Packit |
a4aae4 |
instance of Sequence. Values are stored in instances of BaseType. */
|
|
Packit |
a4aae4 |
typedef vector<BaseType *> BaseTypeRow;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This type holds all of the values of a Sequence. */
|
|
Packit |
a4aae4 |
typedef vector<BaseTypeRow *> SequenceValues;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This is the interface for the class Sequence. A sequence contains
|
|
Packit |
a4aae4 |
a single set of variables, all at the same lexical level just like
|
|
Packit |
a4aae4 |
a Structure. Like a Structure, a Sequence may contain other
|
|
Packit |
a4aae4 |
compound types, including other Sequences. Unlike a Structure, a
|
|
Packit |
a4aae4 |
Sequence defines a pattern that is repeated N times for a sequence
|
|
Packit |
a4aae4 |
of N elements. It is useful to think of a Sequence as representing
|
|
Packit |
a4aae4 |
a table of values (like a relational database), with each row of
|
|
Packit |
a4aae4 |
the table corresponding to a Sequence ``instance.'' (This usage
|
|
Packit |
a4aae4 |
can be confusing, since ``instance'' also refers to a particular
|
|
Packit |
a4aae4 |
item of class Sequence.) For example:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Sequence {
|
|
Packit |
a4aae4 |
String name;
|
|
Packit |
a4aae4 |
Int32 age;
|
|
Packit |
a4aae4 |
} person;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This represents a Sequence of ``person'' records, each instance of
|
|
Packit |
a4aae4 |
which contains a name and an age:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Fred 34
|
|
Packit |
a4aae4 |
Ralph 23
|
|
Packit |
a4aae4 |
Andrea 29
|
|
Packit |
a4aae4 |
...
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
A Sequence can be arbitrarily long, which is to say that its
|
|
Packit |
a4aae4 |
length is not part of its declaration. A Sequence can contain
|
|
Packit |
a4aae4 |
other Sequences:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Sequence {
|
|
Packit |
a4aae4 |
String name;
|
|
Packit |
a4aae4 |
Int32 age;
|
|
Packit |
a4aae4 |
Sequence {
|
|
Packit |
a4aae4 |
String friend;
|
|
Packit |
a4aae4 |
} friend_list;
|
|
Packit |
a4aae4 |
} person;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This is still represented as a single table, but each row contains
|
|
Packit |
a4aae4 |
the elements of both the main Sequence and the nested one:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Fred 34 Norman
|
|
Packit |
a4aae4 |
Fred 34 Andrea
|
|
Packit |
a4aae4 |
Fred 34 Ralph
|
|
Packit |
a4aae4 |
Fred 34 Lisa
|
|
Packit |
a4aae4 |
Ralph 23 Norman
|
|
Packit |
a4aae4 |
Ralph 23 Andrea
|
|
Packit |
a4aae4 |
Ralph 23 Lisa
|
|
Packit |
a4aae4 |
Ralph 23 Marth
|
|
Packit |
a4aae4 |
Ralph 23 Throckmorton
|
|
Packit |
a4aae4 |
Ralph 23 Helga
|
|
Packit |
a4aae4 |
Ralph 23 Millicent
|
|
Packit |
a4aae4 |
Andrea 29 Ralph
|
|
Packit |
a4aae4 |
Andrea 29 Natasha
|
|
Packit |
a4aae4 |
Andrea 29 Norman
|
|
Packit |
a4aae4 |
... .. ...
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Internally, the Sequence is represented by a vector of vectors. The
|
|
Packit |
a4aae4 |
members of the outer vector are the members of the Sequence. This
|
|
Packit |
a4aae4 |
includes the nested Sequences, as in the above example.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
NB: Note that in the past this class had a different behavior. It held
|
|
Packit |
a4aae4 |
only one row at a time and the deserialize(...) method had to be called
|
|
Packit |
a4aae4 |
from within a loop. This is no longer true. Now the
|
|
Packit |
a4aae4 |
deserailize(...) method should be called once and will read the entire
|
|
Packit |
a4aae4 |
sequence's values from the server. All the values are now stored in an
|
|
Packit |
a4aae4 |
instance of Sequence, not just a single row's.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Because the length of a Sequence is indeterminate, there are
|
|
Packit |
a4aae4 |
changes to the behavior of the functions to read this class of
|
|
Packit |
a4aae4 |
data. The <tt>read()</tt> function for Sequence must be written so that
|
|
Packit |
a4aae4 |
successive calls return values for successive rows of the Sequence.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Similar to a C structure, you refer to members of Sequence
|
|
Packit |
a4aae4 |
elements with a ``.'' notation. For example, if the Sequence has
|
|
Packit |
a4aae4 |
a member Sequence called ``Tom'' and Tom has a member Float32
|
|
Packit |
a4aae4 |
called ``shoe_size'', you can refer to Tom's shoe size as
|
|
Packit |
a4aae4 |
``Tom.shoe_size''.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note This class contains the 'logic' for both the server- and client-side
|
|
Packit |
a4aae4 |
behavior. The field \e d_values is used by the client-side methods to store
|
|
Packit |
a4aae4 |
the entire Sequence. On the server-side, the read() method uses an underlying
|
|
Packit |
a4aae4 |
data system to read one row of data values which are then serialized using the
|
|
Packit |
a4aae4 |
serialize() methods of each variable.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@todo Add an isEmpty() method which returns true if the Sequence is
|
|
Packit |
a4aae4 |
empty. This should work before and after calling deserialize().
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Holds a sequence. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
class Sequence: public Constructor
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
private:
|
|
Packit |
a4aae4 |
// This holds the values read off the wire. Values are stored in
|
|
Packit |
a4aae4 |
// instances of BaseTypeRow objects which hold instances of BaseType.
|
|
Packit |
a4aae4 |
SequenceValues d_values;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// The number of the row that has just been deserialized. Before
|
|
Packit |
a4aae4 |
// deserialized has been called, this field is -1.
|
|
Packit |
a4aae4 |
int d_row_number;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If a client asks for certain rows of a sequence using the bracket
|
|
Packit |
a4aae4 |
// notation (<tt>[<start>:<stride>:<stop>]</tt>) primarily intended for
|
|
Packit |
a4aae4 |
// arrays
|
|
Packit |
a4aae4 |
// and grids, record that information in the next three fields. This
|
|
Packit |
a4aae4 |
// information can be used by the translation software. s.a. the accessor
|
|
Packit |
a4aae4 |
// and mutator methods for these members. Values of -1 indicate that
|
|
Packit |
a4aae4 |
// these have not yet been set.
|
|
Packit |
a4aae4 |
int d_starting_row_number;
|
|
Packit |
a4aae4 |
int d_row_stride;
|
|
Packit |
a4aae4 |
int d_ending_row_number;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Used to track if data has not already been sent.
|
|
Packit |
a4aae4 |
bool d_unsent_data;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Track if the Start Of Instance marker has been written. Needed to
|
|
Packit |
a4aae4 |
// properly send EOS for only the outer Sequence when a selection
|
|
Packit |
a4aae4 |
// returns an empty Sequence.
|
|
Packit |
a4aae4 |
bool d_wrote_soi;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This signals whether the sequence is a leaf or parent.
|
|
Packit |
a4aae4 |
bool d_leaf_sequence;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// In a hierarchy of sequences, is this the top most?
|
|
Packit |
a4aae4 |
bool d_top_most;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool is_end_of_rows(int i);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
friend class SequenceTest;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
protected:
|
|
Packit |
a4aae4 |
void m_duplicate(const Sequence &s);
|
|
Packit |
a4aae4 |
typedef stack<SequenceValues*> sequence_values_stack_t;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual bool serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m);
|
|
Packit |
a4aae4 |
virtual void serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m);
|
|
Packit |
a4aae4 |
virtual bool serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void intern_data_private(ConstraintEvaluator &eval, DDS &dds,
|
|
Packit |
a4aae4 |
sequence_values_stack_t &sequence_values_stack);
|
|
Packit |
a4aae4 |
virtual void intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval,
|
|
Packit |
a4aae4 |
sequence_values_stack_t &sequence_values_stack);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void intern_data_parent_part_one(DDS &dds, ConstraintEvaluator &eval,
|
|
Packit |
a4aae4 |
sequence_values_stack_t &sequence_values_stack);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval,
|
|
Packit |
a4aae4 |
sequence_values_stack_t &sequence_values_stack);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
public:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Sequence(const string &n);
|
|
Packit |
a4aae4 |
Sequence(const string &n, const string &d);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Sequence(const Sequence &rhs;;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual ~Sequence();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Sequence &operator=(const Sequence &rhs;;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual BaseType *ptr_duplicate();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void clear_local_data();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void transform_to_dap4(D4Group *root, Constructor *container);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual bool is_dap2_only_type();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual string toString();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual bool is_linear();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual int length() const;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual int number_of_rows() const;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual bool read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval = true);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void intern_data(ConstraintEvaluator &eval, DDS &dds;;
|
|
Packit |
a4aae4 |
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval = true);
|
|
Packit |
a4aae4 |
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse = false);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/// Rest the row number counter
|
|
Packit |
a4aae4 |
void reset_row_number();
|
|
Packit |
a4aae4 |
// I added a second method instead of a param with a default value because I think
|
|
Packit |
a4aae4 |
// this will result only in an addition to the ABI/API, not a change. 5/16/15 jhrg
|
|
Packit |
a4aae4 |
void reset_row_number(bool recur);
|
|
Packit |
a4aae4 |
void increment_row_number(unsigned int i) { d_row_number += i; }
|
|
Packit |
a4aae4 |
int get_row_number() const { return d_row_number; }
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int get_starting_row_number();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual int get_row_stride();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual int get_ending_row_number();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void set_row_number_constraint(int start, int stop, int stride = 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/// Get the unsent data property
|
|
Packit |
a4aae4 |
bool get_unsent_data() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_unsent_data;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/// Set the unsent data property
|
|
Packit |
a4aae4 |
void set_unsent_data(bool usd)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_unsent_data = usd;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void set_value(SequenceValues &values);
|
|
Packit |
a4aae4 |
virtual SequenceValues value();
|
|
Packit |
a4aae4 |
virtual SequenceValues &value_ref();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual BaseType *var_value(size_t row, const string &name);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual BaseType *var_value(size_t row, size_t i);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual BaseTypeRow *row_value(size_t row);
|
|
Packit |
a4aae4 |
virtual void print_one_row(ostream &out, int row, string space, bool print_row_num = false);
|
|
Packit |
a4aae4 |
virtual void print_val_by_rows(ostream &out, string space = "", bool print_decl_p = true, bool print_row_numbers =
|
|
Packit |
a4aae4 |
true);
|
|
Packit |
a4aae4 |
virtual void print_val(ostream &out, string space = "", bool print_decl_p = true);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void print_one_row(FILE *out, int row, string space, bool print_row_num = false);
|
|
Packit |
a4aae4 |
virtual void print_val_by_rows(FILE *out, string space = "", bool print_decl_p = true,
|
|
Packit |
a4aae4 |
bool print_row_numbers = true);
|
|
Packit |
a4aae4 |
virtual void print_val(FILE *out, string space = "", bool print_decl_p = true);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void set_leaf_p(bool state);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual bool is_leaf_sequence();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void set_leaf_sequence(int lvl = 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
virtual void dump(ostream &strm) const;
|
|
Packit |
a4aae4 |
};
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#endif //_sequence_h
|