1 // -*- mode: c++; c-basic-offset:4 -*- 2 3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 4 // Access Protocol. 5 6 // Copyright (c) 2013 OPeNDAP, Inc. 7 // Author: James Gallagher <jgallagher@opendap.org> 8 // 9 // This library is free software; you can redistribute it and/or 10 // modify it under the terms of the GNU Lesser General Public 11 // License as published by the Free Software Foundation; either 12 // version 2.1 of the License, or (at your option) any later version. 13 // 14 // This library is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 // Lesser General Public License for more details. 18 // 19 // You should have received a copy of the GNU Lesser General Public 20 // License along with this library; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 24 25 #ifndef D4DIMENSIONS_H_ 26 #define D4DIMENSIONS_H_ 27 28 #include <string> 29 #include <vector> 30 31 // #include "XMLWriter.h" 32 33 using namespace std; 34 35 namespace libdap { 36 37 class D4Group; 38 class D4Dimensions; 39 class XMLWriter; 40 41 class D4Dimension { 42 string d_name; 43 unsigned long long d_size; 44 45 D4Dimensions *d_parent; // This is used to get the Dimensions and then the Group object 46 47 bool d_constrained; 48 unsigned long long d_c_start, d_c_stride, d_c_stop; 49 50 bool d_used_by_projected_var; 51 52 public: D4Dimension()53 D4Dimension() : d_name(""), d_size(0), d_parent(0), d_constrained(false), d_c_start(0), d_c_stride(0), 54 d_c_stop(0), d_used_by_projected_var(false) {} d_name(name)55 D4Dimension(const string &name, unsigned long long size, D4Dimensions *d = 0) : d_name(name), d_size(size), d_parent(d), 56 d_constrained(false), d_c_start(0), d_c_stride(0), d_c_stop(0), d_used_by_projected_var(false) {} 57 name()58 string name() const {return d_name;} set_name(const string & name)59 void set_name(const string &name) { d_name = name; } 60 string fully_qualified_name() const; 61 size()62 unsigned long long size() const { return d_size; } set_size(unsigned long long size)63 void set_size(unsigned long long size) { d_size = size; } 64 // Because we build these in the XML parser and it's all text... 65 void set_size(const string &size); 66 parent()67 D4Dimensions *parent() const { return d_parent; } set_parent(D4Dimensions * d)68 void set_parent(D4Dimensions *d) { d_parent = d; } 69 constrained()70 bool constrained() const { return d_constrained; } c_start()71 unsigned long long c_start() const { return d_c_start; } c_stride()72 unsigned long long c_stride() const { return d_c_stride; } c_stop()73 unsigned long long c_stop() const { return d_c_stop; } 74 used_by_projected_var()75 bool used_by_projected_var() const { return d_used_by_projected_var; } set_used_by_projected_var(bool state)76 void set_used_by_projected_var(bool state) { d_used_by_projected_var = state; } 77 78 /** 79 * Set this Shared Diemension's constraint. While an Array Dimension object uses a 80 * stop value of -1 to indicate the end of the dimension, this method does not support 81 * that; the caller will have to sort out the correct end value for 'stop'. 82 * @param start Starting index (zero-based) 83 * @param stride The stride for the slice 84 * @param stop The stopping index (never greater than size -1) 85 */ set_constraint(unsigned long long start,unsigned long long stride,unsigned long long stop)86 void set_constraint(unsigned long long start, unsigned long long stride, unsigned long long stop) { 87 d_c_start = start; 88 d_c_stride = stride; 89 d_c_stop = stop; 90 d_constrained = true; 91 } 92 93 void print_dap4(XMLWriter &xml) const; 94 }; 95 96 /** 97 * This class holds information about dimensions. This can be used to store 98 * actual dimension information in an instance of BaseType and it can be 99 * used to store the definition of a dimension in an instance of Group. 100 */ 101 class D4Dimensions { 102 vector<D4Dimension*> d_dims; 103 104 D4Group *d_parent; // the group that holds this set of D4Dimensions; weak pointer, don't delete 105 106 protected: 107 // Note Code in Array depends on the order of these 'new' dimensions 108 // matching the 'old' dimensions they are derived from. See 109 // Array::update_dimension_pointers. jhrg 8/25/14 m_duplicate(const D4Dimensions & rhs)110 void m_duplicate(const D4Dimensions &rhs) { 111 D4DimensionsCIter i = rhs.d_dims.begin(); 112 while (i != rhs.d_dims.end()) { 113 d_dims.push_back(new D4Dimension(**i++)); // deep copy 114 d_dims.back()->set_parent(this); // Set the Dimension's parent 115 } 116 117 d_parent = rhs.d_parent; 118 } 119 120 public: 121 /// Iterator used for D4Dimensions 122 typedef vector<D4Dimension*>::iterator D4DimensionsIter; 123 typedef vector<D4Dimension*>::const_iterator D4DimensionsCIter; 124 D4Dimensions()125 D4Dimensions() : d_parent(0) {} D4Dimensions(D4Group * g)126 D4Dimensions(D4Group *g) : d_parent(g) {} D4Dimensions(const D4Dimensions & rhs)127 D4Dimensions(const D4Dimensions &rhs) : d_parent(0) { m_duplicate(rhs); } 128 ~D4Dimensions()129 virtual ~D4Dimensions() { 130 D4DimensionsIter i = d_dims.begin(); 131 while (i != d_dims.end()) 132 delete *i++; 133 } 134 135 D4Dimensions &operator=(const D4Dimensions &rhs) { 136 if (this == &rhs) return *this; 137 m_duplicate(rhs); 138 return *this; 139 } 140 141 /// Does this D4Dimensions object actually have dimensions? empty()142 bool empty() const { return d_dims.empty(); } 143 parent()144 D4Group *parent() const { return d_parent;} set_parent(D4Group * g)145 void set_parent(D4Group *g) { d_parent = g; } 146 147 /** Append a new dimension. 148 * In DAP4 dimensions are either of a known size or are varying. For 149 * fixed-size dimensions, the value of varying should be false. For varying 150 * dimensions the value of 'size' will be ignored - any value can be used 151 * when called this method. 152 * 153 * @param dim Pointer to the D4Dimension object to add; deep copy 154 */ add_dim(D4Dimension * dim)155 void add_dim(D4Dimension *dim) { add_dim_nocopy(new D4Dimension(*dim)); } 156 157 /** Append a new dimension. 158 * @param dim Pointer to the D4Dimension object to add; copies the pointer 159 */ add_dim_nocopy(D4Dimension * dim)160 void add_dim_nocopy(D4Dimension *dim) { dim->set_parent(this); d_dims.push_back(dim); } 161 162 /// Get an iterator to the start of the dimensions dim_begin()163 D4DimensionsIter dim_begin() { return d_dims.begin(); } 164 165 /// Get an iterator to the end of the dimensions dim_end()166 D4DimensionsIter dim_end() { return d_dims.end(); } 167 168 D4Dimension *find_dim(const string &name); 169 170 /** Insert a dimension. 171 * Insert a dimension before the position specified by the iterator. 172 * @note Calling this method invalidates all iterators that reference this 173 * D4Dimension object. 174 * @param dim Inserted before i; deep copy 175 * @param i iterator 176 */ insert_dim(D4Dimension * dim,D4DimensionsIter i)177 void insert_dim(D4Dimension *dim, D4DimensionsIter i) { 178 insert_dim_nocopy(new D4Dimension(*dim), i); 179 } 180 181 /** Insert a dimension. 182 * @param dim Inserted before i; pointer copy 183 * @param i iterator 184 */ insert_dim_nocopy(D4Dimension * dim,D4DimensionsIter i)185 void insert_dim_nocopy(D4Dimension *dim, D4DimensionsIter i) { 186 dim->set_parent(this); 187 d_dims.insert(i, dim); 188 } 189 190 void print_dap4(XMLWriter &xml, bool constrained = false) const; 191 }; 192 193 } /* namespace libdap */ 194 #endif /* D4DIMENSIONS_H_ */ 195