24#include <libdap/escaping.h>
25#include <libdap/InternalErr.h>
34HE2CF::get_vgroup_field_refids(
const string& _gname,
39 int32 vrefid = Vfind(file_id, (
char*)_gname.c_str());
43 error <<
"cannot obtain the reference number for vgroup "<<_gname;
44 throw_error(error.str());
48 int32 vgroup_id = Vattach(file_id, vrefid,
"r");
49 if (FAIL == vgroup_id) {
52 error <<
"cannot obtain the group id for vgroup "<<_gname;
53 throw_error(error.str());
57 int32 npairs = Vntagrefs(vgroup_id);
65 error <<
"Got " << npairs
66 <<
" npairs for " << _gname;
67 throw_error(error.str());
71 for (
int i = 0; i < npairs; ++i) {
76 if (Vgettagref(vgroup_id, i, &tag, &ref) < 0){
83 error <<
"failed to get tag / ref";
84 throw_error(error.str());
88 if(Visvg(vgroup_id, ref)){
90 char cvgroup_name[VGNAMELENMAX*4];
94 vgroup_cid = Vattach(file_id, ref,
"r");
95 if (FAIL == vgroup_cid) {
99 error <<
"cannot obtain the vgroup id";
100 throw_error(error.str());
104 istat = Vgetname(vgroup_cid,cvgroup_name);
110 error <<
"cannot obtain the vgroup id";
111 throw_error(error.str());
115 if(strncmp(cvgroup_name,
"Data Fields", 11) == 0){
119 if(strncmp(cvgroup_name,
"Geolocation Fields", 18) == 0){
123 if (FAIL == Vdetach(vgroup_cid)) {
127 error <<
"cannot close the vgroup "<< cvgroup_name <<
"Successfully";
128 throw_error(error.str());
137 if (FAIL == Vdetach(vgroup_id)) {
140 error <<
"cannot close the vgroup "<< _gname <<
"Successfully";
141 throw_error(error.str());
148HE2CF::open_sd(
const string& _filename,
const int sd_id_in)
150 int32 num_datasets = -1;
152 if(SDfileinfo(sd_id, &num_datasets, &num_global_attributes)
157 error <<
"Failed to call SDfileinfo() on "
160 throw_error(error.str());
167HE2CF::open_vgroup(
const string& _filename,
const int file_id_in)
170 file_id = file_id_in;
171 if (Vstart(file_id) < 0){
173 error <<
"Failed to call Vstart on " << _filename << endl;
174 throw_error(error.str());
186bool HE2CF::set_non_ecsmetadata_attrs() {
188 for(
int i = 0; i < num_global_attributes; i++){
191 char temp_name[H4_MAX_NC_NAME];
193 int32 attr_count = 0;
194 if(SDattrinfo(sd_id, i, temp_name, &attr_type, &attr_count) == FAIL) {
197 error <<
"Fail to obtain SDS global attribute info." << endl;
198 throw_error(error.str());
201 string attr_namestr(temp_name);
204 if (
true == is_eosmetadata(attr_namestr))
211 if (attr_namestr.compare(0,14,
"StructMetadata" )== 0)
219 if (attr_namestr.compare(0,12,
"CoreMetadata" )== 0)
221 if (attr_namestr.compare(0,12,
"coremetadata" )== 0)
223 if (attr_namestr.compare(0,15,
"ArchiveMetadata" )== 0)
225 if (attr_namestr.compare(0,15,
"archivemetadata" )== 0)
227 if (attr_namestr.compare(0,15,
"Productmetadata" )== 0)
229 if (attr_namestr.compare(0,15,
"productmetadata" )== 0)
233 vector<char>attr_data;
234 attr_data.resize((attr_count+1) *DFKNTsize(attr_type));
236 if(SDreadattr(sd_id, i, attr_data.data()) == FAIL){
239 error <<
"Fail to read SDS global attributes" << endl;
240 throw_error(error.str());
245 if (attr_type == DFNT_CHAR || attr_type == DFNT_UCHAR) {
246 attr_data[attr_count] =
'\0';
250 AttrTable *at = das->get_table(
"HDF_GLOBAL");
252 at = das->add_table(
"HDF_GLOBAL",
new AttrTable);
257 if(attr_type == DFNT_UCHAR || attr_type == DFNT_CHAR){
258 string tempstring2(attr_data);
259 string tempfinalstr= string(tempstring2.c_str());
263 at->append_attr(attr_namestr,
"String" , HDFCFUtil::escattr(tempfinalstr));
268 for (
int loc=0; loc < attr_count ; loc++) {
281bool HE2CF::set_metadata(
const string& metadata_basename,vector<string>& non_number_names, vector<string>& no_num_data)
283 bool suffix_is_num_or_null =
true;
287 list<string> one_dot_names;
290 list<string> two_dots_names;
297 for(
int i = 0; i < num_global_attributes; i++){
300 char temp_name[H4_MAX_NC_NAME];
302 int32 attr_count = 0;
303 if(SDattrinfo(sd_id, i, temp_name, &attr_type, &attr_count) == FAIL) {
306 error <<
"Fail to obtain SDS global attribute info." << endl;
307 throw_error(error.str());
310 string temp_name_str(temp_name);
313 if(temp_name_str.find(metadata_basename)==0) {
314 arrange_list(one_dot_names,two_dots_names,non_number_names,temp_name_str,list_flag);
318 list<string>::const_iterator lit;
324 if ( list_flag >= 0 && list_flag <=2) {
325 for (lit = one_dot_names.begin();lit!=one_dot_names.end();++lit) {
326 set_eosmetadata_namelist(*lit);
328 obtain_SD_attr_value(*lit,cur_data);
329 metadata.append(cur_data);
333 if ( 3== list_flag) {
334 for (lit = two_dots_names.begin();lit!=two_dots_names.end();++lit){
335 set_eosmetadata_namelist(*lit);
337 obtain_SD_attr_value(*lit,cur_data);
338 metadata.append(cur_data);
342 if (non_number_names.empty() ==
false) {
343 suffix_is_num_or_null =
false;
344 no_num_data.resize(non_number_names.size());
347 for (
unsigned int i =0; i<non_number_names.size();i++) {
348 set_eosmetadata_namelist(non_number_names[i]);
349 obtain_SD_attr_value(non_number_names[i],no_num_data[i]);
352 return suffix_is_num_or_null;
359void HE2CF::arrange_list(list<string> & sl1, list<string>&sl2,vector<string>&v1,
const string& name,
int& flag)
const {
362 if(name.find(
".") == string::npos) {
363 sl1.push_front(name);
364 sl2.push_front(name);
367 else if (name.find_first_of(
".") == name.find_last_of(
".")) {
369 size_t dot_pos = name.find_first_of(
".");
371 if((dot_pos+1)==name.size())
372 throw InternalErr(__FILE__, __LINE__,
"Should have characters or numbers after ." );
374 string str_after_dot = name.substr(dot_pos+1);
375 stringstream sstr(str_after_dot);
377 int number_after_dot = 0;
378 sstr >> number_after_dot;
384 else if(0 == number_after_dot) {
394 throw InternalErr(__FILE__, __LINE__,
395 "ecs metadata suffix .1 and .0.1 cannot exist at the same file" );
404 throw InternalErr(__FILE__, __LINE__,
"ecs metadata suffix .1 and .0.1 cannot exist at the same file" );
412void HE2CF::obtain_SD_attr_value(
const string& attrname,
string &cur_data)
const {
414 int32 sds_index = SDfindattr(sd_id, attrname.c_str());
415 if(sds_index == FAIL){
418 error <<
"Failed to obtain the SDS global attribute" << attrname << endl;
419 throw InternalErr(__FILE__, __LINE__,error.str());
423 char temp_name[H4_MAX_NC_NAME];
427 if(SDattrinfo(sd_id, sds_index, temp_name, &type, &count) == FAIL) {
430 error <<
"Failed to obtain the SDS global attribute" << attrname <<
"information" << endl;
431 throw InternalErr(__FILE__, __LINE__,error.str());
434 vector<char> attrvalue;
435 attrvalue.resize((count+1)*DFKNTsize(type));
437 if(SDreadattr(sd_id, sds_index, attrvalue.data()) == FAIL){
440 error <<
"Failed to read the SDS global attribute" << attrname << endl;
441 throw InternalErr(__FILE__, __LINE__,error.str());
452 if(attrvalue[count] !=
'\0')
453 throw InternalErr(__FILE__,__LINE__,
"the last character of the attribute buffer should be nullptr");
456 cur_data.resize(attrvalue.size()-1);
457 copy(attrvalue.begin(),attrvalue.end()-1,cur_data.begin());
461bool HE2CF::set_vgroup_map(int32 _refid,
bool isgeo)
474 int32 vgroup_id = Vattach(file_id, _refid,
"r");
475 if (FAIL == vgroup_id) {
478 error <<
"Fail to attach the vgroup " ;
479 throw_error(error.str());
483 int32 npairs = Vntagrefs(vgroup_id);
484 if (FAIL == npairs) {
488 error <<
"Fail to obtain the number of objects in a group " ;
489 throw_error(error.str());
493 for (
int i = 0; i < npairs; ++i) {
497 char buf[H4_MAX_NC_NAME];
499 if (Vgettagref(vgroup_id, i, &tag2, &ref2) < 0){
503 error <<
"Vgettagref failed for vgroup_id=." << vgroup_id;
504 throw_error(error.str());
508 if(tag2 == DFTAG_NDG){
510 int32 sds_index = SDreftoindex(sd_id, ref2);
511 if (FAIL == sds_index) {
515 error <<
"Cannot obtain the SDS index ";
516 throw_error(error.str());
520 int32 sds_id = SDselect(sd_id, sds_index);
521 if (FAIL == sds_id) {
525 error <<
"Cannot obtain the SDS ID ";
526 throw_error(error.str());
531 int32 dimsizes[H4_MAX_VAR_DIMS];
535 if(FAIL == SDgetinfo(sds_id, buf, &rank, dimsizes, &datatype, &num_attrs)) {
539 error <<
"Cannot obtain the SDS info.";
540 throw_error(error.str());
544 vg_dsd_map[string(buf)] = sds_id;
546 vg_gsd_map[string(buf)] = sds_id;
550 if(tag2 == DFTAG_VH){
553 if ((vid = VSattach(file_id, ref2,
"r")) < 0) {
558 error <<
"VSattach failed for file_id=." << file_id;
559 throw_error(error.str());
561 if (FAIL == VSgetname(vid, buf)) {
566 error <<
"VSgetname failed for file_id=." << file_id;
567 throw_error(error.str());
570 vg_dvd_map[string(buf)] = ref2;
572 vg_gvd_map[string(buf)] = ref2;
574 if (FAIL == VSdetach(vid)) {
579 error <<
"VSdetach failed for file_id=." << file_id;
580 throw_error(error.str());
586 if (FAIL == Vdetach(vgroup_id)){
589 error <<
"VSdetach failed for file_id=." << file_id;
590 throw_error(error.str());
596bool HE2CF::write_attr_long_name(
const string& _long_name,
597 const string& _varname,
600 AttrTable *at = das->get_table(_varname);
602 at = das->add_table(_varname,
new AttrTable);
605 at->append_attr(
"long_name",
"String", _long_name +
"(fake)");
608 at->append_attr(
"long_name",
"String", _long_name);
612bool HE2CF::write_attr_long_name(
const string& _group_name,
613 const string& _long_name,
614 const string& _varname,
617 AttrTable *at = das->get_table(_varname);
619 at = das->add_table(_varname,
new AttrTable);
622 at->append_attr(
"long_name",
"String",
623 _group_name +
":" + _long_name +
"(fake)");
626 at->append_attr(
"long_name",
"String",
627 _group_name +
":" + _long_name);
634HE2CF::write_attr_sd(int32 _sds_id,
const string& _newfname,
int _fieldtype)
636 char buf_var[H4_MAX_NC_NAME];
637 char buf_attr[H4_MAX_NC_NAME];
639 int32 dimsizes[H4_MAX_VAR_DIMS];
645 status = SDgetinfo(_sds_id, buf_var,
646 &rank, dimsizes, &datatype, &num_attrs);
647 if (FAIL == status) {
649 SDendaccess(_sds_id);
651 error <<
"Cannot obtain the SDS info. ";
652 throw_error(error.str());
655 AttrTable *at = das->get_table(_newfname);
657 at = das->add_table(_newfname,
new AttrTable);
661 bool v_has_coordinates =
false;
662 if(0 == _fieldtype) {
663 if(at->simple_find(
"coordinates")!= at->attr_end())
664 v_has_coordinates =
true;
668 bool llcv_has_units =
false;
671 short llcv_ignore_scale = 0;
672 short llcv_ignore_offset = 0;
673 if(1 == _fieldtype || 2 == _fieldtype) {
674 if(at->simple_find(
"units")!= at->attr_end())
675 llcv_has_units =
true;
677 llcv_ignore_scale = check_scale_offset(_sds_id,
true);
680 SDendaccess(_sds_id);
685 llcv_ignore_offset = check_scale_offset(_sds_id,
false);
688 SDendaccess(_sds_id);
703 if(-1 == llcv_ignore_offset && 2 == llcv_ignore_scale){
704 SDendaccess(_sds_id);
707 error <<
"The latitude or longitude has <scale_factor> and <add_offset> attributes, "
708 <<
" the latitude or longitude have integer type and <add_offset> is not 0, "
709 <<
" we don't support such a case in the current implementation, "
710 <<
" please report to eoshelp@hdfgroup.org if you encounter this situation.";
711 throw_error(error.str());
715 for (
int j=0; j < num_attrs; j++){
717 status = SDattrinfo(_sds_id, j, buf_attr, &datatype, &n_values);
720 SDendaccess(_sds_id);
722 error <<
"SDattrinfo() failed on " << buf_attr;
723 throw_error(error.str());
726 if(
true == v_has_coordinates) {
727 if(!strncmp(buf_attr,
"coordinates", H4_MAX_NC_NAME))
731 if(
true == llcv_has_units) {
732 if(!strncmp(buf_attr,
"units", H4_MAX_NC_NAME))
736 if( 1 == _fieldtype || 2 == _fieldtype) {
737 if(!strncmp(buf_attr,
"scale_factor", H4_MAX_NC_NAME))
738 if((1 == llcv_ignore_scale) || (2==llcv_ignore_scale) )
740 if(!strncmp(buf_attr,
"add_offset", H4_MAX_NC_NAME))
741 if(1 == llcv_ignore_offset)
746 value.resize((n_values+1) * DFKNTsize(datatype));
747 status = SDreadattr(_sds_id, j, value.data());
750 SDendaccess(_sds_id);
752 error <<
"SDreadattr() failed on " << buf_attr << endl;
753 throw_error(error.str());
757 if (datatype == DFNT_CHAR || datatype == DFNT_UCHAR) {
758 value[n_values] =
'\0';
763 string attr_cf_name = string(buf_attr,strlen(buf_attr));
765 for (
int loc=0; loc < n_values ; loc++) {
769 if (attr_cf_name ==
"_FillValue") {
770 at->del_attr(attr_cf_name);
773 if (attr_cf_name ==
"long_name") {
774 at->del_attr(attr_cf_name);
783 status = SDendaccess(_sds_id);
786 error <<
"SDendaccess failed on variable " << _newfname;
787 throw_error(error.str());
793bool HE2CF::write_attr_vdata(int32 _vd_id,
const string& _newfname,
int _fieldtype)
795 int32 number_type = 0;
798 char buf[H4_MAX_NC_NAME];
802 if ((vid = VSattach(file_id, _vd_id,
"r")) < 0) {
807 error <<
"VSattach failed.";
808 throw_error(error.str());
813 count = VSfnattrs(vid, _HDF_VDATA);
819 error <<
"VSfnattrs failed.";
820 throw_error(error.str());
823 AttrTable *at = das->get_table(_newfname);
825 at = das->add_table(_newfname,
new AttrTable);
829 bool v_has_coordinates =
false;
830 if(0 == _fieldtype) {
831 if(at->simple_find(
"coordinates")!= at->attr_end())
832 v_has_coordinates =
true;
836 bool llcv_has_units =
false;
837 if(1 == _fieldtype || 2 == _fieldtype) {
838 if(at->simple_find(
"units")!= at->attr_end())
839 llcv_has_units =
true;
843 for(
int i=0; i < count; i++){
845 if (VSattrinfo(vid, _HDF_VDATA, i, buf,
846 &number_type, &count_v, &size) < 0) {
850 error <<
"VSattrinfo failed.";
851 throw_error(error.str());
854 if(
true == v_has_coordinates) {
855 if(!strncmp(buf,
"coordinates", H4_MAX_NC_NAME))
859 else if(
true == llcv_has_units) {
860 if(!strncmp(buf,
"units", H4_MAX_NC_NAME))
865 data.resize((count_v+1) * DFKNTsize(number_type));
866 if (VSgetattr(vid, _HDF_VDATA, i, data.data()) < 0) {
872 error <<
"VSgetattr failed.";
873 throw_error(error.str());
876 if (number_type == DFNT_CHAR || number_type == DFNT_UCHAR8) {
881 for(
int j=0; j < count_v ; j++){
886 if(!strncmp(buf,
"_FillValue", H4_MAX_NC_NAME)){
891 if(!strncmp(buf,
"long_name", H4_MAX_NC_NAME)){
895 string vdataname(buf);
907HE2CF::throw_error(
const string& _error)
909 throw InternalErr(__FILE__, __LINE__,
915HE2CF::HE2CF() =
default;
917HE2CF::~HE2CF() =
default;
924 int istat = Vend(file_id);
927 error <<
"Failed to call Vend in HE2CF::close.";
928 throw_error(error.str());
936HE2CF::get_metadata(
const string& _name,
bool& suffix_is_number,vector<string>&meta_nonnum_names, vector<string>& meta_nonum_data)
938 suffix_is_number = set_metadata(_name,meta_nonnum_names,meta_nonum_data);
943HE2CF::open(
const string& _filename,
const int hc_sd_id,
const int hc_file_id)
947 error <<
"=open(): filename is empty.";
948 throw_error(error.str());
952 if(!open_vgroup(_filename,hc_file_id)){
954 error <<
"=open(): failed to open vgroup.";
955 throw_error(error.str());
959 if(!open_sd(_filename,hc_sd_id)){
961 error <<
"=open(): failed to open sd.";
962 throw_error(error.str());
974 const string& _fname,
975 const string& _newfname,
981 write_attr_long_name(_gname, _fname, _newfname, _fieldtype);
984 write_attr_long_name(_fname, _newfname, _fieldtype);
994 get_vgroup_field_refids(_gname, &ref_df, &ref_gf);
996 set_vgroup_map(ref_gf,
true);
999 set_vgroup_map(ref_df,
false);
1011 id = vg_dsd_map[_fname];
1013 write_attr_sd(
id, _newfname,_fieldtype);
1018 id = vg_dvd_map[_fname];
1020 write_attr_vdata(
id, _newfname,_fieldtype);
1023 id = vg_gsd_map[_fname];
1025 write_attr_sd(
id, _newfname,_fieldtype);
1030 id = vg_gvd_map[_fname];
1032 write_attr_vdata(
id, _newfname,_fieldtype);
1044 void* v_ptr =
nullptr;
1056 auto val = (uint8) value;
1058 memcpy(v_val.data(),&val,1);
1059 v_ptr = (
void*)v_val.data();
1065 auto val = (int8) value;
1067 memcpy(v_val.data(),&val,1);
1068 v_ptr = (
void*)v_val.data();
1073 auto val = (int16) value;
1074 v_val.resize(
sizeof(
short));
1075 memcpy(v_val.data(),&val,
sizeof(
short));
1076 v_ptr = (
void*)v_val.data();
1082 auto val = (uint16) value;
1083 v_val.resize(
sizeof(
unsigned short));
1084 memcpy(v_val.data(),&val,
sizeof(
unsigned short));
1085 v_ptr = (
void*)v_val.data();
1091 auto val = (int32) value;
1092 v_val.resize(
sizeof(
int));
1093 memcpy(v_val.data(),&val,
sizeof(
int));
1094 v_ptr = (
void*)v_val.data();
1099 auto val = (uint32) value;
1100 v_val.resize(
sizeof(
unsigned int));
1101 memcpy(v_val.data(),&val,
sizeof(
int));
1102 v_ptr = (
void*)v_val.data();
1107 v_ptr = (
void*)&value;
1112 auto val = (float64) value;
1113 v_val.resize(
sizeof(
double));
1114 memcpy(v_val.data(),&val,
sizeof(
double));
1115 v_ptr = (
void*)v_val.data();
1119 throw_error(
"Invalid FillValue Type - ");
1123 AttrTable *at = das->get_table(_varname);
1125 at = das->add_table(_varname,
new AttrTable);
1137 AttrTable *at = das->get_table(_varname);
1139 at = das->add_table(_varname,
new AttrTable);
1141 at->append_attr(
"coordinates",
"String", _coordinates);
1150 AttrTable *at = das->get_table(_varname);
1152 at = das->add_table(_varname,
new AttrTable);
1154 at->del_attr(
"units");
1155 at->append_attr(
"units",
"String", _units);
1175HE2CF::check_scale_offset(int32 _sds_id,
bool is_scale) {
1177 char buf_var[H4_MAX_NC_NAME];
1178 char buf_attr[H4_MAX_NC_NAME];
1180 int32 dimsizes[H4_MAX_VAR_DIMS];
1186 short ignore_so = 0;
1187 status = SDgetinfo(_sds_id, buf_var,
1188 &rank, dimsizes, &datatype, &num_attrs);
1189 if (FAIL == status) {
1190 SDendaccess(_sds_id);
1191 ostringstream error;
1192 error <<
"Cannot obtain the SDS info. ";
1193 throw_error(error.str());
1196 bool has_so =
false;
1198 int32 so_dtype = -1;
1199 int32 var_dtype = datatype;
1200 string so_name =((
true==is_scale)?
"scale_factor":
"add_offset");
1202 for (
int j=0; j < num_attrs; j++){
1204 status = SDattrinfo(_sds_id, j, buf_attr, &datatype, &n_values);
1206 SDendaccess(_sds_id);
1207 ostringstream error;
1208 error <<
"SDattrinfo() failed on " << buf_attr;
1209 throw_error(error.str());
1212 if(!strncmp(buf_attr, so_name.c_str(), H4_MAX_NC_NAME)) {
1216 so_dtype = datatype;
1223 if(
true == has_so) {
1226 value.resize(DFKNTsize(so_dtype));
1227 status = SDreadattr(_sds_id, so_index, value.data());
1229 SDendaccess(_sds_id);
1230 ostringstream error;
1231 error <<
"SDreadattr() failed on the attribute scale_factor." << endl;
1232 throw_error(error.str());
1235 if(
true == is_scale) {
1236 if(DFNT_FLOAT32 == so_dtype) {
1237 float final_scale_value = *((
float*)((
void*)(value.data())));
1238 if(final_scale_value == 1.0)
1245 else if(var_dtype !=DFNT_FLOAT32 && var_dtype != DFNT_FLOAT64)
1248 else if(DFNT_FLOAT64 == so_dtype) {
1249 double final_scale_value = *((
double*)((
void*)(value.data())));
1250 if(final_scale_value == 1.0)
1252 else if(var_dtype !=DFNT_FLOAT32 && var_dtype != DFNT_FLOAT64)
1260 if(DFNT_FLOAT32 == so_dtype || DFNT_FLOAT64 == so_dtype) {
1261 if(atof(print_rep.c_str()) == 0.0)
1265 if(atoi(print_rep.c_str()) == 0)
bool open(const std::string &filename, const int sd_id, const int file_id)
openes \afilename HDF4 file.
string get_metadata(const std::string &metadataname, bool &suffix_is_num, std::vector< std::string > &non_num_names, std::vector< std::string > &non_num_data)
retrieves the merged metadata.
bool write_attribute(const std::string &gname, const std::string &fname, const std::string &newfname, int n_groups, int fieldtype)
bool write_attribute_coordinates(const std::string &varname, const std::string &coord)
void set_DAS(libdap::DAS *das)
sets DAS pointer so that we can bulid attribute tables.
bool close()
closes the opened file.
bool write_attribute_units(const std::string &varname, const std::string &units)
bool write_attribute_FillValue(const std::string &varname, int type, float val)
static std::string print_attr(int32, int, void *)
Print attribute values in string.
static std::string print_type(int32)
Print datatype in string.
static std::string get_CF_string(std::string s)
Change special characters to "_".