/*************************************************************************** * Copyright (C) 2005 by Nicolas PASCAL * * nicolas.pascal@icare.univ-lille1.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "hdffilemetadata.h" string HDFFileMetaData::xml_header=""; HDFFileMetaData::HDFFileMetaData( const Hdf_file * _hdf_file) { if (_hdf_file != NULL) { hdf_file=const_cast(_hdf_file); stand_alone_read = false; // Hdf_file given in argument -> initialized outside of this class persistent_xml_file=false; init(); } } HDFFileMetaData::HDFFileMetaData( const char * _hdf_file_name) { if (_hdf_file_name!=NULL) { init_input_hdf_file(_hdf_file_name); } init(); } HDFFileMetaData::HDFFileMetaData( const string & _hdf_file_name) { if (&_hdf_file_name!=NULL) { init_input_hdf_file(_hdf_file_name.c_str()); } init(); } HDFFileMetaData::~HDFFileMetaData() { if (&output_file != NULL) output_file.close(); if (stand_alone_read) { delete hdf_file; hdf_file = NULL; } int return_code = -1; if ( ! persistent_xml_file && output_filename!="" ) { // erase xml file if temp file used string cmd = "rm -f "+output_filename; return_code = system(cmd.c_str()); } if (root_node!=NULL) { delete root_node; } } void HDFFileMetaData::init_input_hdf_file( const char * input_file_name ) { hdf_file = new Hdf_file(input_file_name,DFACC_READ); stand_alone_read = true; } void HDFFileMetaData::init_output_file( const string _output_filename, const bool overwrite, const bool create_temp_file ) { if (!create_temp_file) { persistent_xml_file = true; if (_output_filename!="" && (!exists_file(_output_filename) || overwrite)) { // if the file already exists, and can't be overwritten -> error msg // open output file output_filename=_output_filename; try { if (output_file.is_open()) { // eventually close already opened output_file output_file.close(); } output_file.open(output_filename.c_str(),ofstream::out); } catch (...) { cout<<"Unexpected exception in "<<__FILE__<<" at "<<__LINE__<"; // build the output xml file if (!input_file_lines.empty()) { parse_string_to_xml(input_file_lines.begin(),input_file_lines.end()-1,0); } // at this point, the data have been stored in the xml file : free allocated vectors input_file_lines.clear(); // close the root node output_file<"; } } void HDFFileMetaData::build_tree() { // format the input metadata load_input_file_metadata(); if (!input_file_lines.empty()) { root_node=parse_string(input_file_lines.begin(),input_file_lines.end()-1); }else{ root_node=NULL; } // at this point, the data have been stored in the xml file : free allocated vectors input_file_lines.clear(); } HDFMetadataNode * HDFFileMetaData::parse_string( vector< string >::iterator start, vector< string >::iterator end ) { uint start_index = distance(input_file_lines.begin(),start); uint end_index = distance(input_file_lines.begin(),end); // return value HDFMetadataNode* my_node=NULL; if (start_index>=0 && end_index::iterator end_group=find_end_tag( start, tag,val ); // parse children if (end_group!=vector ::iterator(0)) my_node->set_child(parse_string(start+1, end_group-1)); // parse next group if (end_group!=vector ::iterator(0)) my_node->set_next_sibling(parse_string(end_group+1, end)); } else if (tag == "VALUE") { // create node of the good type int typecode=get_val_type(val); if (typecode!=HDFMetadataNode::BAD) { if (typecode==HDFMetadataNode::INTEGER) { int* v = new int(MyTools::string2int(val)); my_node=new HDFMetadataNode((void*)v,HDFMetadataNode::INTEGER); } else if (typecode==HDFMetadataNode::FLOAT) { float* v = new float(MyTools::string2int(val)); my_node=new HDFMetadataNode((void*)v,HDFMetadataNode::FLOAT); } else if (typecode==HDFMetadataNode::STRING) { string *v = new string(val); my_node=new HDFMetadataNode((void*)v,HDFMetadataNode::STRING); } else if (typecode==HDFMetadataNode::ARRAY_INTEGER) { vector* v = new vector; build_array_value((void*)v,val); my_node=new HDFMetadataNode((void*)v,HDFMetadataNode::ARRAY_INTEGER); } else if (typecode==HDFMetadataNode::ARRAY_FLOAT) { vector* v = new vector; build_array_value((void*)v,val); my_node=new HDFMetadataNode((void*)v,HDFMetadataNode::ARRAY_FLOAT); } else if (typecode==HDFMetadataNode::ARRAY_STRING) { vector* v = new vector; build_array_value((void*)v,val); my_node=new HDFMetadataNode((void*)v,HDFMetadataNode::ARRAY_STRING); } else { cerr<<"HDFFileMetaData::parse_string : in "<<__FILE__<<" at "<<__LINE__<<", array of this type are not treated at this time. Sorry"<has_attr(meta_name)) { Hdf_attr meta = (hdf_file->get_attr(meta_name)); // read it line by line size_t end = meta.get_nvalues(); char cdata[end]; meta.get_values(cdata); bool in_quotes = false; string buffer; buffer.reserve(2048); char c; // format the metadata : remove empty lines, spaces ( not inner quotes ones )... size_t i = 0; while (i copy all since next quote if (c=='"') in_quotes=false; else buffer+=c; } ++i; } // remove END at the end of file if present if (*(input_file_lines.end()-1) == "END") input_file_lines.pop_back(); } } void HDFFileMetaData::init() { build_tree(); } void HDFFileMetaData::to_xml( const char* _output_filename, const bool overwrite) { assert(hdf_file!=NULL); // format output xml name string s_output_filename; if (_output_filename!=NULL) s_output_filename=(_output_filename); else { // output file name is the input file name radix with the xml extension s_output_filename=(hdf_file->get_filename()); } // check and eventually add the extension size_t ext_pos = s_output_filename.find_last_of( '.' ); if (ext_pos != s_output_filename.npos && s_output_filename.substr( ext_pos )!= "xml") // already have an extension, but different than "xml" s_output_filename.replace( ext_pos + 1, s_output_filename.size() - 1, "xml" ); else s_output_filename+=".xml"; // open a non temporary output file, and write xml header write_xml_file(s_output_filename,overwrite,false); } void HDFFileMetaData::parse_string_to_xml( vector ::iterator start,vector ::iterator end , int rank) { size_t start_index = distance(input_file_lines.begin(),start); size_t end_index = distance(input_file_lines.begin(),end); if (start_index>=0 && end_index"; // search for END_GROUP TAG corresponding to this value. Skip non corresponding lines. vector ::iterator end_group=find_end_tag( start, tag,val ); if (end_group!=vector ::iterator(0)) parse_string_to_xml(start+1, end_group-1, rank+1);// parse group inner tags // close tag output_file<"; // parse next group if (end_group!=vector ::iterator(0)) parse_string_to_xml(end_group+1, end, rank); } else if (tag == "OBJECT") { // open tag output_file<"; // search for END_OBJECT TAG corresponding to this value. Skip non corresponding lines. vector ::iterator end_object=find_end_tag( start, tag,val ); if (end_object!=vector ::iterator(0)) parse_string_to_xml(start+1, end_object-1, rank+1);// parse object inner tags // close tag output_file<<""; // parse next object if (end_object!=vector ::iterator(0)) parse_string_to_xml(end_object+1, end, rank); } else if (tag == "VALUE") { // write value output_file<::iterator HDFFileMetaData::find_end_tag( vector< string >::iterator start, const string & tag, const string & val ) { vector< string >::iterator local_start(start); while (local_start!=input_file_lines.end() && ( (*local_start).find("END_"+tag,0)==string::npos || (*local_start).find(val)==string::npos)) { ++local_start; } if (local_start!=input_file_lines.end()) // end object tag found return local_start; else return vector< string >::iterator(0); } void HDFFileMetaData::extract_tag_val( string & tag, string & val, vector< string >::iterator & line ) { // PRECONDITION all spaces have been removed size_t tag_start = 0; size_t tag_end = (*line).find_first_of('=',0); size_t val_start = tag_end+1; size_t val_end = (*line).size(); tag=line->substr(tag_start,tag_end-tag_start); val=line->substr(val_start,val_end-val_start); } void HDFFileMetaData::get_value( void * val, const char * tag_name ) { get_node_value(root_node,val,tag_name); } void HDFFileMetaData::build_array_value(void* val, const string &s_val) { string s=s_val; // local copy if (s[0]=='(') s.erase(0,1); if (s[s.size()-1]==')') s.erase(s.size()-1,1); // determine the type of the values : read the 1st value and get its type size_t start = 0; size_t coma_pos = s.find_first_of(',',0); int val_type = get_val_type(s.substr(start,coma_pos-start)); string s_idx_val; bool parsing_finished=false; while (!parsing_finished) { s_idx_val=s.substr(start,coma_pos-start); switch(val_type) { case HDFMetadataNode::INTEGER: ((vector*)val)->push_back(MyTools::string2int(s_idx_val)); break; case HDFMetadataNode::FLOAT : ((vector*)val)->push_back(MyTools::string2double(s_idx_val)); break; case HDFMetadataNode::STRING : ((vector*)val)->push_back(string(s_idx_val)); break; default: cerr<<"Unexpected Value Type "<print_val(); cout<get_child(),rank+1); // siblings view_node(node->get_next_sibling(),rank); } } const bool HDFFileMetaData::get_tree_value( void* val, const string & tag_name) { return get_node_value(root_node,val,tag_name); } const bool HDFFileMetaData::get_tree_value_string( string &val, const string & tag_name) { return get_node_value_string(root_node,val,tag_name); } const bool HDFFileMetaData::get_node_value_string( HDFMetadataNode* node, string &val, const string & tag_name) { char *val_char= new char[1024]; void *val_void=val_char; bool found = false; if (node!=NULL) { if (node->get_typecode()==HDFMetadataNode::STRING && (*static_cast(node->get_value()))==tag_name) { // node found HDFMetadataNode* leaf_node=node->get_child(); if (leaf_node->is_leaf()) { leaf_node->read_node_value(val_void); if(val_void!=NULL){ HDFMetadataNode::value_type typecode = leaf_node->get_typecode(); found=true; if(typecode == HDFMetadataNode::STRING){ val = string(static_cast(val_void)); }else if(typecode == HDFMetadataNode::INTEGER){ int *x; x = (int*)val_void; val = MyTools::to_string(*x); }else if(typecode == HDFMetadataNode::FLOAT){ float *x; x = (float*)val_void; val = MyTools::to_string(*x); } else if(typecode == HDFMetadataNode::FLOAT){ float *x; x = (float*)val_void; val = MyTools::to_string(*x); } } // case HDFMetadataNode::ARRAY_INTEGER: // val = MyTools::to_string(*static_cast< vector* >(val_void)); // break; // case HDFMetadataNode::ARRAY_FLOAT: // val = MyTools::to_string(*static_cast*>(val_void)); // break; // case HDFMetadataNode::ARRAY_STRING: // val = MyTools::to_string(*static_cast*>(val_void)); // break; } } else { if(node->get_typecode()==HDFMetadataNode::BAD) return false; // children first if (!found) found=get_node_value_string(node->get_child(),val,tag_name); // siblings if (!found) found=get_node_value_string(node->get_next_sibling(),val,tag_name); } } delete []val_char; return found; } const bool HDFFileMetaData::get_node_value( HDFMetadataNode* node, void* val, const string & tag_name) { bool found = false; if (node!=NULL) { if (node->get_typecode()==HDFMetadataNode::STRING && (*static_cast(node->get_value()))==tag_name) { // node found HDFMetadataNode* leaf_node=node->get_child(); if (leaf_node->is_leaf()) { leaf_node->read_node_value(val); found=true; } } else { // children first if (!found) found=get_node_value(node->get_child(),val,tag_name); // siblings if (!found) found=get_node_value(node->get_next_sibling(),val,tag_name); } } return found; }