38 #include "config_nc.h"
51 #include <InternalErr.h>
57 #include "NCRequestHandler.h"
59 #include "NCStructure.h"
63 #define prolog std::string("NCArray::").append(__func__).append("() - ")
66 NCArray::ptr_duplicate()
90 NCArray::operator=(
const NCArray &rhs)
95 dynamic_cast<Array &
>(*this) = rhs;
116 NCArray::format_constraint(
size_t *cor, ptrdiff_t *step,
size_t *edg,
119 int start, stride, stop;
125 for (Dim_iter p = dim_begin(); p != dim_end(); ++p) {
126 start = dimension_start(p,
true);
127 stride = dimension_stride(p,
true);
128 stop = dimension_stop(p,
true);
131 if (start + stop + stride == 0) {
132 start = dimension_start(p,
false);
133 stride = dimension_stride(p,
false);
134 stop = dimension_stop(p,
false);
139 edg[id] = ((stop - start) / stride) + 1;
149 void NCArray::do_cardinal_array_read(
int ncid,
int varid, nc_type datatype,
150 vector<char> &values,
bool has_values,
int values_offset,
151 int nels,
size_t cor[],
size_t edg[], ptrdiff_t step[],
bool has_stride)
155 #if NETCDF_VERSION >= 4
156 errstat = nc_inq_type(ncid, datatype, 0, &size);
157 if (errstat != NC_NOERR)
158 throw Error(errstat,
"Could not get the size for the type.");
160 size = nctypelen(datatype);
163 BESDEBUG( MODULE, prolog <<
"size = " << size << endl);
169 #if NETCDF_VERSION >= 4
176 values.resize(nels * size);
178 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
180 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
181 if (errstat != NC_NOERR){
183 oss << prolog <<
"Could not get the value for Array variable '" << name() <<
"'.";
184 oss <<
" dimensions: " << dimensions(
true);
185 oss <<
" nc_get_vara() errstat: " << errstat;
186 throw Error(errstat, oss.str());
193 val2buf(&values[0] + values_offset);
200 values.resize(nels * size);
202 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
204 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
205 if (errstat != NC_NOERR)
206 throw Error(errstat, prolog +
"Could not get the value for variable '" + name() +
string(
"' (NCArray::do_cardinal_array_read)"));
208 if (NCRequestHandler::get_promote_byte_to_short()) {
212 if (var()->type() != libdap::dods_int16_c) {
213 throw Error(
string(
"NC.PromoteByteToShort is set but the underlying array type is still a Byte: ") + name() +
string(
"."));
216 vector<short int> tmp(nels);
221 char *raw_byte_data = &values[0] + values_offset;
222 for (
int i = 0; i < nels; ++i)
223 tmp[i] = *raw_byte_data++;
228 val2buf(&values[0] + values_offset);
239 int vdimids[MAX_VAR_DIMS];
240 errstat = nc_inq_var(ncid, varid, (
char *)0, (nc_type*)0, &num_dim, vdimids, (
int *)0);
241 if (errstat != NC_NOERR)
242 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
244 throw Error(
string(
"A one-dimensional NC_CHAR array should now map to a DAP string: '") + name() +
string(
"'."));
246 size_t vdims[MAX_VAR_DIMS];
247 for (
int i = 0; i < num_dim; ++i)
248 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &vdims[i])) != NC_NOERR)
249 throw Error(errstat,
string(
"Could not read dimension information about the variable `") + name() +
string(
"'."));
251 int nth_dim_size = vdims[num_dim - 1];
252 cor[num_dim - 1] = 0;
253 edg[num_dim - 1] = nth_dim_size;
255 step[num_dim - 1] = 1;
258 values.resize(nels * nth_dim_size * size);
260 errstat = nc_get_vars_text(ncid, varid, cor, edg, step, &values[0]);
262 errstat = nc_get_vara_text(ncid, varid, cor, edg, &values[0]);
263 if (errstat != NC_NOERR)
264 throw Error(errstat,
string(
"Could not read the variable '") + name() +
string(
"'."));
268 vector<string> strg(nels);
269 vector<char> buf(nth_dim_size + 1);
271 for (
int i = 0; i < nels; i++) {
272 strncpy(&buf[0], &values[0] + values_offset + (i * nth_dim_size), nth_dim_size);
273 buf[nth_dim_size] =
'\0';
281 #if NETCDF_VERSION >= 4
284 values.resize(nels * size);
286 errstat = nc_get_vars_string(ncid, varid, cor, edg, step, (
char**)(&values[0] + values_offset));
288 errstat = nc_get_vara_string(ncid, varid, cor, edg, (
char**)(&values[0] + values_offset));
289 if (errstat != NC_NOERR)
290 throw Error(errstat,
string(
"Could not read the variable `") + name() +
string(
"'."));
294 vector < string > strg(nels);
295 for (
int i = 0; i < nels; i++) {
298 strg[i] = *((
char**)(&values[0] + values_offset) + i);
301 nc_free_string(nels, (
char**)&values[0]);
308 throw InternalErr(__FILE__, __LINE__,
string(
"Unknown data type for the variable '") + name() +
string(
"'."));
312 void NCArray::do_array_read(
int ncid,
int varid, nc_type datatype,
313 vector<char> &values,
bool has_values,
int values_offset,
314 int nels,
size_t cor[],
size_t edg[], ptrdiff_t step[],
bool has_stride)
318 #if NETCDF_VERSION >= 4
319 if (datatype >= NC_FIRSTUSERTYPEID ) {
321 char type_name[NC_MAX_NAME+1];
326 errstat = nc_inq_user_type(ncid, datatype, type_name, &size, &base_type, &nfields, &class_type);
328 if (errstat != NC_NOERR)
329 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about a user-defined type (" + long_to_string(errstat) +
")."));
331 switch (class_type) {
334 values.resize(size * nels);
336 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
338 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
339 if (errstat != NC_NOERR)
340 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"'"));
344 for (
int element = 0; element < nels; ++element) {
346 for (
size_t i = 0; i < nfields; ++i) {
347 char field_name[NC_MAX_NAME+1];
348 nc_type field_typeid;
353 nc_inq_compound_field(ncid, datatype, i, field_name, &field_offset, &field_typeid, 0, 0);
354 BaseType *field = ncs->var(field_name);
355 if (field_typeid >= NC_FIRSTUSERTYPEID ) {
359 nc_inq_compound_name(ncid, field_typeid, field_name);
360 field = ncs->var(field_name);
362 child_ncs.do_structure_read(ncid, varid, field_typeid,
363 values, has_values, field_offset + values_offset + size * element);
365 else if (field->is_vector_type()) {
370 child_array.do_array_read(ncid, varid, field_typeid,
371 values, has_values, field_offset + values_offset + size * element,
372 nels, cor, edg, step, has_stride);
374 else if (field->is_simple_type()) {
375 field->val2buf(&values[0] + (element * size) + field_offset);
378 throw InternalErr(__FILE__, __LINE__,
"Expecting a netcdf user defined type or an array or a scalar.");
381 field->set_read_p(
true);
383 ncs->set_read_p(
true);
384 set_vec(element, ncs);
392 if (NCRequestHandler::get_ignore_unknown_types())
393 cerr <<
"in build_user_defined; found a vlen." << endl;
395 throw Error(
"The netCDF handler does not currently support NC_VLEN attributes.");
403 int vdimids[MAX_VAR_DIMS];
404 errstat = nc_inq_var(ncid, varid, (
char *)0, (nc_type*)0, &num_dim, vdimids, (
int *)0);
405 if (errstat != NC_NOERR)
406 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
408 throw Error(
string(
"A one-dimensional NC_OPAQUE array should now map to a DAP Byte: '") + name() +
string(
"'."));
410 size_t vdims[MAX_VAR_DIMS];
411 for (
int i = 0; i < num_dim; ++i)
412 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &vdims[i])) != NC_NOERR)
413 throw Error(errstat,
string(
"Could not read dimension information about the variable `") + name() +
string(
"'."));
415 int nth_dim_size = vdims[num_dim - 1];
416 cor[num_dim - 1] = 0;
417 edg[num_dim - 1] = nth_dim_size;
419 step[num_dim - 1] = 1;
422 values.resize(size * nels);
424 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
426 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
427 if (errstat != NC_NOERR)
428 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"' (NC_OPAQUE)"));
432 val2buf(&values[0] + values_offset);
439 nc_type base_nc_type;
440 errstat = nc_inq_enum(ncid, datatype, 0 , &base_nc_type, 0, 0);
441 if (errstat != NC_NOERR)
442 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about an enum(" + long_to_string(errstat) +
")."));
444 do_cardinal_array_read(ncid, varid, base_nc_type,
445 values, has_values, values_offset,
446 nels, cor, edg, step, has_stride);
453 throw InternalErr(__FILE__, __LINE__,
"Expected one of NC_COMPOUND, NC_VLEN, NC_OPAQUE or NC_ENUM");
458 do_cardinal_array_read(ncid, varid, datatype, values, has_values, values_offset,
459 nels, cor, edg, step, has_stride);
462 do_cardinal_array_read(ncid, varid, datatype, values, has_values, values_offset,
463 nels, cor, edg, step, has_stride);
473 int errstat = nc_open(dataset().c_str(), NC_NOWRITE, &ncid);
474 if (errstat != NC_NOERR)
475 throw Error(errstat,
string(
"Could not open the dataset's file (") + dataset().c_str() +
string(
")"));
478 errstat = nc_inq_varid(ncid, name().c_str(), &varid);
479 if (errstat != NC_NOERR)
480 throw InternalErr(__FILE__, __LINE__,
"Could not get variable ID for: " + name() +
". (error: " + long_to_string(errstat) +
").");
483 errstat = nc_inq_vartype(ncid, varid, &datatype);
484 if (errstat != NC_NOERR)
485 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
487 size_t cor[MAX_NC_DIMS];
488 size_t edg[MAX_NC_DIMS];
489 ptrdiff_t step[MAX_NC_DIMS];
491 for(
unsigned int i=0; i<MAX_NC_DIMS; i++){
492 cor[i] = edg[i] = step[i] = 0;
494 long nels = format_constraint(cor, step, edg, &has_stride);
502 do_array_read(ncid, varid, datatype, values,
false , 0 ,
503 nels, cor, edg, step, has_stride);
506 if (nc_close(ncid) != NC_NOERR)
507 throw InternalErr(__FILE__, __LINE__,
"Could not close the dataset!");
NCArray(const string &n, const string &d, BaseType *v)