51 #include <InternalErr.h>
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);
127 if (start + stop + stride == 0) {
128 start = dimension_start(p,
false);
129 stride = dimension_stride(p,
false);
130 stop = dimension_stop(p,
false);
135 edg[id] = ((stop - start) / stride) + 1;
145 void NCArray::do_cardinal_array_read(
int ncid,
int varid, nc_type datatype,
146 vector<char> &values,
bool has_values,
int values_offset,
147 int nels,
size_t cor[],
size_t edg[], ptrdiff_t step[],
bool has_stride)
151 #if NETCDF_VERSION >= 4
152 errstat = nc_inq_type(ncid, datatype, 0, &size);
153 if (errstat != NC_NOERR)
154 throw Error(errstat,
"Could not get the size for the type.");
156 size = nctypelen(datatype);
159 BESDEBUG(
"nc",
"In NCArray::do_cardinal_array_read, size = " << size << endl);
165 #if NETCDF_VERSION >= 4
172 values.resize(nels * size);
174 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
176 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
177 if (errstat != NC_NOERR)
178 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"' (NCArray::do_cardinal_array_read)"));
184 val2buf(&values[0] + values_offset);
191 values.resize(nels * size);
193 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
195 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
196 if (errstat != NC_NOERR)
197 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"' (NCArray::do_cardinal_array_read)"));
203 if (var()->type() != libdap::dods_int16_c) {
204 throw Error(
string(
"NC.PromoteByteToShort is set but the underlying array type is still a Byte: ") + name() +
string(
"."));
207 vector<short int> tmp(nels);
212 char *raw_byte_data = &values[0] + values_offset;
213 for (
int i = 0; i < nels; ++i)
214 tmp[i] = *raw_byte_data++;
219 val2buf(&values[0] + values_offset);
230 int vdimids[MAX_VAR_DIMS];
231 errstat = nc_inq_var(ncid, varid, (
char *)0, (nc_type*)0, &num_dim, vdimids, (
int *)0);
232 if (errstat != NC_NOERR)
233 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
235 throw Error(
string(
"A one-dimensional NC_CHAR array should now map to a DAP string: '") + name() +
string(
"'."));
237 size_t vdims[MAX_VAR_DIMS];
238 for (
int i = 0; i < num_dim; ++i)
239 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &vdims[i])) != NC_NOERR)
240 throw Error(errstat,
string(
"Could not read dimension information about the variable `") + name() +
string(
"'."));
242 int nth_dim_size = vdims[num_dim - 1];
243 cor[num_dim - 1] = 0;
244 edg[num_dim - 1] = nth_dim_size;
246 step[num_dim - 1] = 1;
249 values.resize(nels * nth_dim_size * size);
251 errstat = nc_get_vars_text(ncid, varid, cor, edg, step, &values[0]);
253 errstat = nc_get_vara_text(ncid, varid, cor, edg, &values[0]);
254 if (errstat != NC_NOERR)
255 throw Error(errstat,
string(
"Could not read the variable '") + name() +
string(
"'."));
259 vector<string> strg(nels);
260 vector<char> buf(nth_dim_size + 1);
262 for (
int i = 0; i < nels; i++) {
263 strncpy(&buf[0], &values[0] + values_offset + (i * nth_dim_size), nth_dim_size);
264 buf[nth_dim_size] =
'\0';
272 #if NETCDF_VERSION >= 4
275 values.resize(nels * size);
277 errstat = nc_get_vars_string(ncid, varid, cor, edg, step, (
char**)(&values[0] + values_offset));
279 errstat = nc_get_vara_string(ncid, varid, cor, edg, (
char**)(&values[0] + values_offset));
280 if (errstat != NC_NOERR)
281 throw Error(errstat,
string(
"Could not read the variable `") + name() +
string(
"'."));
285 vector < string > strg(nels);
286 for (
int i = 0; i < nels; i++) {
289 strg[i] = *((
char**)(&values[0] + values_offset) + i);
292 nc_free_string(nels, (
char**)&values[0]);
299 throw InternalErr(__FILE__, __LINE__,
string(
"Unknown data type for the variable '") + name() +
string(
"'."));
303 void NCArray::do_array_read(
int ncid,
int varid, nc_type datatype,
304 vector<char> &values,
bool has_values,
int values_offset,
305 int nels,
size_t cor[],
size_t edg[], ptrdiff_t step[],
bool has_stride)
309 #if NETCDF_VERSION >= 4
312 char type_name[NC_MAX_NAME+1];
317 errstat = nc_inq_user_type(ncid, datatype, type_name, &size, &base_type, &nfields, &class_type);
319 if (errstat != NC_NOERR)
320 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about a user-defined type (" + long_to_string(errstat) +
")."));
322 switch (class_type) {
325 values.resize(size * nels);
327 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
329 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
330 if (errstat != NC_NOERR)
331 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"'"));
335 for (
int element = 0; element < nels; ++element) {
337 for (
size_t i = 0; i < nfields; ++i) {
338 char field_name[NC_MAX_NAME+1];
339 nc_type field_typeid;
344 nc_inq_compound_field(ncid, datatype, i, field_name, &field_offset, &field_typeid, 0, 0);
345 BaseType *field = ncs->var(field_name);
351 nc_inq_compound_name(ncid, field_typeid, field_name);
352 field = ncs->var(field_name);
354 child_ncs.do_structure_read(ncid, varid, field_typeid,
355 values, has_values, field_offset + values_offset + size * element);
357 else if (field->is_vector_type()) {
362 child_array.do_array_read(ncid, varid, field_typeid,
363 values, has_values, field_offset + values_offset + size * element,
364 nels, cor, edg, step, has_stride);
366 else if (field->is_simple_type()) {
367 field->val2buf(&values[0] + (element * size) + field_offset);
370 throw InternalErr(__FILE__, __LINE__,
"Expecting a netcdf user defined type or an array or a scalar.");
373 field->set_read_p(
true);
375 ncs->set_read_p(
true);
376 set_vec(element, ncs);
385 cerr <<
"in build_user_defined; found a vlen." << endl;
387 throw Error(
"The netCDF handler does not currently support NC_VLEN attributes.");
395 int vdimids[MAX_VAR_DIMS];
396 errstat = nc_inq_var(ncid, varid, (
char *)0, (nc_type*)0, &num_dim, vdimids, (
int *)0);
397 if (errstat != NC_NOERR)
398 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
400 throw Error(
string(
"A one-dimensional NC_OPAQUE array should now map to a DAP Byte: '") + name() +
string(
"'."));
402 size_t vdims[MAX_VAR_DIMS];
403 for (
int i = 0; i < num_dim; ++i)
404 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &vdims[i])) != NC_NOERR)
405 throw Error(errstat,
string(
"Could not read dimension information about the variable `") + name() +
string(
"'."));
407 int nth_dim_size = vdims[num_dim - 1];
408 cor[num_dim - 1] = 0;
409 edg[num_dim - 1] = nth_dim_size;
411 step[num_dim - 1] = 1;
414 values.resize(size * nels);
416 errstat = nc_get_vars(ncid, varid, cor, edg, step, &values[0]);
418 errstat = nc_get_vara(ncid, varid, cor, edg, &values[0]);
419 if (errstat != NC_NOERR)
420 throw Error(errstat,
string(
"Could not get the value for variable '") + name() +
string(
"' (NC_OPAQUE)"));
424 val2buf(&values[0] + values_offset);
431 nc_type base_nc_type;
432 errstat = nc_inq_enum(ncid, datatype, 0 , &base_nc_type, 0, 0);
433 if (errstat != NC_NOERR)
434 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about an enum(" + long_to_string(errstat) +
")."));
436 do_cardinal_array_read(ncid, varid, base_nc_type,
437 values, has_values, values_offset,
438 nels, cor, edg, step, has_stride);
445 throw InternalErr(__FILE__, __LINE__,
"Expected one of NC_COMPOUND, NC_VLEN, NC_OPAQUE or NC_ENUM");
450 do_cardinal_array_read(ncid, varid, datatype, values, has_values, values_offset,
451 nels, cor, edg, step, has_stride);
454 do_cardinal_array_read(ncid, varid, datatype, values, has_values, values_offset,
455 nels, cor, edg, step, has_stride);
465 int errstat = nc_open(dataset().c_str(), NC_NOWRITE, &ncid);
466 if (errstat != NC_NOERR)
467 throw Error(errstat,
string(
"Could not open the dataset's file (") + dataset().c_str() +
string(
")"));
470 errstat = nc_inq_varid(ncid, name().c_str(), &varid);
471 if (errstat != NC_NOERR)
472 throw InternalErr(__FILE__, __LINE__,
"Could not get variable ID for: " + name() +
". (error: " + long_to_string(errstat) +
").");
475 errstat = nc_inq_vartype(ncid, varid, &datatype);
476 if (errstat != NC_NOERR)
477 throw Error(errstat,
string(
"Could not read information about the variable `") + name() +
string(
"'."));
479 size_t cor[MAX_NC_DIMS];
480 size_t edg[MAX_NC_DIMS];
481 ptrdiff_t step[MAX_NC_DIMS];
483 long nels = format_constraint(cor, step, edg, &has_stride);
486 do_array_read(ncid, varid, datatype, values,
false , 0 ,
487 nels, cor, edg, step, has_stride);
490 if (nc_close(ncid) != NC_NOERR)
491 throw InternalErr(__FILE__, __LINE__,
"Could not close the dataset!");
virtual BaseType * ptr_duplicate()
NCArray(const string &n, const string &d, BaseType *v)
Build an NCArray instance.
static bool get_ignore_unknown_types()
static bool get_promote_byte_to_short()
NCArray & operator=(const NCArray &rhs)
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
bool is_user_defined_type(int ncid, int type)