43 #include "config_nc.h"
59 #include "NCRequestHandler.h"
62 #define ATTR_STRING_QUOTE_FIX
64 #define NETCDF_VERSION 4
66 #if NETCDF_VERSION >= 4
67 #define READ_ATTRIBUTES_MACRO read_attributes_netcdf4
69 #define READ_ATTRIBUTES_MACRO read_attributes_netcdf3
84 static string print_attr(nc_type type,
int loc,
void *vals)
99 #if NETCDF_VERSION >= 4
102 gp.cp = (
char *) vals;
110 if (NCRequestHandler::get_promote_byte_to_short()) {
112 gp.cp = (
char *) vals;
120 gp.cp = (
char *) vals;
128 #ifndef ATTR_STRING_QUOTE_FIX
129 rep <<
"\"" << escattr(
static_cast<const char*
>(vals)) <<
"\"";
132 return escattr(
static_cast<const char*
>(vals));
135 #if NETCDF_VERSION >= 4
137 gp.stringp = (
char **) vals;
138 rep << *(gp.stringp + loc);
143 gp.sp = (
short *) vals;
144 rep << *(gp.sp + loc);
147 #if NETCDF_VERSION >= 4
149 gp.usp = (uint16_t *) vals;
150 rep << *(gp.usp + loc);
155 gp.i = (int32_t *) vals;
156 rep << *(gp.i + loc);
159 #if NETCDF_VERSION >= 4
161 gp.ui = (uint32_t *) vals;
162 rep << *(gp.ui + loc);
167 gp.fp = (
float *) vals;
168 float valAtLoc = *(gp.fp + loc);
170 rep << std::showpoint;
171 rep << std::setprecision(9);
173 if (::isnan(valAtLoc)) {
184 string tmp_value = rep.str();
185 if (tmp_value.find(
'.') == string::npos && tmp_value.find(
'e') == string::npos && tmp_value.find(
'E') == string::npos
186 && tmp_value.find(
"nan") == string::npos && tmp_value.find(
"NaN") == string::npos && tmp_value.find(
"NAN") == string::npos) rep <<
".";
191 gp.dp = (
double *) vals;
192 double valAtLoc = *(gp.dp + loc);
194 rep << std::showpoint;
195 rep << std::setprecision(16);
197 if (::isnan(valAtLoc)) {
203 string tmp_value = rep.str();
204 if (tmp_value.find(
'.') == string::npos && tmp_value.find(
'e') == string::npos && tmp_value.find(
'E') == string::npos
205 && tmp_value.find(
"nan") == string::npos && tmp_value.find(
"NaN") == string::npos && tmp_value.find(
"NAN") == string::npos) rep <<
".";
210 if (NCRequestHandler::get_ignore_unknown_types())
211 cerr <<
"The netcdf handler tried to print an attribute that has an unrecognized type. (1)" << endl;
213 throw InternalErr(__FILE__, __LINE__,
"The netcdf handler tried to print an attribute that has an unrecognized type. (1)");
226 static string print_type(nc_type datatype)
229 #if NETCDF_VERSION >= 4
235 #if NETCDF_VERSION >= 4
240 if (NCRequestHandler::get_promote_byte_to_short()) {
253 #if NETCDF_VERSION >= 4
267 #if NETCDF_VERSION >= 4
269 return "NC_COMPOUND";
272 #if NETCDF_VERSION >= 4
291 if (NCRequestHandler::get_ignore_unknown_types())
292 cerr <<
"The netcdf handler tried to print an attribute that has an unrecognized type. (2)" << endl;
294 throw InternalErr(__FILE__, __LINE__,
"The netcdf handler tried to print an attribute that has an unrecognized type. (2)");
305 static void append_values(
int ncid,
int v,
int len, nc_type datatype,
char *attrname, AttrTable *at)
309 #if NETCDF_VERSION >= 4
310 errstat = nc_inq_type(ncid, datatype, 0, &size);
311 if (errstat != NC_NOERR)
throw Error(errstat,
"Could not get the size for the type.");
313 size = nctypelen(datatype);
316 vector<char> value((len + 1) * size);
317 errstat = nc_get_att(ncid, v, attrname, &value[0]);
318 if (errstat != NC_NOERR) {
319 throw Error(errstat,
string(
"Could not get the value for attribute '") + attrname +
string(
"'"));
325 if (datatype == NC_CHAR) {
331 for (
int loc = 0; loc < len; loc++) {
332 string print_rep =
print_attr(datatype, loc, &value[0]);
333 at->append_attr(attrname, print_type(datatype), print_rep);
348 static void read_attributes_netcdf3(
int ncid,
int v,
int natts, AttrTable *at)
350 char attrname[MAX_NC_NAME];
353 int errstat = NC_NOERR;
355 for (
int a = 0; a < natts; ++a) {
356 errstat = nc_inq_attname(ncid, v, a, attrname);
357 if (errstat != NC_NOERR) {
358 string msg =
"Could not get the name for attribute ";
359 msg += long_to_string(a);
360 throw Error(errstat, msg);
365 errstat = nc_inq_att(ncid, v, attrname, &datatype, &len);
366 if (errstat != NC_NOERR) {
367 string msg =
"Could not get the name for attribute '";
368 msg += attrname + string(
"'");
369 throw Error(errstat, msg);
379 append_values(ncid, v, len, datatype, attrname, at);
383 if (NCRequestHandler::get_ignore_unknown_types())
384 cerr <<
"Unrecognized attribute type." << endl;
386 throw InternalErr(__FILE__, __LINE__,
"Unrecognized attribute type.");
392 #if NETCDF_VERSION >= 4
405 static void read_attributes_netcdf4(
int ncid,
int varid,
int natts, AttrTable *at)
407 BESDEBUG(
"nc",
"In read_attributes_netcdf4" << endl);
409 for (
int attr_num = 0; attr_num < natts; ++attr_num) {
410 int errstat = NC_NOERR;
412 char attrname[MAX_NC_NAME];
413 errstat = nc_inq_attname(ncid, varid, attr_num, attrname);
414 if (errstat != NC_NOERR)
throw Error(errstat,
"Could not get the name for attribute " + long_to_string(attr_num));
419 errstat = nc_inq_att(ncid, varid, attrname, &datatype, &len);
420 if (errstat != NC_NOERR)
throw Error(errstat,
"Could not get the name for attribute '" +
string(attrname) +
"'");
422 BESDEBUG(
"nc",
"nc_inq_att returned datatype = " << datatype <<
" for '" << attrname <<
"'" << endl);
425 if (datatype >= NC_FIRSTUSERTYPEID) {
426 char type_name[NC_MAX_NAME + 1];
431 errstat = nc_inq_user_type(ncid, datatype, type_name, &size, &base_type, &nfields, &class_type);
432 if (errstat != NC_NOERR)
433 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about a user-defined type (" + long_to_string(errstat) +
")."));
435 BESDEBUG(
"nc",
"Before switch(class_type)" << endl);
436 switch (class_type) {
439 vector<unsigned char> values((len + 1) * size);
441 int errstat = nc_get_att(ncid, varid, attrname, &values[0]);
442 if (errstat != NC_NOERR)
throw Error(errstat,
string(
"Could not get the value for attribute '") + attrname +
string(
"'"));
444 for (
size_t i = 0; i < nfields; ++i) {
445 char field_name[NC_MAX_NAME + 1];
446 nc_type field_typeid;
448 nc_inq_compound_field(ncid, datatype, i, field_name, &field_offset, &field_typeid, 0, 0);
450 at->append_attr(field_name, print_type(field_typeid),
print_attr(field_typeid, 0, &values[0] + field_offset));
456 if (NCRequestHandler::get_ignore_unknown_types())
457 cerr <<
"in build_user_defined; found a vlen." << endl;
459 throw Error(
"The netCDF handler does not yet support the NC_VLEN type.");
463 vector<unsigned char> values((len + 1) * size);
465 int errstat = nc_get_att(ncid, varid, attrname, &values[0]);
466 if (errstat != NC_NOERR)
throw Error(errstat,
string(
"Could not get the value for attribute '") + attrname +
string(
"'"));
468 for (
size_t i = 0; i < size; ++i)
469 at->append_attr(attrname, print_type(NC_BYTE),
print_attr(NC_BYTE, i, &values[0]));
477 size_t base_size, num_members;
478 errstat = nc_inq_enum(ncid, datatype, 0, &basetype, &base_size, &num_members);
479 if (errstat != NC_NOERR)
throw Error(errstat,
string(
"Could not get the size of the enum base type for '") + attrname +
string(
"'"));
481 vector<unsigned char> values((len + 1) * size);
483 int errstat = nc_get_att(ncid, varid, attrname, &values[0]);
484 if (errstat != NC_NOERR)
throw Error(errstat,
string(
"Could not get the value for attribute '") + attrname +
string(
"'"));
486 for (
size_t i = 0; i < len; ++i)
487 at->append_attr(attrname, print_type(base_type),
print_attr(base_type, i, &values[0]));
493 throw InternalErr(__FILE__, __LINE__,
"Expected one of NC_COMPOUND, NC_VLEN, NC_OPAQUE or NC_ENUM");
496 BESDEBUG(
"nc",
"After switch(class-type)" << endl);
510 BESDEBUG(
"nc",
"Before append_values ..." << endl);
511 append_values(ncid, varid, len, datatype, attrname, at);
512 BESDEBUG(
"nc",
"After append_values ..." << endl);
517 string note =
"Attribute edlided: Unsupported attribute type ";
518 note +=
"(" + print_type(datatype) +
")";
519 at->append_attr(attrname,
"String", note);
527 throw InternalErr(__FILE__, __LINE__,
"user-defined attribute type not recognized as such!");
530 throw InternalErr(__FILE__, __LINE__,
"Unrecognized attribute type.");
534 BESDEBUG(
"nc",
"Exiting read_attributes_netcdf4" << endl);
547 void nc_read_dataset_attributes(DAS &das,
const string &filename)
549 BESDEBUG(
"nc",
"In nc_read_dataset_attributes" << endl);
552 errstat = nc_open(filename.c_str(), NC_NOWRITE, &ncid);
553 if (errstat != NC_NOERR)
throw Error(errstat,
"NetCDF handler: Could not open " + filename +
".");
557 errstat = nc_inq(ncid, (
int *) 0, &nvars, &ngatts, (
int *) 0);
558 if (errstat != NC_NOERR)
throw Error(errstat,
"NetCDF handler: Could not inquire about netcdf file: " + path_to_filename(filename) +
".");
561 char varname[MAX_NC_NAME];
564 for (
int varid = 0; varid < nvars; ++varid) {
565 BESDEBUG(
"nc",
"Top of for loop; for each var..." << endl);
567 errstat = nc_inq_var(ncid, varid, varname, &var_type, (
int*) 0, (
int*) 0, &natts);
568 if (errstat != NC_NOERR)
throw Error(errstat,
"Could not get information for variable: " + long_to_string(varid));
570 AttrTable *attr_table_ptr = das.get_table(varname);
571 if (!attr_table_ptr) attr_table_ptr = das.add_table(varname,
new AttrTable);
573 READ_ATTRIBUTES_MACRO(ncid, varid, natts, attr_table_ptr);
576 if (var_type == NC_CHAR) {
579 int vdimids[MAX_VAR_DIMS];
580 errstat = nc_inq_var(ncid, varid, (
char *) 0, (nc_type *) 0, &num_dim, vdimids, (
int *) 0);
581 if (errstat != NC_NOERR)
582 throw Error(errstat,
string(
"NetCDF handler: Could not read information about a NC_CHAR variable while building the DAS."));
587 string print_rep =
print_attr(NC_INT, 0, (
void *) &size);
588 attr_table_ptr->append_attr(
"string_length", print_type(NC_INT), print_rep);
592 vector<size_t> dim_sizes(num_dim);
593 for (
int i = 0; i < num_dim; ++i) {
594 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &dim_sizes[i])) != NC_NOERR) {
596 string(
"NetCDF handler: Could not read dimension information about the variable `") + varname +
string(
"'."));
601 string print_rep =
print_attr(NC_INT, 0, (
void *) (&dim_sizes[num_dim - 1]));
602 attr_table_ptr->append_attr(
"string_length", print_type(NC_INT), print_rep);
606 #if NETCDF_VERSION >= 4
607 else if (is_user_defined_type(ncid, var_type)) {
609 vector<char> name(MAX_NC_NAME + 1);
611 errstat = nc_inq_user_type(ncid, var_type, &name[0], 0, 0, 0, &class_type);
612 if (errstat != NC_NOERR)
613 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about a user-defined type (" + long_to_string(errstat) +
")."));
615 switch (class_type) {
617 attr_table_ptr->append_attr(
"DAP2_OriginalNetCDFBaseType", print_type(NC_STRING),
"NC_OPAQUE");
618 attr_table_ptr->append_attr(
"DAP2_OriginalNetCDFTypeName", print_type(NC_STRING), &name[0]);
624 nc_type base_nc_type;
625 size_t base_size, num_members;
626 errstat = nc_inq_enum(ncid, var_type, 0, &base_nc_type, &base_size, &num_members);
627 if (errstat != NC_NOERR)
628 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about an enum(" + long_to_string(errstat) +
")."));
632 if (base_nc_type == NC_INT64 || base_nc_type == NC_UINT64) {
633 if (NCRequestHandler::get_ignore_unknown_types())
634 cerr <<
"An Enum uses 64-bit integers, but this handler does not support that type." << endl;
636 throw Error(
"An Enum uses 64-bit integers, but this handler does not support that type.");
640 for (
size_t i = 0; i < num_members; ++i) {
641 vector<char> member_name(MAX_NC_NAME + 1);
642 vector<char> member_value(base_size);
643 errstat = nc_inq_enum_member(ncid, var_type, i, &member_name[0], &member_value[0]);
644 if (errstat != NC_NOERR)
645 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about an enum value (" + long_to_string(errstat) +
")."));
646 attr_table_ptr->append_attr(
"DAP2_EnumValues", print_type(base_nc_type),
print_attr(base_nc_type, 0, &member_value[0]));
647 attr_table_ptr->append_attr(
"DAP2_EnumNames", print_type(NC_STRING), &member_name[0]);
650 attr_table_ptr->append_attr(
"DAP2_OriginalNetCDFBaseType", print_type(NC_STRING),
"NC_ENUM");
651 attr_table_ptr->append_attr(
"DAP2_OriginalNetCDFTypeName", print_type(NC_STRING), &name[0]);
660 #endif // NETCDF_VERSION >= 4
663 BESDEBUG(
"nc",
"Starting global attributes" << endl);
667 AttrTable *attr_table_ptr = das.add_table(
"NC_GLOBAL",
new AttrTable);
668 READ_ATTRIBUTES_MACRO(ncid, NC_GLOBAL, ngatts, attr_table_ptr);
673 char dimname[MAX_NC_NAME];
674 nc_type datatype = NC_CHAR;
675 if ((errstat = nc_inq(ncid, (
int *) 0, (
int *) 0, (
int *) 0, &xdimid)) != NC_NOERR)
676 throw InternalErr(__FILE__, __LINE__,
string(
"NetCDF handler: Could not access variable information: ") + nc_strerror(errstat));
678 if ((errstat = nc_inq_dim(ncid, xdimid, dimname, (
size_t *) 0)) != NC_NOERR)
679 throw InternalErr(__FILE__, __LINE__,
string(
"NetCDF handler: Could not access dimension information: ") + nc_strerror(errstat));
680 string print_rep =
print_attr(datatype, 0, dimname);
681 AttrTable *attr_table_ptr = das.add_table(
"DODS_EXTRA",
new AttrTable);
682 attr_table_ptr->append_attr(
"Unlimited_Dimension", print_type(datatype), print_rep);
685 if (nc_close(ncid) != NC_NOERR)
throw InternalErr(__FILE__, __LINE__,
"NetCDF handler: Could not close the dataset!");
687 BESDEBUG(
"nc",
"Exiting nc_read_dataset_attributes" << endl);