bes  Updated for version 3.20.6
AsciiArray.cc
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 *
56 AsciiArray::ptr_duplicate()
57 {
58  return new AsciiArray(*this);
59 }
60 
61 AsciiArray::AsciiArray(const string &n, BaseType *v) : Array(n, v)
62 {
63 }
64 
65 AsciiArray::AsciiArray( Array *bt )
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 
90 AsciiArray::~AsciiArray()
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  // Added the 'if (dimension_size...' in support of zero-length arrays.
125  // jhrg 2/2/16
126  if (dimension_size(dim_begin(), true) > 0) {
127  int end = /*bt->*/dimension_size(/*bt->*/dim_begin(), true) - 1;
128 
129  for (int i = 0; i < end; ++i) {
130  BaseType *curr_var = basetype_to_asciitype(bt->var(i));
131  dynamic_cast<AsciiOutput &>(*curr_var).print_ascii(strm, false);
132  strm << ", ";
133  // we're not saving curr_var for future use, so delete it here
134  delete curr_var;
135  }
136  BaseType *curr_var = basetype_to_asciitype(bt->var(end));
137  dynamic_cast<AsciiOutput &>(*curr_var).print_ascii(strm, false);
138  // we're not saving curr_var for future use, so delete it here
139  delete curr_var;
140  }
141 }
142 
154 int AsciiArray::print_row(ostream &strm, int index, int number)
155 {
156  Array *bt = dynamic_cast < Array * >(_redirect);
157  if (!bt) {
158  bt = this;
159  }
160 
161  // Added 'if (number > 0)' to support zero-length arrays. jhrg 2/2/16
162  // Changed to >= 0 to catch the edge case where the rightmost dimension
163  // is constrained to be just one element. jhrg 6/9/16 (See Hyrax-225)
164  if (number >= 0) {
165  for (int i = 0; i < number; ++i) {
166  BaseType *curr_var = basetype_to_asciitype(bt->var(index++));
167  dynamic_cast<AsciiOutput &>(*curr_var).print_ascii(strm, false);
168  strm << ", ";
169  // we're not saving curr_var for future use, so delete it here
170  delete curr_var;
171  }
172  BaseType *curr_var = basetype_to_asciitype(bt->var(index++));
173  dynamic_cast<AsciiOutput &>(*curr_var).print_ascii(strm, false);
174  // we're not saving curr_var for future use, so delete it here
175  delete curr_var;
176  }
177 
178  return index;
179 }
180 
181 // Given a vector of indices, return the corresponding index.
182 
183 int AsciiArray::get_index(vector < int >indices) throw(InternalErr)
184 {
185  if (indices.size() != /*bt->*/dimensions(true)) {
186  throw InternalErr(__FILE__, __LINE__,
187  "Index vector is the wrong size!");
188  }
189  // suppose shape is [3][4][5][6] for x,y,z,t. The index is
190  // t + z(6) + y(5 * 6) + x(4 * 5 *6).
191  // Assume that indices[0] holds x, indices[1] holds y, ...
192 
193  // It's hard to work with Pixes
194  vector < int >shape = get_shape_vector(indices.size());
195 
196  // We want to work from the rightmost index to the left
197  reverse(indices.begin(), indices.end());
198  reverse(shape.begin(), shape.end());
199 
200  vector < int >::iterator indices_iter = indices.begin();
201  vector < int >::iterator shape_iter = shape.begin();
202 
203  int index = *indices_iter++; // in the ex. above, this adds `t'
204  int multiplier = 1;
205  while (indices_iter != indices.end()) {
206  multiplier *= *shape_iter++;
207  index += multiplier * *indices_iter++;
208  }
209 
210  return index;
211 }
212 
213 // get_shape_vector and get_nth_dim_size are public because that are called
214 // from Grid. 9/14/2001 jhrg
215 
216 vector < int > AsciiArray::get_shape_vector(size_t n) throw(InternalErr)
217 {
218  if (n < 1 || n > dimensions(true)) {
219  string msg = "Attempt to get ";
220  msg += long_to_string(n) + " dimensions from " + name()
221  + " which has only " + long_to_string(dimensions(true))
222  + "dimensions.";
223 
224  throw InternalErr(__FILE__, __LINE__, msg);
225  }
226 
227  vector < int >shape;
228  Array::Dim_iter p = dim_begin();
229  for (unsigned i = 0; i < n && p != dim_end(); ++i, ++p) {
230  shape.push_back(dimension_size(p, true));
231  }
232 
233  return shape;
234 }
235 
239 int AsciiArray::get_nth_dim_size(size_t n) throw(InternalErr)
240 {
241  if (n > /*bt->*/dimensions(true) - 1) {
242  string msg = "Attempt to get dimension ";
243  msg +=
244  long_to_string(n + 1) + " from `" + /*bt->*/name() +
245  "' which has " + long_to_string(/*bt->*/dimensions(true)) +
246  " dimension(s).";
247  throw InternalErr(__FILE__, __LINE__, msg);
248  }
249 
250  return /*bt->*/dimension_size(/*bt->*/dim_begin() + n, true);
251 }
252 
253 void AsciiArray::print_array(ostream &strm, bool /*print_name */ )
254 {
255  DBG(cerr << "Entering AsciiArray::print_array" << endl);
256 
257  int dims = /*bt->*/dimensions(true);
258  if (dims <= 1)
259  throw InternalErr(__FILE__, __LINE__,
260  "Dimension count is <= 1 while printing multidimensional array.");
261 
262  // shape holds the maximum index value of all but the last dimension of
263  // the array (not the size; each value is one less that the size).
264  vector < int >shape = get_shape_vector(dims - 1);
265  int rightmost_dim_size = get_nth_dim_size(dims - 1);
266 
267  // state holds the indexes of the current row being printed. For an N-dim
268  // array, there are N-1 dims that are iterated over when printing (the
269  // Nth dim is not printed explicitly. Instead it's the number of values
270  // on the row.
271  vector < int >state(dims - 1, 0);
272 
273  bool more_indices;
274  int index = 0;
275  do {
276  // Print indices for all dimensions except the last one.
277  strm << dynamic_cast <AsciiOutput *>(this)->get_full_name() ;
278 
279  for (int i = 0; i < dims - 1; ++i) {
280  strm << "[" << state[i] << "]" ;
281  }
282  strm << ", " ;
283 
284  index = print_row(strm, index, rightmost_dim_size - 1);
285  more_indices = increment_state(&state, shape);
286  if (more_indices)
287  strm << "\n" ;
288 
289  } while (more_indices);
290 
291  DBG(cerr << "ExitingAsciiArray::print_array" << endl);
292 }
293 
294 void AsciiArray::print_complex_array(ostream &strm, bool /*print_name */ )
295 {
296  DBG(cerr << "Entering AsciiArray::print_complex_array" << endl);
297 
298  Array *bt = dynamic_cast < Array * >(_redirect);
299  if (!bt)
300  bt = this;
301 
302  int dims = /*bt->*/dimensions(true);
303  if (dims < 1)
304  throw InternalErr(__FILE__, __LINE__,
305  "Dimension count is <= 1 while printing multidimensional array.");
306 
307  // shape holds the maximum index value of all but the last dimension of
308  // the array (not the size; each value is one less than the size).
309  vector < int >shape = get_shape_vector(dims);
310 
311  vector < int >state(dims, 0);
312 
313  bool more_indices;
314  do {
315  // Print indices for all dimensions except the last one.
316  strm << dynamic_cast <AsciiOutput *>(this)->get_full_name() ;
317 
318  for (int i = 0; i < dims; ++i) {
319  strm << "[" << state[i] << "]" ;
320  }
321  strm << "\n" ;
322 
323  BaseType *curr_var =
324  basetype_to_asciitype(bt->var(get_index(state)));
325  dynamic_cast < AsciiOutput & >(*curr_var).print_ascii(strm, true);
326  // we are not saving curr_var for future reference, so delete it
327  delete curr_var;
328 
329  more_indices = increment_state(&state, shape);
330  if (more_indices)
331  strm << "\n" ;
332 
333  } while (more_indices);
334 
335  DBG(cerr << "ExitingAsciiArray::print_complex_array" << endl);
336 }
337 
AsciiArray::print_row
int print_row(ostream &strm, int index, int number)
Definition: AsciiArray.cc:154
AsciiArray::get_shape_vector
vector< int > get_shape_vector(size_t n)
Definition: AsciiArray.cc:216
AsciiOutput::print_ascii
virtual void print_ascii(ostream &strm, bool print_name=true)
Print values as ASCII Prints the values of this in ASCII suitable for import into a spreadsheet....
Definition: AsciiOutput.cc:73
AsciiArray::print_ascii
virtual void print_ascii(ostream &strm, bool print_name=true)
Print values as ASCII Prints the values of this in ASCII suitable for import into a spreadsheet....
Definition: AsciiArray.cc:94
AsciiArray
Definition: AsciiArray.h:44
AsciiOutput
Definition: AsciiOutput.h:46
AsciiArray::get_nth_dim_size
int get_nth_dim_size(size_t n)
Definition: AsciiArray.cc:239