38 #include "config_nc.h"
51 #include <InternalErr.h>
57 #include "NCRequestHandler.h"
59 #include "NCStructure.h"
63 NCArray::ptr_duplicate()
87 NCArray::operator=(
const NCArray &rhs)
92 dynamic_cast<Array &
>(*this) = rhs;
113 NCArray::format_constraint(
size_t *cor, ptrdiff_t *step,
size_t *edg,
116 int start, stride, stop;
122 for (Dim_iter p = dim_begin(); p != dim_end(); ++p) {
123 start = dimension_start(p,
true);
124 stride = dimension_stride(p,
true);
125 stop = dimension_stop(p,
true);
128 if (start + stop + stride == 0) {
129 start = dimension_start(p,
false);
130 stride = dimension_stride(p,
false);
131 stop = dimension_stop(p,
false);
136 edg[id] = ((stop - start) / stride) + 1;
146 void NCArray::do_cardinal_array_read(
int ncid,
int varid, nc_type datatype,
147 vector<char> &values,
bool has_values,
int values_offset,
148 int nels,
size_t cor[],
size_t edg[], ptrdiff_t step[],
bool has_stride)
152 #if NETCDF_VERSION >= 4
153 errstat = nc_inq_type(ncid, datatype, 0, &size);
154 if (errstat != NC_NOERR)
155 throw Error(errstat,
"Could not get the size for the type.");
157 size = nctypelen(datatype);
160 BESDEBUG(
"nc",
"In NCArray::do_cardinal_array_read, size = " << size << endl);
166 #if NETCDF_VERSION >= 4
173 values.resize(nels * size);
175 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
177 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
178 if (errstat != NC_NOERR){
180 oss <<
"NCArray::do_cardinal_array_read() - Could not get the value for Array variable '" << name() <<
"'.";
181 oss <<
" dimensions: " << dimensions(
true);
182 oss <<
" nc_get_vara() errstat: " << errstat;
183 throw Error(errstat, oss.str());
190 val2buf(&values[0] + values_offset);
197 values.resize(nels * size);
199 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
201 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
202 if (errstat != NC_NOERR)
203 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"' (NCArray::do_cardinal_array_read)"));
205 if (NCRequestHandler::get_promote_byte_to_short()) {
209 if (var()->type() != libdap::dods_int16_c) {
210 throw Error(
string(
"NC.PromoteByteToShort is set but the underlying array type is still a Byte: ") + name() +
string(
"."));
213 vector<short int> tmp(nels);
218 char *raw_byte_data = &values[0] + values_offset;
219 for (
int i = 0; i < nels; ++i)
220 tmp[i] = *raw_byte_data++;
225 val2buf(&values[0] + values_offset);
236 int vdimids[MAX_VAR_DIMS];
237 errstat = nc_inq_var(ncid, varid, (
char *)0, (nc_type*)0, &num_dim, vdimids, (
int *)0);
238 if (errstat != NC_NOERR)
239 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
241 throw Error(
string(
"A one-dimensional NC_CHAR array should now map to a DAP string: '") + name() +
string(
"'."));
243 size_t vdims[MAX_VAR_DIMS];
244 for (
int i = 0; i < num_dim; ++i)
245 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &vdims[i])) != NC_NOERR)
246 throw Error(errstat,
string(
"Could not read dimension information about the variable `") + name() +
string(
"'."));
248 int nth_dim_size = vdims[num_dim - 1];
249 cor[num_dim - 1] = 0;
250 edg[num_dim - 1] = nth_dim_size;
252 step[num_dim - 1] = 1;
255 values.resize(nels * nth_dim_size * size);
257 errstat = nc_get_vars_text(ncid, varid, cor, edg, step, &values[0]);
259 errstat = nc_get_vara_text(ncid, varid, cor, edg, &values[0]);
260 if (errstat != NC_NOERR)
261 throw Error(errstat,
string(
"Could not read the variable '") + name() +
string(
"'."));
265 vector<string> strg(nels);
266 vector<char> buf(nth_dim_size + 1);
268 for (
int i = 0; i < nels; i++) {
269 strncpy(&buf[0], &values[0] + values_offset + (i * nth_dim_size), nth_dim_size);
270 buf[nth_dim_size] =
'\0';
278 #if NETCDF_VERSION >= 4
281 values.resize(nels * size);
283 errstat = nc_get_vars_string(ncid, varid, cor, edg, step, (
char**)(&values[0] + values_offset));
285 errstat = nc_get_vara_string(ncid, varid, cor, edg, (
char**)(&values[0] + values_offset));
286 if (errstat != NC_NOERR)
287 throw Error(errstat,
string(
"Could not read the variable `") + name() +
string(
"'."));
291 vector < string > strg(nels);
292 for (
int i = 0; i < nels; i++) {
295 strg[i] = *((
char**)(&values[0] + values_offset) + i);
298 nc_free_string(nels, (
char**)&values[0]);
305 throw InternalErr(__FILE__, __LINE__,
string(
"Unknown data type for the variable '") + name() +
string(
"'."));
309 void NCArray::do_array_read(
int ncid,
int varid, nc_type datatype,
310 vector<char> &values,
bool has_values,
int values_offset,
311 int nels,
size_t cor[],
size_t edg[], ptrdiff_t step[],
bool has_stride)
315 #if NETCDF_VERSION >= 4
316 if (datatype >= NC_FIRSTUSERTYPEID ) {
318 char type_name[NC_MAX_NAME+1];
323 errstat = nc_inq_user_type(ncid, datatype, type_name, &size, &base_type, &nfields, &class_type);
325 if (errstat != NC_NOERR)
326 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about a user-defined type (" + long_to_string(errstat) +
")."));
328 switch (class_type) {
331 values.resize(size * nels);
333 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
335 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
336 if (errstat != NC_NOERR)
337 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"'"));
341 for (
int element = 0; element < nels; ++element) {
343 for (
size_t i = 0; i < nfields; ++i) {
344 char field_name[NC_MAX_NAME+1];
345 nc_type field_typeid;
350 nc_inq_compound_field(ncid, datatype, i, field_name, &field_offset, &field_typeid, 0, 0);
351 BaseType *field = ncs->var(field_name);
352 if (field_typeid >= NC_FIRSTUSERTYPEID ) {
356 nc_inq_compound_name(ncid, field_typeid, field_name);
357 field = ncs->var(field_name);
359 child_ncs.do_structure_read(ncid, varid, field_typeid,
360 values, has_values, field_offset + values_offset + size * element);
362 else if (field->is_vector_type()) {
367 child_array.do_array_read(ncid, varid, field_typeid,
368 values, has_values, field_offset + values_offset + size * element,
369 nels, cor, edg, step, has_stride);
371 else if (field->is_simple_type()) {
372 field->val2buf(&values[0] + (element * size) + field_offset);
375 throw InternalErr(__FILE__, __LINE__,
"Expecting a netcdf user defined type or an array or a scalar.");
378 field->set_read_p(
true);
380 ncs->set_read_p(
true);
381 set_vec(element, ncs);
389 if (NCRequestHandler::get_ignore_unknown_types())
390 cerr <<
"in build_user_defined; found a vlen." << endl;
392 throw Error(
"The netCDF handler does not currently support NC_VLEN attributes.");
400 int vdimids[MAX_VAR_DIMS];
401 errstat = nc_inq_var(ncid, varid, (
char *)0, (nc_type*)0, &num_dim, vdimids, (
int *)0);
402 if (errstat != NC_NOERR)
403 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
405 throw Error(
string(
"A one-dimensional NC_OPAQUE array should now map to a DAP Byte: '") + name() +
string(
"'."));
407 size_t vdims[MAX_VAR_DIMS];
408 for (
int i = 0; i < num_dim; ++i)
409 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &vdims[i])) != NC_NOERR)
410 throw Error(errstat,
string(
"Could not read dimension information about the variable `") + name() +
string(
"'."));
412 int nth_dim_size = vdims[num_dim - 1];
413 cor[num_dim - 1] = 0;
414 edg[num_dim - 1] = nth_dim_size;
416 step[num_dim - 1] = 1;
419 values.resize(size * nels);
421 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
423 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
424 if (errstat != NC_NOERR)
425 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"' (NC_OPAQUE)"));
429 val2buf(&values[0] + values_offset);
436 nc_type base_nc_type;
437 errstat = nc_inq_enum(ncid, datatype, 0 , &base_nc_type, 0, 0);
438 if (errstat != NC_NOERR)
439 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about an enum(" + long_to_string(errstat) +
")."));
441 do_cardinal_array_read(ncid, varid, base_nc_type,
442 values, has_values, values_offset,
443 nels, cor, edg, step, has_stride);
450 throw InternalErr(__FILE__, __LINE__,
"Expected one of NC_COMPOUND, NC_VLEN, NC_OPAQUE or NC_ENUM");
455 do_cardinal_array_read(ncid, varid, datatype, values, has_values, values_offset,
456 nels, cor, edg, step, has_stride);
459 do_cardinal_array_read(ncid, varid, datatype, values, has_values, values_offset,
460 nels, cor, edg, step, has_stride);
470 int errstat = nc_open(dataset().c_str(), NC_NOWRITE, &ncid);
471 if (errstat != NC_NOERR)
472 throw Error(errstat,
string(
"Could not open the dataset's file (") + dataset().c_str() +
string(
")"));
475 errstat = nc_inq_varid(ncid, name().c_str(), &varid);
476 if (errstat != NC_NOERR)
477 throw InternalErr(__FILE__, __LINE__,
"Could not get variable ID for: " + name() +
". (error: " + long_to_string(errstat) +
").");
480 errstat = nc_inq_vartype(ncid, varid, &datatype);
481 if (errstat != NC_NOERR)
482 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
484 size_t cor[MAX_NC_DIMS];
485 size_t edg[MAX_NC_DIMS];
486 ptrdiff_t step[MAX_NC_DIMS];
488 for(
unsigned int i=0; i<MAX_NC_DIMS; i++){
489 cor[i] = edg[i] = step[i] = 0;
491 long nels = format_constraint(cor, step, edg, &has_stride);
499 do_array_read(ncid, varid, datatype, values,
false , 0 ,
500 nels, cor, edg, step, has_stride);
503 if (nc_close(ncid) != NC_NOERR)
504 throw InternalErr(__FILE__, __LINE__,
"Could not close the dataset!");