62 #define ATTR_STRING_QUOTE_FIX
64 #if NETCDF_VERSION >= 4
65 #define READ_ATTRIBUTES_MACRO read_attributes_netcdf4
67 #define READ_ATTRIBUTES_MACRO read_attributes_netcdf3
82 static string print_attr(nc_type type,
int loc,
void *vals)
97 #if NETCDF_VERSION >= 4
100 gp.cp = (
char *) vals;
110 gp.cp = (
char *) vals;
118 gp.cp = (
char *) vals;
126 #ifndef ATTR_STRING_QUOTE_FIX
127 rep <<
"\"" << escattr(static_cast<const char*>(vals)) <<
"\"";
130 return escattr(static_cast<const char*> (vals));
133 #if NETCDF_VERSION >= 4
135 gp.stringp = (
char **) vals;
136 rep << *(gp.stringp + loc);
141 gp.sp = (
short *) vals;
142 rep << *(gp.sp + loc);
145 #if NETCDF_VERSION >= 4
147 gp.usp = (
unsigned short *) vals;
148 rep << *(gp.usp + loc);
154 rep << *(gp.i + loc);
157 #if NETCDF_VERSION >= 4
159 gp.ui = (
unsigned int *) vals;
160 rep << *(gp.ui + loc);
165 gp.fp = (
float *) vals;
167 rep << std::showpoint;
168 rep << std::setprecision(9);
170 rep << *(gp.fp + loc);
176 string tmp_value = rep.str();
177 if (tmp_value.find(
'.') == string::npos
178 && tmp_value.find(
'e') == string::npos
179 && tmp_value.find(
'E') == string::npos
180 && tmp_value.find(
"nan") == string::npos
181 && tmp_value.find(
"NaN") == string::npos
182 && tmp_value.find(
"NAN") == string::npos)
188 gp.dp = (
double *) vals;
189 rep << std::showpoint;
190 rep << std::setprecision(16);
191 rep << *(gp.dp + loc);
192 string tmp_value = rep.str();
193 if (tmp_value.find(
'.') == string::npos
194 && tmp_value.find(
'e') == string::npos
195 && tmp_value.find(
'E') == string::npos
196 && tmp_value.find(
"nan") == string::npos
197 && tmp_value.find(
"NaN") == string::npos
198 && tmp_value.find(
"NAN") == string::npos)
205 cerr <<
"The netcdf handler tried to print an attribute that has an unrecognized type. (1)" << endl;
207 throw InternalErr(__FILE__, __LINE__,
"The netcdf handler tried to print an attribute that has an unrecognized type. (1)");
220 static string print_type(nc_type datatype)
223 #if NETCDF_VERSION >= 4
229 #if NETCDF_VERSION >= 4
248 #if NETCDF_VERSION >= 4
262 #if NETCDF_VERSION >= 4
264 return "NC_COMPOUND";
267 #if NETCDF_VERSION >= 4
287 cerr <<
"The netcdf handler tried to print an attribute that has an unrecognized type. (2)" << endl;
289 throw InternalErr(__FILE__, __LINE__,
"The netcdf handler tried to print an attribute that has an unrecognized type. (2)");
300 static void append_values(
int ncid,
int v,
int len, nc_type datatype,
char *attrname, AttrTable *at)
304 #if NETCDF_VERSION >= 4
305 errstat = nc_inq_type(ncid, datatype, 0, &size);
306 if (errstat != NC_NOERR)
307 throw Error(errstat,
"Could not get the size for the type.");
309 size = nctypelen(datatype);
312 vector<char> value((len + 1) * size);
313 errstat = nc_get_att(ncid, v, attrname, &value[0]);
314 if (errstat != NC_NOERR) {
315 throw Error(errstat,
string(
"Could not get the value for attribute '") + attrname +
string(
"'"));
321 if (datatype == NC_CHAR) {
327 for (
int loc = 0; loc < len; loc++) {
328 string print_rep =
print_attr(datatype, loc, &value[0]);
329 at->append_attr(attrname, print_type(datatype), print_rep);
344 static void read_attributes_netcdf3(
int ncid,
int v,
int natts, AttrTable *at)
346 char attrname[MAX_NC_NAME];
349 int errstat = NC_NOERR;
351 for (
int a = 0; a < natts; ++a) {
352 errstat = nc_inq_attname(ncid, v, a, attrname);
353 if (errstat != NC_NOERR) {
354 string msg =
"Could not get the name for attribute ";
355 msg += long_to_string(a);
356 throw Error(errstat, msg);
361 errstat = nc_inq_att(ncid, v, attrname, &datatype, &len);
362 if (errstat != NC_NOERR) {
363 string msg =
"Could not get the name for attribute '";
364 msg += attrname + string(
"'");
365 throw Error(errstat, msg);
375 append_values(ncid, v, len, datatype, attrname, at);
380 cerr <<
"Unrecognized attribute type." << endl;
382 throw InternalErr(__FILE__, __LINE__,
"Unrecognized attribute type.");
388 #if NETCDF_VERSION >= 4
401 static void read_attributes_netcdf4(
int ncid,
int varid,
int natts, AttrTable *at)
403 BESDEBUG(
"nc",
"In read_attributes_netcdf4" << endl);
405 for (
int attr_num = 0; attr_num < natts; ++attr_num) {
406 int errstat = NC_NOERR;
408 char attrname[MAX_NC_NAME];
409 errstat = nc_inq_attname(ncid, varid, attr_num, attrname);
410 if (errstat != NC_NOERR)
411 throw Error(errstat,
"Could not get the name for attribute " + long_to_string(attr_num));
416 errstat = nc_inq_att(ncid, varid, attrname, &datatype, &len);
417 if (errstat != NC_NOERR)
418 throw Error(errstat,
"Could not get the name for attribute '" +
string(attrname) +
"'");
420 BESDEBUG(
"nc",
"nc_inq_att returned datatype = " << datatype << endl);
424 char type_name[NC_MAX_NAME+1];
429 errstat = nc_inq_user_type(ncid, datatype, type_name, &size, &base_type, &nfields, &class_type);
430 if (errstat != NC_NOERR)
431 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about a user-defined type (" + long_to_string(errstat) +
")."));
433 BESDEBUG(
"nc",
"Before switch(class_type)" << endl);
434 switch (class_type) {
437 vector<unsigned char> values((len + 1) * size);
439 int errstat = nc_get_att(ncid, varid, attrname, &values[0]);
440 if (errstat != NC_NOERR)
441 throw Error(errstat,
string(
"Could not get the value for attribute '") + attrname +
string(
"'"));
443 for (
size_t i = 0; i < nfields; ++i) {
444 char field_name[NC_MAX_NAME+1];
445 nc_type field_typeid;
447 nc_inq_compound_field(ncid, datatype, i, field_name, &field_offset, &field_typeid, 0, 0);
449 at->append_attr(field_name, print_type(field_typeid),
print_attr(field_typeid, 0, &values[0] + field_offset));
456 cerr <<
"in build_user_defined; found a vlen." << endl;
458 throw Error(
"The netCDF handler does not yet support the NC_VLEN type.");
462 vector<unsigned char> values((len + 1) * size);
464 int errstat = nc_get_att(ncid, varid, attrname, &values[0]);
465 if (errstat != NC_NOERR)
466 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]));
475 vector<unsigned char> values((len + 1) * size);
477 int errstat = nc_get_att(ncid, varid, attrname, &values[0]);
478 if (errstat != NC_NOERR)
479 throw Error(errstat,
string(
"Could not get the value for attribute '") + attrname +
string(
"'"));
482 errstat = nc_inq_enum(ncid, datatype, 0, &basetype,
484 if (errstat != NC_NOERR)
485 throw Error(errstat,
string(
"Could not get the size of the enum base type for '") + attrname +
string(
"'"));
487 for (
size_t i = 0; i < size; ++i)
488 at->append_attr(attrname, print_type(basetype),
print_attr(basetype, i, &values[0]));
494 throw InternalErr(__FILE__, __LINE__,
"Expected one of NC_COMPOUND, NC_VLEN, NC_OPAQUE or NC_ENUM");
497 BESDEBUG(
"nc",
"After switch(class-type)" << endl);
511 BESDEBUG(
"nc",
"Before append_values ..." << endl);
512 append_values(ncid, varid, len, datatype, attrname, at);
513 BESDEBUG(
"nc",
"After append_values ..." << endl);
518 string note =
"Attribute edlided: Unsupported attribute type ";
519 note +=
"(" + print_type(datatype) +
")";
520 at->append_attr(attrname,
"String", note);
528 throw InternalErr(__FILE__, __LINE__,
"user-defined attribute type not recognized as such!");
531 throw InternalErr(__FILE__, __LINE__,
"Unrecognized attribute type.");
535 BESDEBUG(
"nc",
"Exiting read_attributes_netcdf4" << endl);
550 BESDEBUG(
"nc",
"In nc_read_dataset_attributes" << endl);
553 errstat = nc_open(filename.c_str(), NC_NOWRITE, &ncid);
554 if (errstat != NC_NOERR)
555 throw Error(errstat,
"Could not open " + path_to_filename(filename) +
".");
559 errstat = nc_inq(ncid, (
int *) 0, &nvars, &ngatts, (
int *) 0);
560 if (errstat != NC_NOERR)
561 throw Error(errstat,
"Could not inquire about netcdf file: " + path_to_filename(filename) +
".");
564 char varname[MAX_NC_NAME];
567 for (
int varid = 0; varid < nvars; ++varid) {
568 BESDEBUG(
"nc",
"Top of for loop; for each var..." << endl);
570 errstat = nc_inq_var(ncid, varid, varname, &var_type, (
int*) 0, (
int*) 0, &natts);
571 if (errstat != NC_NOERR)
572 throw Error(errstat,
"Could not get information for variable: " + long_to_string(varid));
574 AttrTable *attr_table_ptr = das.get_table(varname);
576 attr_table_ptr = das.add_table(varname,
new AttrTable);
578 BESDEBUG(
"nc",
"Before READ_ATTRIBUTES_MACRO" << endl);
580 BESDEBUG(
"nc",
"After READ_ATTRIBUTES_MACRO" << endl);
583 if (var_type == NC_CHAR) {
586 int vdimids[MAX_VAR_DIMS];
587 errstat = nc_inq_var(ncid, varid, (
char *) 0, (nc_type *) 0, &num_dim, vdimids, (
int *) 0);
588 if (errstat != NC_NOERR)
589 throw Error(errstat,
string(
"Could not read information about a NC_CHAR variable while building the DAS."));
594 string print_rep =
print_attr(NC_INT, 0, (
void *) &size);
595 attr_table_ptr->append_attr(
"string_length", print_type(NC_INT), print_rep);
599 vector<size_t> dim_sizes(num_dim);
600 for (
int i = 0; i < num_dim; ++i) {
601 if ((errstat = nc_inq_dimlen(ncid, vdimids[i], &dim_sizes[i])) != NC_NOERR) {
602 throw Error(errstat,
string(
"Could not read dimension information about the variable `") + varname +
string(
"'."));
607 string print_rep =
print_attr(NC_INT, 0, (
void *) (&dim_sizes[num_dim - 1]));
608 attr_table_ptr->append_attr(
"string_length", print_type(NC_INT), print_rep);
612 #if NETCDF_VERSION >= 4
615 vector<char> name(MAX_NC_NAME + 1);
617 errstat = nc_inq_user_type(ncid, var_type, &name[0], 0, 0, 0, &class_type);
618 if (errstat != NC_NOERR)
619 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about a user-defined type (" + long_to_string(errstat) +
")."));
621 switch (class_type) {
623 attr_table_ptr->append_attr(
"DAP2_OriginalNetCDFBaseType", print_type(NC_STRING),
"NC_OPAQUE");
624 attr_table_ptr->append_attr(
"DAP2_OriginalNetCDFTypeName", print_type(NC_STRING), &name[0]);
630 nc_type base_nc_type;
631 size_t base_size, num_members;
632 errstat = nc_inq_enum(ncid, var_type, 0, &base_nc_type, &base_size, &num_members);
633 if (errstat != NC_NOERR)
634 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about an enum(" + long_to_string(errstat) +
")."));
638 if (base_nc_type == NC_INT64 || base_nc_type == NC_UINT64) {
640 cerr <<
"An Enum uses 64-bit integers, but this handler does not support that type." << endl;
642 throw Error(
"An Enum uses 64-bit integers, but this handler does not support that type.");
646 for (
size_t i = 0; i < num_members; ++i) {
647 vector<char> member_name(MAX_NC_NAME + 1);
648 vector<char> member_value(base_size);
649 errstat = nc_inq_enum_member(ncid, var_type, i, &member_name[0], &member_value[0]);
650 if (errstat != NC_NOERR)
651 throw(InternalErr(__FILE__, __LINE__,
"Could not get information about an enum value (" + long_to_string(errstat) +
")."));
652 attr_table_ptr->append_attr(
"DAP2_EnumValues", print_type(base_nc_type),
print_attr(base_nc_type, 0, &member_value[0]));
653 attr_table_ptr->append_attr(
"DAP2_EnumNames", print_type(NC_STRING), &member_name[0]);
656 attr_table_ptr->append_attr(
"DAP2_OriginalNetCDFBaseType", print_type(NC_STRING),
"NC_ENUM");
657 attr_table_ptr->append_attr(
"DAP2_OriginalNetCDFTypeName", print_type(NC_STRING), &name[0]);
666 #endif // NETCDF_VERSION >= 4
669 BESDEBUG(
"nc",
"Starting global attributes" << endl);
673 AttrTable *attr_table_ptr = das.add_table(
"NC_GLOBAL",
new AttrTable);
679 char dimname[MAX_NC_NAME];
680 nc_type datatype = NC_CHAR;
681 nc_inq(ncid, (
int *) 0, (
int *) 0, (
int *) 0, &xdimid);
683 nc_inq_dim(ncid, xdimid, dimname, (
size_t *) 0);
684 string print_rep =
print_attr(datatype, 0, dimname);
685 AttrTable *attr_table_ptr = das.add_table(
"DODS_EXTRA",
new AttrTable);
686 attr_table_ptr->append_attr(
"Unlimited_Dimension", print_type(datatype), print_rep);
689 if (nc_close(ncid) != NC_NOERR)
690 throw InternalErr(__FILE__, __LINE__,
"ncdds: Could not close the dataset!");
692 BESDEBUG(
"nc",
"Exiting nc_read_dataset_attributes" << endl);
#define READ_ATTRIBUTES_MACRO
static class NCMLUtil overview
void nc_read_dataset_attributes(DAS &das, const string &filename)
Given a reference to an instance of class DAS and a filename that refers to a netcdf file...
static bool get_ignore_unknown_types()
static bool get_promote_byte_to_short()
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
bool is_user_defined_type(int ncid, int type)
string print_attr(hid_t type, int loc, void *sm_buf)
will get the printed representation of an attribute.