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){
240 error <<
"Fail to read SDS global attributes" << endl;
241 throw_error(error.str());
246 if (attr_type == DFNT_CHAR || attr_type == DFNT_UCHAR) {
247 attr_data[attr_count] =
'\0';
251 AttrTable *at = das->get_table(
"HDF_GLOBAL");
253 at = das->add_table(
"HDF_GLOBAL",
new AttrTable);
258 if(attr_type == DFNT_UCHAR || attr_type == DFNT_CHAR){
259 string tempstring2(attr_data);
260 string tempfinalstr= string(tempstring2.c_str());
269 for (
int loc=0; loc < attr_count ; loc++) {
282bool HE2CF::set_metadata(
const string& metadata_basename,vector<string>& non_number_names, vector<string>& no_num_data)
284 bool suffix_is_num_or_null =
true;
288 list<string> one_dot_names;
291 list<string> two_dots_names;
298 for(
int i = 0; i < num_global_attributes; i++){
301 char temp_name[H4_MAX_NC_NAME];
303 int32 attr_count = 0;
304 if(SDattrinfo(sd_id, i, temp_name, &attr_type, &attr_count) == FAIL) {
307 error <<
"Fail to obtain SDS global attribute info." << endl;
308 throw_error(error.str());
311 string temp_name_str(temp_name);
314 if(temp_name_str.find(metadata_basename)==0) {
315 arrange_list(one_dot_names,two_dots_names,non_number_names,temp_name_str,list_flag);
319 list<string>::const_iterator lit;
326 if ( list_flag >= 0 && list_flag <=2) {
327 for (lit = one_dot_names.begin();lit!=one_dot_names.end();++lit) {
328 set_eosmetadata_namelist(*lit);
330 obtain_SD_attr_value(*lit,cur_data);
332 metadata.append(cur_data);
337 for (lit = two_dots_names.begin();lit!=two_dots_names.end();++lit){
338 set_eosmetadata_namelist(*lit);
340 obtain_SD_attr_value(*lit,cur_data);
341 metadata.append(cur_data);
345 if(non_number_names.size() >0) {
346 suffix_is_num_or_null =
false;
347 no_num_data.resize(non_number_names.size());
350 for (
unsigned int i =0; i<non_number_names.size();i++) {
351 set_eosmetadata_namelist(non_number_names[i]);
352 obtain_SD_attr_value(non_number_names[i],no_num_data[i]);
355 return suffix_is_num_or_null;
362void HE2CF::arrange_list(list<string> & sl1, list<string>&sl2,vector<string>&v1,
string name,
int& flag) {
365 if(name.find(
".") == string::npos) {
366 sl1.push_front(name);
367 sl2.push_front(name);
370 else if (name.find_first_of(
".") == name.find_last_of(
".")) {
372 size_t dot_pos = name.find_first_of(
".");
374 if((dot_pos+1)==name.size())
375 throw InternalErr(__FILE__, __LINE__,
"Should have characters or numbers after ." );
377 string str_after_dot = name.substr(dot_pos+1);
378 stringstream sstr(str_after_dot);
380 int number_after_dot = 0;
381 sstr >> number_after_dot;
387 else if(0 == number_after_dot) {
397 throw InternalErr(__FILE__, __LINE__,
398 "ecs metadata suffix .1 and .0.1 cannot exist at the same file" );
407 throw InternalErr(__FILE__, __LINE__,
"ecs metadata suffix .1 and .0.1 cannot exist at the same file" );
415void HE2CF::obtain_SD_attr_value(
const string& attrname,
string &cur_data) {
417 int32 sds_index = SDfindattr(sd_id, attrname.c_str());
418 if(sds_index == FAIL){
421 error <<
"Failed to obtain the SDS global attribute" << attrname << endl;
422 throw InternalErr(__FILE__, __LINE__,error.str());
426 char temp_name[H4_MAX_NC_NAME];
430 if(SDattrinfo(sd_id, sds_index, temp_name, &type, &count) == FAIL) {
433 error <<
"Failed to obtain the SDS global attribute" << attrname <<
"information" << endl;
434 throw InternalErr(__FILE__, __LINE__,error.str());
437 vector<char> attrvalue;
438 attrvalue.resize((count+1)*DFKNTsize(type));
440 if(SDreadattr(sd_id, sds_index, attrvalue.data()) == FAIL){
443 error <<
"Failed to read the SDS global attribute" << attrname << endl;
444 throw InternalErr(__FILE__, __LINE__,error.str());
451 if(attrvalue[count] !=
'\0')
452 throw InternalErr(__FILE__,__LINE__,
"the last character of the attribute buffer should be nullptr");
455 cur_data.resize(attrvalue.size()-1);
456 copy(attrvalue.begin(),attrvalue.end()-1,cur_data.begin());
460bool HE2CF::set_vgroup_map(int32 _refid,
bool isgeo)
473 int32 vgroup_id = Vattach(file_id, _refid,
"r");
474 if (FAIL == vgroup_id) {
477 error <<
"Fail to attach the vgroup " ;
478 throw_error(error.str());
482 int32 npairs = Vntagrefs(vgroup_id);
483 if (FAIL == npairs) {
487 error <<
"Fail to obtain the number of objects in a group " ;
488 throw_error(error.str());
492 for (
int i = 0; i < npairs; ++i) {
496 char buf[H4_MAX_NC_NAME];
498 if (Vgettagref(vgroup_id, i, &tag2, &ref2) < 0){
502 error <<
"Vgettagref failed for vgroup_id=." << vgroup_id;
503 throw_error(error.str());
507 if(tag2 == DFTAG_NDG){
509 int32 sds_index = SDreftoindex(sd_id, ref2);
510 if (FAIL == sds_index) {
514 error <<
"Cannot obtain the SDS index ";
515 throw_error(error.str());
519 int32 sds_id = SDselect(sd_id, sds_index);
520 if (FAIL == sds_id) {
524 error <<
"Cannot obtain the SDS ID ";
525 throw_error(error.str());
530 int32 dimsizes[H4_MAX_VAR_DIMS];
534 if(FAIL == SDgetinfo(sds_id, buf, &rank, dimsizes, &datatype, &num_attrs)) {
538 error <<
"Cannot obtain the SDS info.";
539 throw_error(error.str());
543 vg_dsd_map[string(buf)] = sds_id;
545 vg_gsd_map[string(buf)] = sds_id;
549 if(tag2 == DFTAG_VH){
552 if ((vid = VSattach(file_id, ref2,
"r")) < 0) {
557 error <<
"VSattach failed for file_id=." << file_id;
558 throw_error(error.str());
560 if (FAIL == VSgetname(vid, buf)) {
565 error <<
"VSgetname failed for file_id=." << file_id;
566 throw_error(error.str());
569 vg_dvd_map[string(buf)] = ref2;
571 vg_gvd_map[string(buf)] = ref2;
573 if (FAIL == VSdetach(vid)) {
578 error <<
"VSdetach failed for file_id=." << file_id;
579 throw_error(error.str());
585 if (FAIL == Vdetach(vgroup_id)){
588 error <<
"VSdetach failed for file_id=." << file_id;
589 throw_error(error.str());
595bool HE2CF::write_attr_long_name(
const string& _long_name,
596 const string& _varname,
599 AttrTable *at = das->get_table(_varname);
601 at = das->add_table(_varname,
new AttrTable);
604 at->append_attr(
"long_name",
"String", _long_name +
"(fake)");
607 at->append_attr(
"long_name",
"String", _long_name);
611bool HE2CF::write_attr_long_name(
const string& _group_name,
612 const string& _long_name,
613 const string& _varname,
616 AttrTable *at = das->get_table(_varname);
618 at = das->add_table(_varname,
new AttrTable);
621 at->append_attr(
"long_name",
"String",
622 _group_name +
":" + _long_name +
"(fake)");
625 at->append_attr(
"long_name",
"String",
626 _group_name +
":" + _long_name);
633HE2CF::write_attr_sd(int32 _sds_id,
const string& _newfname,
int _fieldtype)
635 char buf_var[H4_MAX_NC_NAME];
636 char buf_attr[H4_MAX_NC_NAME];
638 int32 dimsizes[H4_MAX_VAR_DIMS];
644 status = SDgetinfo(_sds_id, buf_var,
645 &rank, dimsizes, &datatype, &num_attrs);
646 if (FAIL == status) {
648 SDendaccess(_sds_id);
650 error <<
"Cannot obtain the SDS info. ";
651 throw_error(error.str());
654 AttrTable *at = das->get_table(_newfname);
656 at = das->add_table(_newfname,
new AttrTable);
660 bool v_has_coordinates =
false;
661 if(0 == _fieldtype) {
662 if(at->simple_find(
"coordinates")!= at->attr_end())
663 v_has_coordinates =
true;
667 bool llcv_has_units =
false;
670 short llcv_ignore_scale = 0;
671 short llcv_ignore_offset = 0;
672 if(1 == _fieldtype || 2 == _fieldtype) {
673 if(at->simple_find(
"units")!= at->attr_end())
674 llcv_has_units =
true;
676 llcv_ignore_scale = check_scale_offset(_sds_id,
true);
679 SDendaccess(_sds_id);
684 llcv_ignore_offset = check_scale_offset(_sds_id,
false);
687 SDendaccess(_sds_id);
702 if(-1 == llcv_ignore_offset && 2 == llcv_ignore_scale){
703 SDendaccess(_sds_id);
706 error <<
"The latitude or longitude has <scale_factor> and <add_offset> attributes, "
707 <<
" the latitude or longitude have integer type and <add_offset> is not 0, "
708 <<
" we don't support such a case in the current implementation, "
709 <<
" please report to eoshelp@hdfgroup.org if you encounter this situation.";
710 throw_error(error.str());
714 for (
int j=0; j < num_attrs; j++){
716 status = SDattrinfo(_sds_id, j, buf_attr, &datatype, &n_values);
719 SDendaccess(_sds_id);
721 error <<
"SDattrinfo() failed on " << buf_attr;
722 throw_error(error.str());
725 if(
true == v_has_coordinates) {
726 if(!strncmp(buf_attr,
"coordinates", H4_MAX_NC_NAME))
730 if(
true == llcv_has_units) {
731 if(!strncmp(buf_attr,
"units", H4_MAX_NC_NAME))
735 if( 1 == _fieldtype || 2 == _fieldtype) {
736 if(!strncmp(buf_attr,
"scale_factor", H4_MAX_NC_NAME))
737 if((1 == llcv_ignore_scale) || (2==llcv_ignore_scale) )
739 if(!strncmp(buf_attr,
"add_offset", H4_MAX_NC_NAME))
740 if(1 == llcv_ignore_offset)
745 value.resize((n_values+1) * DFKNTsize(datatype));
746 status = SDreadattr(_sds_id, j, value.data());
749 SDendaccess(_sds_id);
751 error <<
"SDreadattr() failed on " << buf_attr << endl;
752 throw_error(error.str());
756 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(
string _error)
909 throw InternalErr(__FILE__, __LINE__,
917 num_global_attributes = -1;
936 int istat = Vend(file_id);
939 error <<
"Failed to call Vend in HE2CF::close.";
940 throw_error(error.str());
948HE2CF::get_metadata(
const string& _name,
bool& suffix_is_number,vector<string>&meta_nonnum_names, vector<string>& meta_nonum_data)
950 suffix_is_number = set_metadata(_name,meta_nonnum_names,meta_nonum_data);
955HE2CF::open(
const string& _filename,
const int hc_sd_id,
const int hc_file_id)
959 error <<
"=open(): filename is empty.";
960 throw_error(error.str());
964 if(!open_vgroup(_filename,hc_file_id)){
966 error <<
"=open(): failed to open vgroup.";
967 throw_error(error.str());
971 if(!open_sd(_filename,hc_sd_id)){
973 error <<
"=open(): failed to open sd.";
974 throw_error(error.str());
986 const string& _fname,
987 const string& _newfname,
993 write_attr_long_name(_gname, _fname, _newfname, _fieldtype);
996 write_attr_long_name(_fname, _newfname, _fieldtype);
1003 if(gname != _gname){
1006 get_vgroup_field_refids(_gname, &ref_df, &ref_gf);
1008 set_vgroup_map(ref_gf,
true);
1011 set_vgroup_map(ref_df,
false);
1023 id = vg_dsd_map[_fname];
1025 write_attr_sd(
id, _newfname,_fieldtype);
1030 id = vg_dvd_map[_fname];
1032 write_attr_vdata(
id, _newfname,_fieldtype);
1035 id = vg_gsd_map[_fname];
1037 write_attr_sd(
id, _newfname,_fieldtype);
1042 id = vg_gvd_map[_fname];
1044 write_attr_vdata(
id, _newfname,_fieldtype);
1056 void* v_ptr =
nullptr;
1068 uint8 val = (uint8) value;
1070 memcpy(v_val.data(),&val,1);
1071 v_ptr = (
void*)v_val.data();
1077 int8 val = (int8) value;
1079 memcpy(v_val.data(),&val,1);
1080 v_ptr = (
void*)v_val.data();
1085 int16 val = (int16) value;
1086 v_val.resize(
sizeof(
short));
1087 memcpy(v_val.data(),&val,
sizeof(
short));
1088 v_ptr = (
void*)v_val.data();
1094 uint16 val = (uint16) value;
1095 v_val.resize(
sizeof(
unsigned short));
1096 memcpy(v_val.data(),&val,
sizeof(
unsigned short));
1097 v_ptr = (
void*)v_val.data();
1103 int32 val = (int32) value;
1104 v_val.resize(
sizeof(
int));
1105 memcpy(v_val.data(),&val,
sizeof(
int));
1106 v_ptr = (
void*)v_val.data();
1111 uint32 val = (uint32) value;
1112 v_val.resize(
sizeof(
unsigned int));
1113 memcpy(v_val.data(),&val,
sizeof(
int));
1114 v_ptr = (
void*)v_val.data();
1119 v_ptr = (
void*)&value;
1124 float64 val = (float64) value;
1125 v_val.resize(
sizeof(
double));
1126 memcpy(v_val.data(),&val,
sizeof(
double));
1127 v_ptr = (
void*)v_val.data();
1131 throw_error(
"Invalid FillValue Type - ");
1135 AttrTable *at = das->get_table(_varname);
1137 at = das->add_table(_varname,
new AttrTable);
1149 AttrTable *at = das->get_table(_varname);
1151 at = das->add_table(_varname,
new AttrTable);
1153 at->append_attr(
"coordinates",
"String", _coordinates);
1162 AttrTable *at = das->get_table(_varname);
1164 at = das->add_table(_varname,
new AttrTable);
1166 at->del_attr(
"units");
1167 at->append_attr(
"units",
"String", _units);
1187HE2CF::check_scale_offset(int32 _sds_id,
bool is_scale) {
1189 char buf_var[H4_MAX_NC_NAME];
1190 char buf_attr[H4_MAX_NC_NAME];
1192 int32 dimsizes[H4_MAX_VAR_DIMS];
1198 short ignore_so = 0;
1199 status = SDgetinfo(_sds_id, buf_var,
1200 &rank, dimsizes, &datatype, &num_attrs);
1201 if (FAIL == status) {
1202 SDendaccess(_sds_id);
1203 ostringstream error;
1204 error <<
"Cannot obtain the SDS info. ";
1205 throw_error(error.str());
1208 bool has_so =
false;
1210 int32 so_dtype = -1;
1211 int32 var_dtype = datatype;
1212 string so_name =((
true==is_scale)?
"scale_factor":
"add_offset");
1214 for (
int j=0; j < num_attrs; j++){
1216 status = SDattrinfo(_sds_id, j, buf_attr, &datatype, &n_values);
1218 SDendaccess(_sds_id);
1219 ostringstream error;
1220 error <<
"SDattrinfo() failed on " << buf_attr;
1221 throw_error(error.str());
1224 if(!strncmp(buf_attr, so_name.c_str(), H4_MAX_NC_NAME)) {
1228 so_dtype = datatype;
1235 if(
true == has_so) {
1238 value.resize(DFKNTsize(so_dtype));
1239 status = SDreadattr(_sds_id, so_index, value.data());
1241 SDendaccess(_sds_id);
1242 ostringstream error;
1243 error <<
"SDreadattr() failed on the attribute scale_factor." << endl;
1244 throw_error(error.str());
1247 if(
true == is_scale) {
1248 if(DFNT_FLOAT32 == so_dtype) {
1249 float final_scale_value = *((
float*)((
void*)(value.data())));
1250 if(final_scale_value == 1.0)
1257 else if(var_dtype !=DFNT_FLOAT32 && var_dtype != DFNT_FLOAT64)
1260 else if(DFNT_FLOAT64 == so_dtype) {
1261 double final_scale_value = *((
double*)((
void*)(value.data())));
1262 if(final_scale_value == 1.0)
1264 else if(var_dtype !=DFNT_FLOAT32 && var_dtype != DFNT_FLOAT64)
1272 if(DFNT_FLOAT32 == so_dtype || DFNT_FLOAT64 == so_dtype) {
1273 if(atof(print_rep.c_str()) == 0.0)
1277 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)
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_FillValue(const std::string &varname, int type, float val)
bool write_attribute_coordinates(const std::string &varname, std::string coord)
bool write_attribute_units(const std::string &varname, std::string units)
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 "_".
static std::string escattr(std::string s)