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