48#include <libdap/BaseType.h>
49#include <libdap/Error.h>
50#include <libdap/InternalErr.h>
51#include <libdap/util.h>
52#include <libdap/debug.h>
56#include "NCRequestHandler.h"
58#include "NCStructure.h"
62#define prolog std::string("NCArray::").append(__func__).append("() - ")
65NCArray::ptr_duplicate()
89NCArray::operator=(
const NCArray &rhs)
94 dynamic_cast<Array &
>(*this) = rhs;
115NCArray::format_constraint(
size_t *cor, ptrdiff_t *step,
size_t *edg,
118 int start, stride, stop;
124 for (Dim_iter p = dim_begin(); p != dim_end(); ++p) {
125 start = dimension_start(p,
true);
126 stride = dimension_stride(p,
true);
127 stop = dimension_stop(p,
true);
130 if (start + stop + stride == 0) {
131 start = dimension_start(p,
false);
132 stride = dimension_stride(p,
false);
133 stop = dimension_stop(p,
false);
138 edg[id] = ((stop - start) / stride) + 1;
148void NCArray::do_cardinal_array_read(
int ncid,
int varid, nc_type datatype,
149 vector<char> &values,
bool has_values,
int values_offset,
150 int nels,
size_t cor[],
size_t edg[], ptrdiff_t step[],
bool has_stride)
154#if NETCDF_VERSION >= 4
155 errstat = nc_inq_type(ncid, datatype, 0, &size);
156 if (errstat != NC_NOERR)
157 throw Error(errstat,
"Could not get the size for the type.");
159 size = nctypelen(datatype);
162 BESDEBUG( MODULE, prolog <<
"size = " << size << endl);
168#if NETCDF_VERSION >= 4
175 values.resize(nels * size);
177 errstat = nc_get_vars(ncid, varid, cor, edg, step, values.data());
179 errstat = nc_get_vara(ncid, varid, cor, edg, values.data());
180 if (errstat != NC_NOERR){
182 oss << prolog <<
"Could not get the value for Array variable '" << name() <<
"'.";
183 oss <<
" dimensions: " << dimensions(
true);
184 oss <<
" nc_get_vara() errstat: " << errstat;
185 throw Error(errstat, oss.str());
192 val2buf(values.data() + values_offset);
199 values.resize(nels * size);
201 errstat = nc_get_vars(ncid, varid, cor, edg, step, values.data());
203 errstat = nc_get_vara(ncid, varid, cor, edg, values.data());
204 if (errstat != NC_NOERR)
205 throw Error(errstat, prolog +
"Could not get the value for variable '" + name() +
string(
"' (NCArray::do_cardinal_array_read)"));
207 if (NCRequestHandler::get_promote_byte_to_short()) {
211 if (var()->type() != libdap::dods_int16_c) {
212 throw Error(
string(
"NC.PromoteByteToShort is set but the underlying array type is still a Byte: ") + name() +
string(
"."));
215 vector<short int> tmp(nels);
220 const char *raw_byte_data = values.data() + values_offset;
221 for (
int i = 0; i < nels; ++i)
222 tmp[i] = *raw_byte_data++;
227 val2buf(values.data() + values_offset);
238 int vdimids[MAX_VAR_DIMS];
239 errstat = nc_inq_var(ncid, varid, (
char *)0, (nc_type*)0, &num_dim, vdimids, (
int *)0);
240 if (errstat != NC_NOERR)
241 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
243 throw Error(
string(
"A one-dimensional NC_CHAR array should now map to a DAP string: '") + name() +
string(
"'."));
245 size_t vdims[MAX_VAR_DIMS];
246 for (
int i = 0; i < num_dim; ++i)
247 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &vdims[i])) != NC_NOERR)
248 throw Error(errstat,
string(
"Could not read dimension information about the variable `") + name() +
string(
"'."));
250 int nth_dim_size = vdims[num_dim - 1];
251 cor[num_dim - 1] = 0;
252 edg[num_dim - 1] = nth_dim_size;
254 step[num_dim - 1] = 1;
257 values.resize(nels * nth_dim_size * size);
259 errstat = nc_get_vars_text(ncid, varid, cor, edg, step, values.data());
261 errstat = nc_get_vara_text(ncid, varid, cor, edg, values.data());
262 if (errstat != NC_NOERR)
263 throw Error(errstat,
string(
"Could not read the variable '") + name() +
string(
"'."));
267 vector<string> strg(nels);
268 vector<char> buf(nth_dim_size + 1);
270 for (
int i = 0; i < nels; i++) {
271 strncpy(buf.data(), values.data() + values_offset + (i * nth_dim_size), nth_dim_size);
272 buf[nth_dim_size] =
'\0';
273 strg[i] = buf.data();
277 val2buf(strg.data());
280#if NETCDF_VERSION >= 4
283 values.resize(nels * size);
285 errstat = nc_get_vars_string(ncid, varid, cor, edg, step, (
char**)(values.data() + values_offset));
287 errstat = nc_get_vara_string(ncid, varid, cor, edg, (
char**)(values.data() + values_offset));
288 if (errstat != NC_NOERR)
289 throw Error(errstat,
string(
"Could not read the variable `") + name() +
string(
"'."));
293 vector < string > strg(nels);
294 for (
int i = 0; i < nels; i++) {
297 strg[i] = *((
char**)(values.data() + values_offset) + i);
300 nc_free_string(nels, (
char**)values.data());
302 val2buf(strg.data());
307 throw InternalErr(__FILE__, __LINE__,
string(
"Unknown data type for the variable '") + name() +
string(
"'."));
311void NCArray::do_array_read(
int ncid,
int varid, nc_type datatype,
312 vector<char> &values,
bool has_values,
int values_offset,
313 int nels,
size_t cor[],
size_t edg[], ptrdiff_t step[],
bool has_stride)
317#if NETCDF_VERSION >= 4
318 if (datatype >= NC_FIRSTUSERTYPEID ) {
320 char type_name[NC_MAX_NAME+1];
325 errstat = nc_inq_user_type(ncid, datatype, type_name, &size, &base_type, &nfields, &class_type);
327 if (errstat != NC_NOERR)
328 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about a user-defined type (" + long_to_string(errstat) +
")."));
330 switch (class_type) {
333 values.resize(size * nels);
335 errstat = nc_get_vars(ncid, varid, cor, edg, step, values.data());
337 errstat = nc_get_vara(ncid, varid, cor, edg, values.data());
338 if (errstat != NC_NOERR)
339 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"'"));
343 for (
int element = 0; element < nels; ++element) {
344 NCStructure *ncs =
dynamic_cast<NCStructure*
> (var()->ptr_duplicate());
345 for (
int i = 0; i < nfields; ++i) {
346 char field_name[NC_MAX_NAME+1];
347 nc_type field_typeid;
352 nc_inq_compound_field(ncid, datatype, i, field_name, &field_offset, &field_typeid,
nullptr,
nullptr);
353 BaseType *field = ncs->var(field_name);
354 if (field_typeid >= NC_FIRSTUSERTYPEID ) {
358 nc_inq_compound_name(ncid, field_typeid, field_name);
359 field = ncs->var(field_name);
360 NCStructure &child_ncs =
dynamic_cast<NCStructure&
> (*field);
361 child_ncs.do_structure_read(ncid, varid, field_typeid,
362 values, has_values, field_offset + values_offset + size * element);
364 else if (field->is_vector_type()) {
369 child_array.do_array_read(ncid, varid, field_typeid,
370 values, has_values, field_offset + values_offset + size * element,
371 nels, cor, edg, step, has_stride);
373 else if (field->is_simple_type()) {
374 field->val2buf(values.data() + (element * size) + field_offset);
377 throw InternalErr(__FILE__, __LINE__,
"Expecting a netcdf user defined type or an array or a scalar.");
380 field->set_read_p(
true);
382 ncs->set_read_p(
true);
383 set_vec(element, ncs);
391 if (NCRequestHandler::get_ignore_unknown_types())
392 cerr <<
"in build_user_defined; found a vlen." << endl;
394 throw Error(
"The netCDF handler does not currently support NC_VLEN attributes.");
402 int vdimids[MAX_VAR_DIMS];
403 errstat = nc_inq_var(ncid, varid, (
char *)0, (nc_type*)0, &num_dim, vdimids, (
int *)0);
404 if (errstat != NC_NOERR)
405 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
407 throw Error(
string(
"A one-dimensional NC_OPAQUE array should now map to a DAP Byte: '") + name() +
string(
"'."));
409 size_t vdims[MAX_VAR_DIMS];
410 for (
int i = 0; i < num_dim; ++i)
411 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &vdims[i])) != NC_NOERR)
412 throw Error(errstat,
string(
"Could not read dimension information about the variable `") + name() +
string(
"'."));
414 int nth_dim_size = vdims[num_dim - 1];
415 cor[num_dim - 1] = 0;
416 edg[num_dim - 1] = nth_dim_size;
418 step[num_dim - 1] = 1;
421 values.resize(size * nels);
423 errstat = nc_get_vars(ncid, varid, cor, edg, step, values.data());
425 errstat = nc_get_vara(ncid, varid, cor, edg, values.data());
426 if (errstat != NC_NOERR)
427 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"' (NC_OPAQUE)"));
431 val2buf(values.data() + values_offset);
438 nc_type base_nc_type;
439 errstat = nc_inq_enum(ncid, datatype,
nullptr , &base_nc_type,
nullptr,
nullptr);
440 if (errstat != NC_NOERR)
441 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about an enum(" + long_to_string(errstat) +
")."));
443 do_cardinal_array_read(ncid, varid, base_nc_type,
444 values, has_values, values_offset,
445 nels, cor, edg, step, has_stride);
452 throw InternalErr(__FILE__, __LINE__,
"Expected one of NC_COMPOUND, NC_VLEN, NC_OPAQUE or NC_ENUM");
457 do_cardinal_array_read(ncid, varid, datatype, values, has_values, values_offset,
458 nels, cor, edg, step, has_stride);
461 do_cardinal_array_read(ncid, varid, datatype, values, has_values, values_offset,
462 nels, cor, edg, step, has_stride);
472 int errstat = nc_open(dataset().c_str(), NC_NOWRITE, &ncid);
473 if (errstat != NC_NOERR)
474 throw Error(errstat,
string(
"Could not open the dataset's file (") + dataset().c_str() +
string(
")"));
477 errstat = nc_inq_varid(ncid, name().c_str(), &varid);
478 if (errstat != NC_NOERR)
479 throw InternalErr(__FILE__, __LINE__,
"Could not get variable ID for: " + name() +
". (error: " + long_to_string(errstat) +
").");
482 errstat = nc_inq_vartype(ncid, varid, &datatype);
483 if (errstat != NC_NOERR)
484 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
486 size_t cor[MAX_NC_DIMS];
487 size_t edg[MAX_NC_DIMS];
488 ptrdiff_t step[MAX_NC_DIMS];
490 for(
unsigned int i=0; i<MAX_NC_DIMS; i++){
491 cor[i] = edg[i] = step[i] = 0;
493 long nels = format_constraint(cor, step, edg, &has_stride);
501 do_array_read(ncid, varid, datatype, values,
false , 0 ,
502 nels, cor, edg, step, has_stride);
505 if (nc_close(ncid) != NC_NOERR)
506 throw InternalErr(__FILE__, __LINE__,
"Could not close the dataset!");
NCArray(const string &n, const string &d, BaseType *v)