bes Updated for version 3.20.10
FONcAttributes.cc
1// FONcAttributes.cc
2
3// This file is part of BES Netcdf File Out Module
4
5// Copyright (c) 2004,2005 University Corporation for Atmospheric Research
6// Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
7//
8// This library is free software; you can redistribute it and/or
9// modify it under the terms of the GNU Lesser General Public
10// License as published by the Free Software Foundation; either
11// version 2.1 of the License, or (at your option) any later version.
12//
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// Lesser General Public License for more details.
17//
18// You should have received a copy of the GNU Lesser General Public
19// License along with this library; if not, write to the Free Software
20// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21//
22// You can contact University Corporation for Atmospheric Research at
23// 3080 Center Green Drive, Boulder, CO 80301
24
25// (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
26// Please read the full copyright statement in the file COPYRIGHT_UCAR.
27//
28// Authors:
29// pwest Patrick West <pwest@ucar.edu>
30// jgarcia Jose Garcia <jgarcia@ucar.edu>
31
32#include <sstream>
33
34using std::istringstream;
35
36#include <netcdf.h>
37
38#include <BESDebug.h>
39#include <BESInternalError.h>
40#include <BESUtil.h>
41#include <cstdlib>
42
43#include "DapFunctionUtils.h"
44
45#include "FONcAttributes.h"
46#include "FONcUtils.h"
47
79void FONcAttributes::add_variable_attributes(int ncid, int varid, BaseType *b, bool is_nc_enhanced,bool is_dap4) {
80 string emb_name;
81 BaseType *parent = b->get_parent();
82 if (parent) {
83 //BESDEBUG("dap", "FONcAttributes::parent name is "<< parent->name() <<endl);
84 //BESDEBUG("dap", "FONcAttributes::parent type is "<< parent->type() <<endl);
85 if(true != is_dap4 || parent->type()!=dods_group_c)
86 FONcAttributes::add_variable_attributes_worker(ncid, varid, parent, emb_name, is_nc_enhanced,is_dap4);
87 }
88 // addattrs_workerA(ncid, varid, b, "");
89 // Add DAP4 attribute support by using attributes().
90
91 BESDEBUG("dap", "FONcAttributes::add_variable_attributes() after parent "<<endl);
92 if(is_dap4)
93 add_dap4_attributes(ncid, varid, b->attributes(), b->name(), "", is_nc_enhanced);
94 else
95 add_attributes(ncid, varid, b->get_attr_table(), b->name(), "", is_nc_enhanced);
96
97}
98
113void FONcAttributes::add_variable_attributes_worker(int ncid, int varid, BaseType *b, string &emb_name,
114 bool is_nc_enhanced,bool is_dap4) {
115
116 BaseType *parent = b->get_parent();
117 if (parent) {
118 FONcAttributes::add_variable_attributes_worker(ncid, varid, parent, emb_name, is_nc_enhanced,is_dap4);
119 }
120 if (!emb_name.empty()) {
121 emb_name += FONC_EMBEDDED_SEPARATOR;
122 }
123 emb_name += b->name();
124 // addattrs_workerA(ncid, varid, b, emb_name);
125 if(is_dap4)
126 add_dap4_attributes(ncid, varid, b->attributes(), b->name(), emb_name, is_nc_enhanced);
127 else
128 add_attributes(ncid, varid, b->get_attr_table(), b->name(), emb_name, is_nc_enhanced);
129}
130
131
146void FONcAttributes::add_attributes(int ncid, int varid, AttrTable &attrs, const string &var_name,
147 const string &prepend_attr, bool is_nc_enhanced) {
148
149 unsigned int num_attrs = attrs.get_size();
150 if (num_attrs) {
151 AttrTable::Attr_iter i = attrs.attr_begin();
152 AttrTable::Attr_iter e = attrs.attr_end();
153 for (; i != e; i++) {
154 unsigned int num_vals = attrs.get_attr_num(i);
155 if (num_vals) {
156 add_attributes_worker(ncid, varid, var_name, attrs, i, prepend_attr, is_nc_enhanced);
157 }
158 }
159 }
160}
161
176//void FONcAttributes::add_dap4_attributes(int ncid, int varid, AttrTable &attrs, const string &var_name,
177void FONcAttributes::add_dap4_attributes(int ncid, int varid, D4Attributes *d4_attrs, const string &var_name,
178 const string &prepend_attr, bool is_nc_enhanced) {
179
180 BESDEBUG("dap", "FONcAttributes::add_dap4_attributes() number of attributes "<< d4_attrs <<endl);
181 for (D4Attributes::D4AttributesIter ii = d4_attrs->attribute_begin(), ee = d4_attrs->attribute_end(); ii != ee; ++ii) {
182 string name = (*ii)->name();
183 //BESDEBUG("dap", "FONcAttributes:: attribute name is "<<name <<endl);
184 unsigned int num_vals = (*ii)->num_values();
185 //BESDEBUG("dap", "FONcAttributes:: num_vals is "<<num_vals <<endl);
186 // d4_attrs includes all the global containers' attributes, which is not right.
187 if (num_vals || varid == NC_GLOBAL)
188 add_dap4_attributes_worker(ncid, varid, var_name, *ii, prepend_attr, is_nc_enhanced);
189 }
190}
191
205void FONcAttributes::add_attributes_worker(int ncid, int varid, const string &var_name,
206 AttrTable &attrs, AttrTable::Attr_iter &attr,
207 const string &prepend_attr, bool is_nc_enhanced) {
208
209 AttrType attrType = attrs.get_attr_type(attr);
210
211 string attr_name = attrs.get_name(attr);
212 string new_attr_name("");
213 if (!prepend_attr.empty()) {
214 new_attr_name = prepend_attr + FONC_EMBEDDED_SEPARATOR + attr_name;
215 } else {
216
217 // If we're doing global attributes AND it's an attr table, and its name is "special"
218 // (ends with "_GLOBAL"), then we suppress the use of the attrTable name in
219 // the NetCDF Attributes name.
220 if (varid == NC_GLOBAL && attrType == Attr_container && BESUtil::endsWith(attr_name, "_GLOBAL")) {
221 BESDEBUG("fonc",
222 "Suppressing global AttributeTable name '" << attr_name
223 << "' from inclusion in NetCDF attributes namespace chain."
224 << endl);
225 new_attr_name = "";
226 } else {
227 new_attr_name = attr_name;
228 }
229 }
230
231//Note: Leave the following #if 0 #endif block for the time being. Don't change to NBEBUG.
232#if 0
233 // This was the old way of doing it and it polluted the attribute names
234 // by prepending full qualified variable names to the attribute name..
235 string new_name = new_attr_name;
236 if (!var_name.empty()) {
237 new_name = var_name + FONC_ATTRIBUTE_SEPARATOR + new_attr_name;
238 }
239
240 // BESDEBUG("fonc","new_name: " << new_name << " new_attr_name: " << new_attr_name << " var_name: " << var_name << endl);
241
242 new_name = FONcUtils::id2netcdf(new_name);
243#endif
244
245 string new_name = FONcUtils::id2netcdf(new_attr_name);;
246 BESDEBUG("fonc", "FONcAttributes name: " << new_name << endl);
247 BESDEBUG("fonc", "FONcAttributes type: " << attrType << endl);
248
249
250 if (varid == NC_GLOBAL) {
251 BESDEBUG("fonc", "FONcAttributes::add_attrbutes_worker() - Adding global attributes " << attr_name << endl);
252 } else {
253 BESDEBUG("fonc", "FONcAttributes::add_attributes_worker() - Adding attribute " << new_name << endl);
254 }
255
256 // If we want to map the attributes of the datatypes to those of netCDF-4, KY 2020-02-14
257 if (is_nc_enhanced == true)
258 write_attrs_for_nc4_types(ncid, varid, var_name, new_attr_name, new_name, attrs, attr, is_nc_enhanced);
259 else {
260 int stax = NC_NOERR;
261 unsigned int attri = 0;
262 unsigned int num_vals = attrs.get_attr_num(attr);
263 switch (attrType) {
264 case Attr_container: {
265 // flatten
266 BESDEBUG("fonc",
267 "Attribute " << attr_name << " is an attribute container. new_attr_name: \"" << new_attr_name
268 << "\"" << endl);
269 AttrTable *container = attrs.get_attr_table(attr);
270 if (container) {
271 add_attributes(ncid, varid, *container, var_name, new_attr_name, is_nc_enhanced);
272 }
273 }
274 break;
275 case Attr_byte: {
276 // unsigned char
277 // This should be converted to short to be consistent with the array.
278 // The classic model doesn't support unsigned char.
279 vector<short>vals;
280 vals.resize(num_vals);
281 for (attri = 0; attri < num_vals; attri++) {
282 string val = attrs.get_attr(attr, attri);
283 istringstream is(val);
284 unsigned int uival = 0;
285 is >> uival;
286 vals[attri] = (short) uival;
287 }
288 stax = nc_put_att_short(ncid, varid, new_name.c_str(), NC_SHORT,
289 num_vals, &vals[0]);
290 if (stax != NC_NOERR) {
291 string err = (string) "File out netcdf, "
292 + "failed to write byte attribute " + new_name;
293 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
294 }
295 }
296 break;
297 case Attr_int16: {
298 // short
299 vector<short>vals;
300 vals.resize(num_vals);
301 for (attri = 0; attri < num_vals; attri++) {
302 string val = attrs.get_attr(attr, attri);
303 istringstream is(val);
304 short sval = 0;
305 is >> sval;
306 vals[attri] = sval;
307 }
308 stax = nc_put_att_short(ncid, varid, new_name.c_str(), NC_SHORT,
309 num_vals, &vals[0]);
310 if (stax != NC_NOERR) {
311 string err = (string) "File out netcdf, "
312 + "failed to write short attribute " + new_name;
313 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
314 }
315 }
316 break;
317 case Attr_uint16: {
318 // unsigned short
319 // (needs to be big enough to store an unsigned short
320 vector<int>vals;
321 vals.resize(num_vals);
322 for (attri = 0; attri < num_vals; attri++) {
323 string val = attrs.get_attr(attr, attri);
324 istringstream is(val);
325 int ival = 0;
326 is >> ival;
327 vals[attri] = ival;
328 }
329 stax = nc_put_att_int(ncid, varid, new_name.c_str(), NC_INT, num_vals,
330 &vals[0]);
331 if (stax != NC_NOERR) {
332 string err = (string) "File out netcdf, "
333 + "failed to write unsinged short attribute " + new_name;
334 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
335 }
336 }
337 break;
338 case Attr_int32: {
339 // int
340 vector<int> vals;
341 vals.resize(num_vals);
342 for (attri = 0; attri < num_vals; attri++) {
343 string val = attrs.get_attr(attr, attri);
344 istringstream is(val);
345 int ival = 0;
346 is >> ival;
347 vals[attri] = ival;
348 }
349 stax = nc_put_att_int(ncid, varid, new_name.c_str(), NC_INT, num_vals,
350 &vals[0]);
351 if (stax != NC_NOERR) {
352 string err = (string) "File out netcdf, "
353 + "failed to write int attribute " + new_name;
354 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
355 }
356 }
357 break;
358 case Attr_uint32: {
359 // uint
360 // needs to be big enough to store an unsigned int
361 string err = (string) "File out netcdf, "
362 + "failed to write unsigned int attribute " + new_name;
363 err = err + " for classic model because of potential overflow. ";
364 err = err + " Please use the netCDF4 enhanced model. ";
365 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
366 // Note: the following #if 0 #endif is for reminder to developers only.
367 // Don't change it to NBEDBUG.
368#if 0
369 vector<int>vals;
370 vals.resize(num_vals);
371 for (attri = 0; attri < num_vals; attri++) {
372 string val = attrs.get_attr(attr, attri);
373 istringstream is(val);
374 int lval = 0;
375 is >> lval;
376 vals[attri] = lval;
377 }
378 stax = nc_put_att_int(ncid, varid, new_name.c_str(), NC_INT, num_vals,
379 &vals[0]);
380 if (stax != NC_NOERR) {
381 string err = (string) "File out netcdf, "
382 + "failed to write unsigned int attribute " + new_name;
383 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
384 }
385#endif
386 }
387 break;
388 case Attr_float32: {
389 // float
390 vector<float> vals;
391 vals.resize(num_vals);
392 for (attri = 0; attri < num_vals; attri++) {
393 string val = attrs.get_attr(attr, attri);
394 const char *cval = val.c_str();
395 //istringstream is(val);
396 float fval = 0;
397 fval = strtod(cval,NULL);
398 //is >> fval;
399 vals[attri] = fval;
400 }
401 stax = nc_put_att_float(ncid, varid, new_name.c_str(), NC_FLOAT,
402 num_vals, &vals[0]);
403 if (stax != NC_NOERR) {
404 string err = (string) "File out netcdf, "
405 + "failed to write float attribute " + new_name;
406 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
407 }
408 }
409 break;
410 case Attr_float64: {
411 // double
412 vector<double>vals;
413 vals.resize(num_vals);
414 for (attri = 0; attri < num_vals; attri++) {
415 string val = attrs.get_attr(attr, attri);
416 const char *cval = val.c_str();
417 //istringstream is(val);
418 double dval = 0;
419 dval = strtod(cval,NULL);
420 //is >> dval;
421 vals[attri] = dval;
422 }
423 stax = nc_put_att_double(ncid, varid, new_name.c_str(), NC_DOUBLE,
424 num_vals, &vals[0]);
425 if (stax != NC_NOERR) {
426 string err = (string) "File out netcdf, "
427 + "failed to write double attribute " + new_name;
428 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
429 }
430 }
431 break;
432 case Attr_string:
433 case Attr_url:
434 case Attr_other_xml: // Added. jhrg 12.27.2011
435 {
436 // string
437 string val = attrs.get_attr(attr, 0);
438 for (attri = 1; attri < num_vals; attri++) {
439 val += "\n" + attrs.get_attr(attr, attri);
440 }
441 if (attr_name != _FillValue) {
442 stax = nc_put_att_text(ncid, varid, new_name.c_str(), val.length(), val.c_str());
443 } else {
444 BESDEBUG("fonc",
445 "FONcAttributes::add_attributes_worker - Original attribute value is first character: "
446 << val.c_str()[0] << endl);
447 stax = nc_put_att_text(ncid, varid, new_name.c_str(), 1, val.c_str());
448 if (stax == NC_NOERR) {
449 // New name for attribute _FillValue with original value
450 string new_name_fillvalue = "Orig_FillValue";
451 BESDEBUG("fonc",
452 "FONcAttributes::add_attributes_worker - New attribute value is original value: "
453 << val.c_str() << endl);
454 // This line causes the segmentation fault since attrs is changed and the original iterator of attrs doesn't exist anymore.
455 // So it causes the segmentation fault when next attribute is fetched in the for loop of the add_attributes(). KY 2019-12-13
456#if 0
457 attrs.append_attr(new_name_fillvalue,"String", val);
458#endif
459 stax = nc_put_att_text(ncid, varid, new_name_fillvalue.c_str(), val.length(), val.c_str());
460 }
461 }
462
463 if (stax != NC_NOERR) {
464 string err = (string) "File out netcdf, "
465 + "failed to write string attribute " + new_name;
466 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
467 }
468 }
469 break;
470
471 case Attr_unknown: {
472 string err = (string) "File out netcdf, "
473 + "failed to write unknown type of attribute " + new_name;
474 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
475 }
476 break;
477 }
478 }
479}
480
493void FONcAttributes::add_dap4_attributes_worker(int ncid, int varid, const string &var_name,
494 D4Attribute* attr,
495 const string &prepend_attr, bool is_nc_enhanced) {
496 D4AttributeType d4_attr_type = attr->type();
497
498 string d4_attr_name = attr->name();
499 BESDEBUG("dap", "FONcAttributes:: D4 attribute name is "<<d4_attr_name <<endl);
500 string new_attr_name("");
501 if (!prepend_attr.empty()) {
502 new_attr_name = prepend_attr + FONC_EMBEDDED_SEPARATOR + d4_attr_name;
503 BESDEBUG("dap", "FONcAttributes:: D4 new attribute name is "<<new_attr_name <<endl);
504
505 } else {
506
507 // If we're doing global attributes AND it's an attr table, and its name is "special"
508 // (ends with "_GLOBAL"), then we suppress the use of the attrTable name in
509 // the NetCDF Attributes name.
510 if (varid == NC_GLOBAL && d4_attr_type == attr_container_c && (BESUtil::endsWith(d4_attr_name, "_GLOBAL") ||
511 BESUtil::endsWith(d4_attr_name, "HDF5_GLOBAL_integer_64"))) {
512 BESDEBUG("fonc",
513 "Suppressing global AttributeTable name '" << d4_attr_name
514 << "' from inclusion in NetCDF attributes namespace chain."
515 << endl);
516 new_attr_name = "";
517 } else {
518 new_attr_name = d4_attr_name;
519 }
520 }
521
522
523//Note: Leave the following #if 0 #endif block for the time being. Don't change to NBEBUG.
524#if 0
525 // This was the old way of doing it and it polluted the attribute names
526 // by prepending full qualified variable names to the attribute name..
527 string new_name = new_attr_name;
528 if (!var_name.empty()) {
529 new_name = var_name + FONC_ATTRIBUTE_SEPARATOR + new_attr_name;
530 }
531
532 // BESDEBUG("fonc","new_name: " << new_name << " new_attr_name: " << new_attr_name << " var_name: " << var_name << endl);
533
534 new_name = FONcUtils::id2netcdf(new_name);
535#endif
536
537 string new_name = FONcUtils::id2netcdf(new_attr_name);;
538
539#if !NDEBUG
540 if (varid == NC_GLOBAL) {
541 BESDEBUG("fonc", "FONcAttributes::addattrs() - Adding global attributes " << d4_attr_name << endl);
542 } else {
543 BESDEBUG("fonc", "FONcAttributes::addattrs() - Adding attribute " << new_name << endl);
544 }
545#endif
546
547 // If we want to map the attributes of the datatypes to those of netCDF-4, KY 2020-02-14
548 if (is_nc_enhanced == true)
549 //write_dap4_attrs_for_nc4_types(ncid, varid, var_name, new_attr_name, new_name, d4_attrs, attr, is_nc_enhanced);
550 write_dap4_attrs_for_nc4_types(ncid, varid, var_name, new_attr_name, new_name, attr, is_nc_enhanced);
551 else {
552 int stax = NC_NOERR;
553 string attr_type = "unknown"; // Used for error messages. jhrg 6/18/20
554 unsigned int attri = 0;
555 //unsigned int num_vals = attrs.get_attr_num(attr);
556 unsigned int num_vals = attr->num_values();
557 switch (d4_attr_type) {
558 case attr_container_c: {
559 // flatten
560 BESDEBUG("fonc",
561 "Attribute " << d4_attr_name << " is an attribute container. new_attr_name: \""
562 << new_attr_name
563 << "\"" << endl);
564 D4Attributes *c_attributes = attr->attributes();
565 if (c_attributes) {
566 add_dap4_attributes(ncid, varid, c_attributes, var_name, new_attr_name, is_nc_enhanced);
567 }
568
569 }
570 break;
571
572 case attr_int8_c:{
573
574 // 8-bit integer
575 vector<int8_t> vals;
576 vals.resize(num_vals);
577 attri = 0;
578 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
579 string val = *vi;
580 istringstream is(val);
581 int uival = 0;
582 is >> uival;
583 vals[attri] = (int8_t) uival;
584 ++attri;
585 }
586 stax = nc_put_att_schar(ncid, varid, new_name.c_str(), NC_BYTE,
587 num_vals, &vals[0]);
588 if (stax != NC_NOERR) {
589 string err = (string) "File out netcdf-4 classic for DAP4, "
590 + "failed to write signed 8-bit integer attribute " + new_name;
591 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
592 }
593 }
594 break;
595
596 case attr_byte_c:
597 case attr_uint8_c: {
598 vector<short> vals;
599 vals.resize(num_vals);
600 attri = 0;
601 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
602 string val = *vi;
603 istringstream is(val);
604 // Follow the classic code, the stringstream doesn't work well with int8,
605 // no overflow when casted back to vals.
606 unsigned int uival = 0;
607 is >> uival;
608 vals[attri] = (short) uival;
609 ++attri;
610 }
611 stax = nc_put_att_short(ncid, varid, new_name.c_str(), NC_SHORT, num_vals, &vals[0]);
612
613 }
614 break;
615
616 case attr_int16_c: {
617 // short
618 vector<short> vals;
619 vals.resize(num_vals);
620 attri = 0;
621 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
622 string val = *vi;
623 istringstream is(val);
624 short sval = 0;
625 is >> sval;
626 vals[attri] = sval;
627 ++attri;
628 }
629
630 stax = nc_put_att_short(ncid, varid, new_name.c_str(), NC_SHORT, num_vals, &vals[0]);
631
632 break;
633 }
634
635 case attr_uint16_c: {
636 // unsigned short
637 // (needs to be big enough to store an unsigned short
638 attri = 0;
639 //int vals[num_vals];
640 vector<int> vals;
641 vals.resize(num_vals);
642 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
643 string val = *vi;
644 istringstream is(val);
645 int ival = 0;
646 is >> ival;
647 vals[attri] = ival;
648 ++attri;
649 }
650
651 stax = nc_put_att_int(ncid, varid, new_name.c_str(), NC_INT, num_vals, &vals[0]);
652
653 break;
654 }
655
656 case attr_int32_c: {
657 // int
658 vector<int>vals;
659 vals.resize(num_vals);
660 attri = 0;
661 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
662 string val = *vi;
663 istringstream is(val);
664 int sval = 0;
665 is >> sval;
666 vals[attri] = sval;
667 ++attri;
668 }
669
670 stax = nc_put_att_int(ncid, varid, new_name.c_str(), NC_INT, num_vals, &vals[0]);
671
672 break;
673 }
674
675 case attr_uint32_c: {
676 // uint
677 // needs to be big enough to store an unsigned int
678 vector<int>vals;
679 vals.resize(num_vals);
680 attri = 0;
681 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
682 string val = *vi;
683 istringstream is(val);
684 int sval = 0;
685 is >> sval;
686 vals[attri] = sval;
687 ++attri;
688 }
689
690 stax = nc_put_att_int(ncid, varid, new_name.c_str(), NC_INT, num_vals, &vals[0]);
691
692 break;
693 }
694
695 case attr_float32_c: {
696 // float
697 vector<float>vals;
698 vals.resize(num_vals);
699 attri = 0;
700 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
701 string val = *vi;
702 const char *cval = val.c_str();
703 //istringstream is(val);
704 float sval = 0;
705 sval = strtod(cval,NULL);
706 //is >> sval;
707 vals[attri] = sval;
708 ++attri;
709 }
710
711 stax = nc_put_att_float(ncid, varid, new_name.c_str(), NC_FLOAT, num_vals, &vals[0]);
712
713 break;
714 }
715
716 case attr_float64_c: {
717 // double
718 vector<double>vals;
719 vals.resize(num_vals);
720 attri = 0;
721 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
722 string val = *vi;
723 const char *cval = val.c_str();
724 //istringstream is(val);
725 double sval = 0;
726 sval = strtod(cval,NULL);
727 //is >> sval;
728 vals[attri] = sval;
729 ++attri;
730 }
731 stax = nc_put_att_double(ncid, varid, new_name.c_str(), NC_DOUBLE, num_vals, &vals[0]);
732
733 break;
734 }
735
736 case attr_str_c:
737 case attr_url_c:
738 case attr_otherxml_c: { // Added. jhrg 12.27.2011
739 attr_type = "string";
740 D4Attribute::D4AttributeIter vi, ve;
741 vi = attr->value_begin();
742 ve = attr->value_end();
743
744 string val = (*vi);
745
746 vi++;
747 for (; vi != ve; vi++) {
748 val += "\n" + *vi;
749 }
750
751 if (d4_attr_name != _FillValue) {
752 stax = nc_put_att_text(ncid, varid, new_name.c_str(), val.length(), val.c_str());
753 }
754 else {
755 BESDEBUG("fonc",
756 "FONcAttributes::add_attributes_worker - Original attribute value is first character: "
757 << val.c_str()[0] << endl);
758 stax = nc_put_att_text(ncid, varid, new_name.c_str(), 1, val.c_str());
759 if (stax == NC_NOERR) {
760 // New name for attribute _FillValue with original value
761 string new_name_fillvalue = "Orig_FillValue";
762 BESDEBUG("fonc",
763 "FONcAttributes::add_attributes_worker - New attribute value is original value: "
764 << val.c_str() << endl);
765 // This line causes the segmentation fault since attrs is changed and the original iterator of attrs doesn't exist anymore.
766 // So it causes the segmentation fault when next attribute is fetched in the for loop of the add_attributes(). KY 2019-12-13
767#if 0
768 attrs.append_attr(new_name_fillvalue,"String", val);
769#endif
770 stax = nc_put_att_text(ncid, varid, new_name_fillvalue.c_str(), val.length(), val.c_str());
771 }
772 }
773
774 break;
775 }
776
777 case attr_null_c:
778 case attr_int64_c:
779 case attr_uint64_c:
780 case attr_enum_c:
781 case attr_opaque_c:
782 default: {
783 // Temporarily don't support these types.TODO: add the support.
784 string err = (string) "File out netcdf, failed to write unknown/unsupported type of attribute " + new_name;
785 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
786 break;
787 }
788 }
789
790 if (stax != NC_NOERR) {
791 string err = (string) "File out netcdf, failed to write " + attr_type + " attribute " + new_name;
792 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
793 }
794 }
795}
796
797
811void FONcAttributes::add_original_name(int ncid, int varid,
812 const string &var_name, const string &orig) {
813 if (var_name != orig) {
814 string attr_name = FONC_ORIGINAL_NAME;
815 int stax = nc_put_att_text(ncid, varid, attr_name.c_str(),
816 orig.length(), orig.c_str());
817 if (stax != NC_NOERR) {
818 string err = (string) "File out netcdf, "
819 + "failed to write change of name attribute for "
820 + var_name;
821 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
822 }
823 }
824}
838void
839FONcAttributes::write_attrs_for_nc4_types(int ncid, int varid, const string &var_name, const string &global_attr_name,
840 const string &var_attr_name, AttrTable attrs, AttrTable::Attr_iter &attr,
841 bool is_nc_enhanced) {
842
843 int stax = NC_NOERR;
844 string attr_type = "unknown"; // Used for error messages. jhrg 6/18/20
845 AttrType attrType = attrs.get_attr_type(attr);
846 BESDEBUG("fonc", "FONcAttributes write_attrs_for_nc4_type name: " << var_attr_name << endl);
847 BESDEBUG("fonc", "FONcAttributes write_attrs_for_nc4_type type: " << attrType << endl);
848 unsigned int attri = 0;
849 unsigned int num_vals = attrs.get_attr_num(attr);
850 switch (attrType) {
851 case Attr_container: {
852 // flatten
853 BESDEBUG("fonc", "This is an attribute container. attr_name: \"" << global_attr_name << "\"" << endl);
854 AttrTable *container = attrs.get_attr_table(attr);
855 if (container) {
856 add_attributes(ncid, varid, *container, var_name, global_attr_name, is_nc_enhanced);
857 }
858 break;
859 }
860
861 case Attr_byte: {
862 // unsigned char
863 vector<unsigned char> vals;
864 vals.resize(num_vals);
865 for (attri = 0; attri < num_vals; attri++) {
866 string val = attrs.get_attr(attr, attri);
867 istringstream is(val);
868 unsigned int uival = 0;
869 is >> uival;
870 vals[attri] = (unsigned char) uival;
871 }
872 stax = nc_put_att_uchar(ncid, varid, var_attr_name.c_str(), NC_UBYTE,
873 num_vals, &vals[0]);
874#if !NDEBUG
875 if (stax != NC_NOERR) {
876 string err = (string) "File out netcdf, "
877 + "failed to write byte attribute " + var_attr_name;
878 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
879 }
880#endif
881 break;
882 }
883
884 case Attr_int16: {
885 // short
886 vector<short> vals;
887 vals.resize(num_vals);
888 for (attri = 0; attri < num_vals; attri++) {
889 string val = attrs.get_attr(attr, attri);
890 istringstream is(val);
891 short sval = 0;
892 is >> sval;
893 vals[attri] = sval;
894 }
895 stax = nc_put_att_short(ncid, varid, var_attr_name.c_str(), NC_SHORT, num_vals, &vals[0]);
896#if !NDEBUG
897 if (stax != NC_NOERR) {
898 string err = (string) "File out netcdf, "
899 + "failed to write short attribute " + var_attr_name;
900 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
901 }
902#endif
903
904 break;
905 }
906
907 case Attr_uint16: {
908 // unsigned short
909 // (needs to be big enough to store an unsigned short
910 //unsigned short vals[num_vals];
911 vector<unsigned short> vals;
912 vals.resize(num_vals);
913 for (attri = 0; attri < num_vals; attri++) {
914 string val = attrs.get_attr(attr, attri);
915 istringstream is(val);
916 unsigned short ival = 0;
917 is >> ival;
918 vals[attri] = ival;
919 }
920 stax = nc_put_att_ushort(ncid, varid, var_attr_name.c_str(), NC_USHORT, num_vals,
921 &vals[0]);
922#if !NDEBUG
923 if (stax != NC_NOERR) {
924 string err = (string) "File out netcdf, "
925 + "failed to write unsinged short attribute " + var_attr_name;
926 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
927 }
928#endif
929
930 break;
931 }
932
933 case Attr_int32: {
934 // int
935 //int vals[num_vals];
936 vector<int> vals;
937 vals.resize(num_vals);
938 for (attri = 0; attri < num_vals; attri++) {
939 string val = attrs.get_attr(attr, attri);
940 istringstream is(val);
941 int ival = 0;
942 is >> ival;
943 vals[attri] = ival;
944 }
945 stax = nc_put_att_int(ncid, varid, var_attr_name.c_str(), NC_INT, num_vals, &vals[0]);
946
947#if !NDEBUG
948 if (stax != NC_NOERR) {
949 string err = (string) "File out netcdf, "
950 + "failed to write int attribute " + var_attr_name;
951 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
952 }
953#endif
954
955 break;
956 }
957
958 case Attr_uint32: {
959 // uint
960 //unsigned int vals[num_vals];
961 vector<unsigned int> vals;
962 vals.resize(num_vals);
963 for (attri = 0; attri < num_vals; attri++) {
964 string val = attrs.get_attr(attr, attri);
965 istringstream is(val);
966 unsigned int lval = 0;
967 is >> lval;
968 vals[attri] = lval;
969 }
970 stax = nc_put_att_uint(ncid, varid, var_attr_name.c_str(), NC_UINT, num_vals,
971 &vals[0]);
972#if !NDEBUG
973 if (stax != NC_NOERR) {
974 string err = (string) "File out netcdf, "
975 + "failed to write byte attribute " + var_attr_name;
976 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
977 }
978#endif
979
980 break;
981 }
982
983 case Attr_float32: {
984 // float
985 //float vals[num_vals];
986 vector<float> vals;
987 vals.resize(num_vals);
988 for (attri = 0; attri < num_vals; attri++) {
989 string val = attrs.get_attr(attr, attri);
990 const char *cval = val.c_str();
991 //istringstream is(val);
992 float fval = 0;
993 fval = strtod(cval,NULL);
994 //is >> fval;
995 vals[attri] = fval;
996 }
997 stax = nc_put_att_float(ncid, varid, var_attr_name.c_str(), NC_FLOAT, num_vals, &vals[0]);
998
999#if !NDEBUG
1000 if (stax != NC_NOERR) {
1001 string err = (string) "File out netcdf, "
1002 + "failed to write float attribute " + var_attr_name;
1003 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1004 }
1005#endif
1006
1007 break;
1008 }
1009
1010 case Attr_float64: {
1011 // double
1012 //double vals[num_vals];
1013 vector<double> vals;
1014 vals.resize(num_vals);
1015 for (attri = 0; attri < num_vals; attri++) {
1016 string val = attrs.get_attr(attr, attri);
1017 const char *cval = val.c_str();
1018 //istringstream is(val);
1019 double dval = 0;
1020 dval = strtod(cval,NULL);
1021 //is >> dval;
1022 vals[attri] = dval;
1023 }
1024 stax = nc_put_att_double(ncid, varid, var_attr_name.c_str(), NC_DOUBLE, num_vals, &vals[0]);
1025
1026#if !NDEBUG
1027 if (stax != NC_NOERR) {
1028 string err = (string) "File out netcdf, "
1029 + "failed to write double attribute " + var_attr_name;
1030 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1031 }
1032#endif
1033
1034 break;
1035 }
1036
1037 case Attr_string:
1038 case Attr_url:
1039 case Attr_other_xml: { // Added. jhrg 12.27.2011
1040 // string
1041 string val = attrs.get_attr(attr, 0);
1042 for (attri = 1; attri < num_vals; attri++) {
1043 val += "\n" + attrs.get_attr(attr, attri);
1044 }
1045 string attr_name = attrs.get_name(attr);
1046 if (attr_name != _FillValue) {
1047 stax = nc_put_att_text(ncid, varid, var_attr_name.c_str(), val.length(), val.c_str());
1048 }
1049 else {
1050 BESDEBUG("fonc",
1051 "FONcAttributes::add_attributes_worker - Original attribute value is first character: "
1052 << val.c_str()[0] << endl);
1053 stax = nc_put_att_text(ncid, varid, var_attr_name.c_str(), 1, val.c_str());
1054 if (stax == NC_NOERR) {
1055 // New name for attribute _FillValue with original value
1056 string var_attr_name_fillvalue = "Orig_FillValue";
1057 BESDEBUG("fonc",
1058 "FONcAttributes::add_attributes_worker - New attribute value is original value: "
1059 << val.c_str() << endl);
1060 // This line causes the segmentation fault since attrs is changed and the original iterator of attrs doesn't exist anymore.
1061 // So it causes the segmentation fault when next attribute is fetched in the for loop of the add_attributes(). KY 2019-12-13
1062 // Note: Leave the following #if 0 #endif for the time being.
1063#if 0
1064 attrs.append_attr(var_attr_name_fillvalue,"String", val);
1065#endif
1066 stax = nc_put_att_text(ncid, varid, var_attr_name_fillvalue.c_str(), val.length(), val.c_str());
1067 }
1068 }
1069
1070#if !NDEBUG
1071 if (stax != NC_NOERR) {
1072 string err = (string) "File out netcdf, "
1073 + "failed to write string attribute " + var_attr_name;
1074 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1075 }
1076#endif
1077
1078 break;
1079 }
1080
1081
1082 case Attr_unknown:
1083 default: {
1084 string err = (string) "File out netcdf, failed to write unknown type of attribute " + var_attr_name;
1085 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1086 break; // Not actually needed since FONcUtils::handle_error throws
1087 }
1088 }
1089
1090 if (stax != NC_NOERR) {
1091 string err = (string) "File out netcdf, failed to write " + attr_type + " attribute " + var_attr_name;
1092 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1093 }
1094}
1095
1108void
1110 int varid,
1111 const string &var_name,
1112 const string &global_attr_name,
1113 const string &var_attr_name,
1114 D4Attribute* attr,
1115 bool is_nc_enhanced) {
1116
1117 D4AttributeType d4_attr_type = attr->type();
1118 int stax = NC_NOERR;
1119 unsigned int attri = 0;
1120 unsigned int num_vals = attr->num_values();
1121 switch (d4_attr_type) {
1122 case attr_container_c: {
1123 // flatten
1124 BESDEBUG("fonc", "This is an attribute container. attr_name: \"" << global_attr_name << "\"" << endl);
1125 D4Attributes *c_attributes = attr->attributes();
1126 if (c_attributes) {
1127 add_dap4_attributes(ncid, varid, c_attributes, var_name, global_attr_name, is_nc_enhanced);
1128 }
1129 }
1130 break;
1131 case attr_byte_c:
1132 case attr_uint8_c:{
1133 // unsigned char
1134 vector<unsigned char> vals;
1135 vals.resize(num_vals);
1136 attri = 0;
1137 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1138 string val = *vi;
1139 istringstream is(val);
1140 unsigned int uival = 0;
1141 is >> uival;
1142 vals[attri] = (unsigned char) uival;
1143 ++attri;
1144 }
1145 stax = nc_put_att_uchar(ncid, varid, var_attr_name.c_str(), NC_UBYTE,
1146 num_vals, &vals[0]);
1147 if (stax != NC_NOERR) {
1148 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1149 + "failed to write byte attribute " + var_attr_name;
1150 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1151 }
1152 }
1153 break;
1154 case attr_int8_c:{
1155 // 8-bit integer
1156 vector<int8_t> vals;
1157 vals.resize(num_vals);
1158 attri = 0;
1159 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1160 string val = *vi;
1161 istringstream is(val);
1162 int uival = 0;
1163 is >> uival;
1164 vals[attri] = (int8_t) uival;
1165 ++attri;
1166 }
1167 stax = nc_put_att_schar(ncid, varid, var_attr_name.c_str(), NC_BYTE,
1168 num_vals, &vals[0]);
1169 if (stax != NC_NOERR) {
1170 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1171 + "failed to write signed 8-bit integer attribute " + var_attr_name;
1172 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1173 }
1174 }
1175 break;
1176 case attr_int16_c: {
1177 // short
1178 vector<short> vals;
1179 vals.resize(num_vals);
1180 attri = 0;
1181 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1182 string val = *vi;
1183 istringstream is(val);
1184 short sval = 0;
1185 is >> sval;
1186 vals[attri] = sval;
1187 ++attri;
1188 }
1189
1190 stax = nc_put_att_short(ncid, varid, var_attr_name.c_str(), NC_SHORT,
1191 num_vals, &vals[0]);
1192 if (stax != NC_NOERR) {
1193 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1194 + "failed to write short attribute " + var_attr_name;
1195 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1196 }
1197 }
1198 break;
1199 case attr_uint16_c: {
1200 // unsigned short
1201 attri = 0;
1202 vector<unsigned short>vals;
1203 vals.resize(num_vals);
1204 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1205 string val = *vi;
1206 istringstream is(val);
1207 unsigned short ival = 0;
1208 is >> ival;
1209 vals[attri] = ival;
1210 ++attri;
1211 }
1212
1213 stax = nc_put_att_ushort(ncid, varid, var_attr_name.c_str(), NC_USHORT, num_vals,
1214 &vals[0]);
1215 if (stax != NC_NOERR) {
1216 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1217 + "failed to write unsigned short attribute " + var_attr_name;
1218 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1219 }
1220 }
1221 break;
1222 case attr_int32_c: {
1223 vector<int> vals;
1224 vals.resize(num_vals);
1225 attri = 0;
1226 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1227 string val = *vi;
1228 istringstream is(val);
1229 int sval = 0;
1230 is >> sval;
1231 vals[attri] = sval;
1232 ++attri;
1233 }
1234
1235 stax = nc_put_att_int(ncid, varid, var_attr_name.c_str(), NC_INT, num_vals,
1236 &vals[0]);
1237 if (stax != NC_NOERR) {
1238 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1239 + "failed to write int attribute " + var_attr_name;
1240 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1241 }
1242 }
1243 break;
1244 case attr_uint32_c: {
1245 // uint
1246 vector<unsigned int> vals;
1247 vals.resize(num_vals);
1248 attri = 0;
1249 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1250 string val = *vi;
1251 istringstream is(val);
1252 unsigned int sval = 0;
1253 is >> sval;
1254 vals[attri] = sval;
1255 ++attri;
1256 }
1257
1258 stax = nc_put_att_uint(ncid, varid, var_attr_name.c_str(), NC_UINT, num_vals,
1259 &vals[0]);
1260 if (stax != NC_NOERR) {
1261 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1262 + "failed to write unsigned int attribute " + var_attr_name;
1263 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1264 }
1265 }
1266 break;
1267 case attr_int64_c: {
1268 vector<long long> vals;
1269 vals.resize(num_vals);
1270 attri = 0;
1271 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1272 string val = *vi;
1273 istringstream is(val);
1274 long long sval = 0;
1275 is >> sval;
1276 vals[attri] = sval;
1277 ++attri;
1278 }
1279
1280 stax = nc_put_att_longlong(ncid, varid, var_attr_name.c_str(), NC_INT64, num_vals,
1281 &vals[0]);
1282 if (stax != NC_NOERR) {
1283 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1284 + "failed to write 64-bit int attribute " + var_attr_name;
1285 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1286 }
1287 }
1288 break;
1289 case attr_uint64_c: {
1290 vector<unsigned long long> vals;
1291 vals.resize(num_vals);
1292 attri = 0;
1293 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1294 string val = *vi;
1295 istringstream is(val);
1296 unsigned long long sval = 0;
1297 is >> sval;
1298 vals[attri] = sval;
1299 ++attri;
1300 }
1301
1302 stax = nc_put_att_ulonglong(ncid, varid, var_attr_name.c_str(), NC_UINT64, num_vals,
1303 &vals[0]);
1304 if (stax != NC_NOERR) {
1305 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1306 + "failed to write unsigned 64-bit int attribute " + var_attr_name;
1307 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1308 }
1309 }
1310 break;
1311
1312 case attr_float32_c: {
1313 vector<float>vals;
1314 vals.resize(num_vals);
1315 attri = 0;
1316 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1317 string val = *vi;
1318 const char *cval = val.c_str();
1319 //istringstream is(val);
1320 float sval = 0;
1321 sval = strtod(cval,NULL);
1322 //is >> sval;
1323 vals[attri] = sval;
1324 ++attri;
1325 }
1326
1327 stax = nc_put_att_float(ncid, varid, var_attr_name.c_str(), NC_FLOAT,
1328 num_vals, &vals[0]);
1329 if (stax != NC_NOERR) {
1330 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1331 + "failed to write float attribute " + var_attr_name;
1332 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1333 }
1334 }
1335 break;
1336 case attr_float64_c: {
1337 vector<double> vals;
1338 vals.resize(num_vals);
1339 attri = 0;
1340 for (D4Attribute::D4AttributeIter vi = attr->value_begin(), ve = attr->value_end(); vi != ve; vi++) {
1341 string val = *vi;
1342 const char *cval = val.c_str();
1343 //istringstream is(val);
1344 double sval = 0;
1345 sval = strtod(cval,NULL);
1346 //is >> sval;
1347 vals[attri] = sval;
1348 ++attri;
1349 }
1350 stax = nc_put_att_double(ncid, varid, var_attr_name.c_str(), NC_DOUBLE,
1351 num_vals, &vals[0]);
1352 if (stax != NC_NOERR) {
1353 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1354 + "failed to write double attribute " + var_attr_name;
1355 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1356 }
1357 }
1358 break;
1359 case attr_str_c:
1360 case attr_url_c:
1361 case attr_otherxml_c: // Added. jhrg 12.27.2011
1362 {
1363
1364 if(attr->num_values()==0)
1365 stax = nc_put_att_text(ncid, varid, var_attr_name.c_str(), 0, "");
1366 else {
1367
1368 D4Attribute::D4AttributeIter vi,ve;
1369 vi = attr->value_begin();
1370 ve = attr->value_end();
1371
1372
1373 string val = (*vi);
1374
1375 vi++;
1376 for (; vi != ve; vi++) {
1377 val += "\n" + *vi;
1378 }
1379
1380 if (var_attr_name != _FillValue) {
1381 stax = nc_put_att_text(ncid, varid, var_attr_name.c_str(), val.length(), val.c_str());
1382 } else {
1383 BESDEBUG("fonc",
1384 "FONcAttributes::add_attributes_worker - Original attribute value is first character: "
1385 << val.c_str()[0] << endl);
1386 stax = nc_put_att_text(ncid, varid, var_attr_name.c_str(), 1, val.c_str());
1387 if (stax == NC_NOERR) {
1388 // New name for attribute _FillValue with original value
1389 string var_attr_name_fillvalue = "Orig_FillValue";
1390 BESDEBUG("fonc",
1391 "FONcAttributes::add_attributes_worker - New attribute value is original value: "
1392 << val.c_str() << endl);
1393 // This line causes the segmentation fault since attrs is changed and the original iterator of attrs doesn't exist anymore.
1394 // So it causes the segmentation fault when next attribute is fetched in the for loop of the add_attributes(). KY 2019-12-13
1395 #if 0
1396 attrs.append_attr(var_attr_name_fillvalue,"String", val);
1397 #endif
1398 stax = nc_put_att_text(ncid, varid, var_attr_name_fillvalue.c_str(), val.length(), val.c_str());
1399 }
1400 }
1401 }
1402
1403 if (stax != NC_NOERR) {
1404 string err = (string) "File out netcdf-4 enhanced for DAP4, "
1405 + "failed to write string attribute " + var_attr_name;
1406 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1407 }
1408 }
1409 break;
1410
1411 case attr_null_c:
1412 case attr_enum_c:
1413 case attr_opaque_c:
1414 {
1415 string err = (string) "File out netcdf, "
1416 + "failed to write unknown type of attribute " + var_attr_name;
1417 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1418 }
1419 break;
1420 }
1421}
1422
1423// Note: Leave the following #if 0 #endif block for the time being. They can be removed in the future
1424// release. KY 2021-06-15
1425#if 0
1426 int stax = NC_NOERR;
1427 AttrType attrType = attrs.get_attr_type(attr);
1428 unsigned int attri = 0;
1429 unsigned int num_vals = attrs.get_attr_num(attr);
1430 switch (attrType) {
1431 case Attr_container: {
1432 // flatten
1433 BESDEBUG("fonc", "This is an attribute container. attr_name: \"" << global_attr_name << "\"" << endl);
1434 AttrTable *container = attrs.get_attr_table(attr);
1435 if (container) {
1436 add_attributes(ncid, varid, *container, var_name, global_attr_name, is_nc_enhanced);
1437 }
1438 }
1439 break;
1440 case Attr_byte: {
1441 // unsigned char
1442 //unsigned char vals[num_vals];
1443 vector<unsigned char> vals;
1444 vals.resize(num_vals);
1445 for (attri = 0; attri < num_vals; attri++) {
1446 string val = attrs.get_attr(attr, attri);
1447 istringstream is(val);
1448 unsigned int uival = 0;
1449 is >> uival;
1450 vals[attri] = (unsigned char) uival;
1451 }
1452 stax = nc_put_att_uchar(ncid, varid, var_attr_name.c_str(), NC_UBYTE,
1453 num_vals, &vals[0]);
1454 if (stax != NC_NOERR) {
1455 string err = (string) "File out netcdf, "
1456 + "failed to write byte attribute " + var_attr_name;
1457 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1458 }
1459 }
1460 break;
1461 case Attr_int16: {
1462 // short
1463 //short vals[num_vals];
1464 vector<short> vals;
1465 vals.resize(num_vals);
1466 for (attri = 0; attri < num_vals; attri++) {
1467 string val = attrs.get_attr(attr, attri);
1468 istringstream is(val);
1469 short sval = 0;
1470 is >> sval;
1471 vals[attri] = sval;
1472 }
1473 stax = nc_put_att_short(ncid, varid, var_attr_name.c_str(), NC_SHORT,
1474 num_vals, &vals[0]);
1475 if (stax != NC_NOERR) {
1476 string err = (string) "File out netcdf, "
1477 + "failed to write short attribute " + var_attr_name;
1478 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1479 }
1480 }
1481 break;
1482 case Attr_uint16: {
1483 // unsigned short
1484 // (needs to be big enough to store an unsigned short
1485 //unsigned short vals[num_vals];
1486 vector<unsigned short> vals;
1487 vals.resize(num_vals);
1488 for (attri = 0; attri < num_vals; attri++) {
1489 string val = attrs.get_attr(attr, attri);
1490 istringstream is(val);
1491 unsigned short ival = 0;
1492 is >> ival;
1493 vals[attri] = ival;
1494 }
1495 stax = nc_put_att_ushort(ncid, varid, var_attr_name.c_str(), NC_USHORT, num_vals,
1496 &vals[0]);
1497 if (stax != NC_NOERR) {
1498 string err = (string) "File out netcdf, "
1499 + "failed to write unsinged short attribute " + var_attr_name;
1500 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1501 }
1502 }
1503 break;
1504 case Attr_int32: {
1505 // int
1506 //int vals[num_vals];
1507 vector<int> vals;
1508 vals.resize(num_vals);
1509 for (attri = 0; attri < num_vals; attri++) {
1510 string val = attrs.get_attr(attr, attri);
1511 istringstream is(val);
1512 int ival = 0;
1513 is >> ival;
1514 vals[attri] = ival;
1515 }
1516 stax = nc_put_att_int(ncid, varid, var_attr_name.c_str(), NC_INT, num_vals,
1517 &vals[0]);
1518 if (stax != NC_NOERR) {
1519 string err = (string) "File out netcdf, "
1520 + "failed to write int attribute " + var_attr_name;
1521 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1522 }
1523 }
1524 break;
1525 case Attr_uint32: {
1526 // uint
1527 //unsigned int vals[num_vals];
1528 vector<unsigned int> vals;
1529 vals.resize(num_vals);
1530 for (attri = 0; attri < num_vals; attri++) {
1531 string val = attrs.get_attr(attr, attri);
1532 istringstream is(val);
1533 unsigned int lval = 0;
1534 is >> lval;
1535 vals[attri] = lval;
1536 }
1537 stax = nc_put_att_uint(ncid, varid, var_attr_name.c_str(), NC_UINT, num_vals,
1538 &vals[0]);
1539 if (stax != NC_NOERR) {
1540 string err = (string) "File out netcdf, "
1541 + "failed to write byte attribute " + var_attr_name;
1542 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1543 }
1544 }
1545 break;
1546 case Attr_float32: {
1547 // float
1548 //float vals[num_vals];
1549 vector<float> vals;
1550 vals.resize(num_vals);
1551 for (attri = 0; attri < num_vals; attri++) {
1552 string val = attrs.get_attr(attr, attri);
1553 const char *cval = val.c_str();
1554 //istringstream is(val);
1555 float fval = 0;
1556 fval = strtod(cval,NULL);
1557 //is >> fval;
1558 vals[attri] = fval;
1559 }
1560 stax = nc_put_att_float(ncid, varid, var_attr_name.c_str(), NC_FLOAT,
1561 num_vals, &vals[0]);
1562 if (stax != NC_NOERR) {
1563 string err = (string) "File out netcdf, "
1564 + "failed to write float attribute " + var_attr_name;
1565 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1566 }
1567 }
1568 break;
1569 case Attr_float64: {
1570 // double
1571 //double vals[num_vals];
1572 vector<double> vals;
1573 vals.resize(num_vals);
1574 for (attri = 0; attri < num_vals; attri++) {
1575 string val = attrs.get_attr(attr, attri);
1576 const char *cval = val.c_str();
1577 //istringstream is(val);
1578 double dval = 0;
1579 dval = strtod(cval,NULL);
1580 //is >> dval;
1581 vals[attri] = dval;
1582 }
1583 stax = nc_put_att_double(ncid, varid, var_attr_name.c_str(), NC_DOUBLE,
1584 num_vals, &vals[0]);
1585 if (stax != NC_NOERR) {
1586 string err = (string) "File out netcdf, "
1587 + "failed to write double attribute " + var_attr_name;
1588 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1589 }
1590 }
1591 break;
1592 case Attr_string:
1593 case Attr_url:
1594 case Attr_other_xml: // Added. jhrg 12.27.2011
1595 {
1596 // string
1597 string val = attrs.get_attr(attr, 0);
1598 for (attri = 1; attri < num_vals; attri++) {
1599 val += "\n" + attrs.get_attr(attr, attri);
1600 }
1601 string attr_name = attrs.get_name(attr);
1602 if (attr_name != _FillValue) {
1603 stax = nc_put_att_text(ncid, varid, var_attr_name.c_str(), val.length(), val.c_str());
1604 } else {
1605 BESDEBUG("fonc",
1606 "FONcAttributes::add_attributes_worker - Original attribute value is first character: "
1607 << val.c_str()[0] << endl);
1608 stax = nc_put_att_text(ncid, varid, var_attr_name.c_str(), 1, val.c_str());
1609 if (stax == NC_NOERR) {
1610 // New name for attribute _FillValue with original value
1611 string var_attr_name_fillvalue = "Orig_FillValue";
1612 BESDEBUG("fonc",
1613 "FONcAttributes::add_attributes_worker - New attribute value is original value: "
1614 << val.c_str() << endl);
1615 // This line causes the segmentation fault since attrs is changed and the original iterator of attrs doesn't exist anymore.
1616 // So it causes the segmentation fault when next attribute is fetched in the for loop of the add_attributes(). KY 2019-12-13
1617#if 0
1618 attrs.append_attr(var_attr_name_fillvalue,"String", val);
1619#endif
1620 stax = nc_put_att_text(ncid, varid, var_attr_name_fillvalue.c_str(), val.length(), val.c_str());
1621 }
1622 }
1623
1624 if (stax != NC_NOERR) {
1625 string err = (string) "File out netcdf, "
1626 + "failed to write string attribute " + var_attr_name;
1627 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1628 }
1629 }
1630 break;
1631
1632 case Attr_unknown: {
1633 string err = (string) "File out netcdf, "
1634 + "failed to write unknown type of attribute " + var_attr_name;
1635 FONcUtils::handle_error(stax, err, __FILE__, __LINE__);
1636 }
1637 break;
1638 }
1639
1640#endif
1641
static bool endsWith(std::string const &fullString, std::string const &ending)
Definition: BESUtil.cc:961
static void add_dap4_attributes(int ncid, int varid, D4Attributes *d4_attrs, const string &var_name, const string &prepend_attr, bool is_netCDF_enhanced)
add_dap4_attributes
static void write_dap4_attrs_for_nc4_types(int ncid, int varid, const string &var_name, const string &global_attr_name, const string &var_attr_name, D4Attribute *attr, bool is_nc_enhanced)
writes out a single attribute that maps the dap4 datatype to netCDF-4
static void add_original_name(int ncid, int varid, const string &var_name, const string &orig)
Adds an attribute for the variable if the variable name had to be modified in any way.
static void add_attributes(int ncid, int varid, AttrTable &attrs, const string &var_name, const string &prepend_attr, bool is_netCDF_enhanced)
helper function for add_attributes
static void write_attrs_for_nc4_types(int ncid, int varid, const string &var_name, const string &global_attr_name, const string &var_attr_name, AttrTable attrs, AttrTable::Attr_iter &attr, bool is_nc_enhanced)
writes out a single attribute that maps the datatype to netCDF-4
static void add_variable_attributes(int ncid, int varid, BaseType *b, bool is_netCDF_enhanced, bool is_dap4)
Add the attributes for an OPeNDAP variable to the netcdf file.
static void handle_error(int stax, const string &err, const string &file, int line)
handle any netcdf errors
Definition: FONcUtils.cc:424
static string id2netcdf(string in)
convert the provided string to a netcdf allowed identifier.
Definition: FONcUtils.cc:84