bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
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
42using namespace std;
43
44// #define DODS_DEBUG
45
46#include <libdap/InternalErr.h>
47#include <libdap/debug.h>
48
49#include "AsciiArray.h"
50#include <libdap/util.h>
51#include "get_ascii.h"
52
53using namespace dap_asciival;
54
55BaseType *
56AsciiArray::ptr_duplicate()
57{
58 return new AsciiArray(*this);
59}
60
61AsciiArray::AsciiArray(const string &n, BaseType *v) : Array(n, v)
62{
63}
64
65AsciiArray::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
90AsciiArray::~AsciiArray()
91{
92}
93
94void 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.
113void 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 int64_t end = /*bt->*/dimension_size_ll(/*bt->*/dim_begin(), true) - 1;
128
129 for (int64_t 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
154int 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
183int 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
216vector < 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
239int 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
253void 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
294void 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
virtual void print_ascii(ostream &strm, bool print_name=true)
Definition AsciiArray.cc:94
int get_nth_dim_size(size_t n)
vector< int > get_shape_vector(size_t n)
int print_row(ostream &strm, int index, int number)
bool increment_state(vector< int > *state, const vector< int > &shape)