OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
AsciiArray.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of asciival, software which can return an ASCII
5 // representation of the data read from a DAP server.
6 
7 // Copyright (c) 2002,2003 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 // (c) COPYRIGHT URI/MIT 1998,2000
27 // Please read the full copyright statement in the file COPYRIGHT_URI.
28 //
29 // Authors:
30 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31 
32 // Implementation for AsciiArray. See AsciiByte.cc
33 //
34 // 3/12/98 jhrg
35 
36 #include "config.h"
37 
38 #include <iostream>
39 #include <string>
40 #include <algorithm>
41 
42 using namespace std;
43 
44 // #define DODS_DEBUG
45 
46 #include "InternalErr.h"
47 #include "debug.h"
48 
49 #include "AsciiArray.h"
50 #include "util.h"
51 #include "get_ascii.h"
52 
53 using namespace dap_asciival;
54 
55 BaseType *
57 {
58  return new AsciiArray(*this);
59 }
60 
61 AsciiArray::AsciiArray(const string &n, BaseType *v) : Array(n, v)
62 {
63 }
64 
66  : Array(bt->name(), 0), AsciiOutput( bt )
67 {
68  // By calling var() without any parameters we get back the template
69  // itself, then we can add it to this Array as the template. By doing
70  // this we set the parent as well, which is what we need.
71  BaseType *abt = basetype_to_asciitype( bt->var() ) ;
72  add_var( abt ) ;
73  // add_var makes a copy of the base type passed, so delete the original
74  delete abt ;
75 
76  // Copy the dimensions
77  Dim_iter p = bt->dim_begin();
78  while ( p != bt->dim_end() ) {
79  append_dim(bt->dimension_size(p, true), bt->dimension_name(p));
80  ++p;
81  }
82 
83  // I'm not particularly happy with this constructor; we should be able to
84  // use the libdap ctors like BaseType::BaseType(const BaseType &copy_from)
85  // using that via the Array copy ctor won't let us use the
86  // basetype_to_asciitype() factory class. jhrg 5/19/09
87  set_send_p(bt->send_p());
88 }
89 
91 {
92 }
93 
94 void AsciiArray::print_ascii(ostream &strm, bool print_name) throw(InternalErr)
95 {
96  Array *bt = dynamic_cast < Array * >(_redirect);
97  if (!bt) {
98  bt = this;
99  }
100 
101  if (bt->var()->is_simple_type()) {
102  if (/*bt->*/dimensions(true) > 1) {
103  print_array(strm, print_name);
104  } else {
105  print_vector(strm, print_name);
106  }
107  } else {
108  print_complex_array(strm, print_name);
109  }
110 }
111 
112 // Print out a values for a vector (one dimensional array) of simple types.
113 void AsciiArray::print_vector(ostream &strm, bool print_name)
114 {
115  Array *bt = dynamic_cast < Array * >(_redirect);
116  if (!bt) {
117  bt = this;
118  }
119 
120  if (print_name)
121  strm << dynamic_cast<AsciiOutput*>(this)->get_full_name() << ", " ;
122 
123  // only one dimension
124  int end = /*bt->*/dimension_size(/*bt->*/dim_begin(), true) - 1;
125 
126  for (int i = 0; i < end; ++i) {
127  BaseType *curr_var = basetype_to_asciitype(bt->var(i));
128  dynamic_cast < AsciiOutput & >(*curr_var).print_ascii(strm, false);
129  strm << ", ";
130  // we're not saving curr_var for future use, so delete it here
131  delete curr_var;
132  }
133  BaseType *curr_var = basetype_to_asciitype(bt->var(end));
134  dynamic_cast < AsciiOutput & >(*curr_var).print_ascii(strm, false);
135  // we're not saving curr_var for future use, so delete it here
136  delete curr_var;
137 }
138 
150 int AsciiArray::print_row(ostream &strm, int index, int number)
151 {
152  Array *bt = dynamic_cast < Array * >(_redirect);
153  if (!bt) {
154  bt = this;
155  }
156 
157 #if 0
158  // basetype_to_asciitype() returns a copy
159  AsciiArray *abt = dynamic_cast<AsciiArray*>(basetype_to_asciitype( bt ));
160  for (int i = 0; i < number; ++i) {
161  dynamic_cast<AsciiOutput*>(abt->var(index++))->print_ascii(strm, false);
162  }
163  dynamic_cast<AsciiOutput*>(abt->var(index++))->print_ascii(strm, false);
164 
165  delete abt;
166 #else
167  for (int i = 0; i < number; ++i) {
168  BaseType *curr_var = basetype_to_asciitype(bt->var(index++));
169  dynamic_cast < AsciiOutput & >(*curr_var).print_ascii(strm, false);
170  strm << ", " ;
171  // we're not saving curr_var for future use, so delete it here
172  delete curr_var;
173  }
174  BaseType *curr_var = basetype_to_asciitype(bt->var(index++));
175  dynamic_cast < AsciiOutput & >(*curr_var).print_ascii(strm, false);
176  // we're not saving curr_var for future use, so delete it here
177  delete curr_var;
178 #endif
179 
180  return index;
181 }
182 
183 // Given a vector of indices, return the corresponding index.
184 
185 int AsciiArray::get_index(vector < int >indices) throw(InternalErr)
186 {
187  if (indices.size() != /*bt->*/dimensions(true)) {
188  throw InternalErr(__FILE__, __LINE__,
189  "Index vector is the wrong size!");
190  }
191  // suppose shape is [3][4][5][6] for x,y,z,t. The index is
192  // t + z(6) + y(5 * 6) + x(4 * 5 *6).
193  // Assume that indices[0] holds x, indices[1] holds y, ...
194 
195  // It's hard to work with Pixes
196  vector < int >shape = get_shape_vector(indices.size());
197 
198  // We want to work from the rightmost index to the left
199  reverse(indices.begin(), indices.end());
200  reverse(shape.begin(), shape.end());
201 
202  vector < int >::iterator indices_iter = indices.begin();
203  vector < int >::iterator shape_iter = shape.begin();
204 
205  int index = *indices_iter++; // in the ex. above, this adds `t'
206  int multiplier = 1;
207  while (indices_iter != indices.end()) {
208  multiplier *= *shape_iter++;
209  index += multiplier * *indices_iter++;
210  }
211 
212  return index;
213 }
214 
215 // get_shape_vector and get_nth_dim_size are public because that are called
216 // from Grid. 9/14/2001 jhrg
217 
218 vector < int > AsciiArray::get_shape_vector(size_t n) throw(InternalErr)
219 {
220  if (n < 1 || n > dimensions(true)) {
221  string msg = "Attempt to get ";
222  msg += long_to_string(n) + " dimensions from " + name()
223  + " which has only " + long_to_string(dimensions(true))
224  + "dimensions.";
225 
226  throw InternalErr(__FILE__, __LINE__, msg);
227  }
228 
229  vector < int >shape;
230  Array::Dim_iter p = dim_begin();
231  for (unsigned i = 0; i < n && p != dim_end(); ++i, ++p) {
232  shape.push_back(dimension_size(p, true));
233  }
234 
235  return shape;
236 }
237 
241 int AsciiArray::get_nth_dim_size(size_t n) throw(InternalErr)
242 {
243  if (n > /*bt->*/dimensions(true) - 1) {
244  string msg = "Attempt to get dimension ";
245  msg +=
246  long_to_string(n + 1) + " from `" + /*bt->*/name() +
247  "' which has " + long_to_string(/*bt->*/dimensions(true)) +
248  " dimension(s).";
249  throw InternalErr(__FILE__, __LINE__, msg);
250  }
251 
252  return /*bt->*/dimension_size(/*bt->*/dim_begin() + n, true);
253 }
254 
255 void AsciiArray::print_array(ostream &strm, bool /*print_name */ )
256 {
257  DBG(cerr << "Entering AsciiArray::print_array" << endl);
258 
259  int dims = /*bt->*/dimensions(true);
260  if (dims <= 1)
261  throw InternalErr(__FILE__, __LINE__,
262  "Dimension count is <= 1 while printing multidimensional array.");
263 
264  // shape holds the maximum index value of all but the last dimension of
265  // the array (not the size; each value is one less that the size).
266  vector < int >shape = get_shape_vector(dims - 1);
267  int rightmost_dim_size = get_nth_dim_size(dims - 1);
268 
269  // state holds the indexes of the current row being printed. For an N-dim
270  // array, there are N-1 dims that are iterated over when printing (the
271  // Nth dim is not printed explicitly. Instead it's the number of values
272  // on the row.
273  vector < int >state(dims - 1, 0);
274 
275  bool more_indices;
276  int index = 0;
277  do {
278  // Print indices for all dimensions except the last one.
279  strm << dynamic_cast <AsciiOutput *>(this)->get_full_name() ;
280 
281  for (int i = 0; i < dims - 1; ++i) {
282  strm << "[" << state[i] << "]" ;
283  }
284  strm << ", " ;
285 
286  index = print_row(strm, index, rightmost_dim_size - 1);
287  more_indices = increment_state(&state, shape);
288  if (more_indices)
289  strm << "\n" ;
290 
291  } while (more_indices);
292 
293  DBG(cerr << "ExitingAsciiArray::print_array" << endl);
294 }
295 
296 void AsciiArray::print_complex_array(ostream &strm, bool /*print_name */ )
297 {
298  DBG(cerr << "Entering AsciiArray::print_complex_array" << endl);
299 
300  Array *bt = dynamic_cast < Array * >(_redirect);
301  if (!bt)
302  bt = this;
303 
304  int dims = /*bt->*/dimensions(true);
305  if (dims < 1)
306  throw InternalErr(__FILE__, __LINE__,
307  "Dimension count is <= 1 while printing multidimensional array.");
308 
309  // shape holds the maximum index value of all but the last dimension of
310  // the array (not the size; each value is one less that the size).
311  vector < int >shape = get_shape_vector(dims);
312 
313  vector < int >state(dims, 0);
314 
315  bool more_indices;
316  do {
317  // Print indices for all dimensions except the last one.
318  strm << dynamic_cast <AsciiOutput *>(this)->get_full_name() ;
319 
320  for (int i = 0; i < dims; ++i) {
321  strm << "[" << state[i] << "]" ;
322  }
323  strm << "\n" ;
324 
325  BaseType *curr_var =
326  basetype_to_asciitype(bt->var(get_index(state)));
327  dynamic_cast < AsciiOutput & >(*curr_var).print_ascii(strm, true);
328  // we are not saving curr_var for future reference, so delete it
329  delete curr_var;
330 
331  more_indices = increment_state(&state, shape);
332  if (more_indices)
333  strm << "\n" ;
334 
335  } while (more_indices);
336 
337  DBG(cerr << "ExitingAsciiArray::print_complex_array" << endl);
338 }
339 
bool increment_state(vector< int > *state, const vector< int > &shape)
Increment #state# to the next value given #shape#.
Definition: AsciiOutput.cc:98
BaseType * _redirect
Definition: AsciiOutput.h:52
virtual BaseType * ptr_duplicate()
Definition: AsciiArray.cc:56
STL namespace.
virtual void print_ascii(ostream &strm, bool print_name=true)
Print an ASCII representation for an instance of BaseType's children.
Definition: AsciiOutput.cc:73
virtual ~AsciiArray()
Definition: AsciiArray.cc:90
int get_index(vector< int > indices)
Definition: AsciiArray.cc:185
int get_nth_dim_size(size_t n)
Get the size of dimension #n#.
Definition: AsciiArray.cc:241
BaseType * basetype_to_asciitype(BaseType *bt)
Definition: get_ascii.cc:116
int print_row(ostream &strm, int index, int number)
Print a single row of values for a N-dimensional array.
Definition: AsciiArray.cc:150
vector< int > get_shape_vector(size_t n)
Get the sizes of the first N dimensions of this array.
Definition: AsciiArray.cc:218
virtual void print_ascii(ostream &strm, bool print_name=true)
Print an ASCII representation for an instance of BaseType's children.
Definition: AsciiArray.cc:94
string get_full_name()
Get the fully qualified name of this object.
Definition: AsciiOutput.cc:49
AsciiArray(const string &n, BaseType *v)
Definition: AsciiArray.cc:61