#include #include #include #include #include "nexus_retriever.h" #include "nexus_util.h" #include "node.h" #include "retriever.h" #include "string_util.h" #include "tree.hh" using std::invalid_argument; using std::runtime_error; using std::string; using std::vector; const static int GROUP_STRING_LEN = 128; const static string SDS = "SDS"; typedef tree NodeTree; /** * The factory will call the constructor with a string. The string * specifies where to locate the data (e.g. a filename), but * interpreting the string is left up to the implementing code. */ NexusRetriever::NexusRetriever(const string &str): source(str){ // allocate memory for the handle handle=new NXhandle; // check if the filename is nonzero if(str.size()<=0) throw invalid_argument("Cannot initialize from an empty string"); // check if the file is readable { // have the variable quickly go out of scope to enable cleanup std::ifstream checkFile(source.c_str()); bool is_readable(checkFile); checkFile.close(); if(!is_readable) throw runtime_error(source+" is not readable"); } // open the file using NAPI char filename[50]; strcpy(filename,str.c_str()); if(NXopen(filename,NXACC_READ,handle)!=NX_OK){ delete handle; throw runtime_error("NXopen failed"); } } NexusRetriever::~NexusRetriever(){ if(handle!=NULL){ if(NXclose(handle)!=NX_OK) throw runtime_error("NXclose failed"); delete handle; } } /** * This can throw a runtime_error if something goes wrong */ static void getAttrAsNode(NXhandle *handle, NodeTree &tree, string &name){ // get ready to find the correct attribute if(NXinitattrdir(*handle)!=NX_OK) throw runtime_error("NXinitattrdir failed"); char attr_name[GROUP_STRING_LEN]; int attr_type; int num_attr; int attr_len; if(NXgetattrinfo(*handle,&num_attr)!=NX_OK) throw runtime_error("NXgetattrinfo failed"); // find the correct attribute bool found=false; for( int i=0 ; i attrs; for( int i=0 ; i StringVec; StringVec listing=nexus_util::get_list(handle); if(listing.size()%2 || !listing.size()){ nexus_util::close(handle,node); throw runtime_error("listing of NeXus file returned odd result"); } // itterate through the listing for( StringVec::iterator it=listing.begin() ; it!=listing.end() ; it+=2 ) get_subtree(handle,tree,new_parent,*it); } // close the path to the node nexus_util::close(handle,node); } /** * This is the method for retrieving data from a file. The whole * tree will be written to the new file immediately after being * called. Interpreting the string is left up to the implementing * code. */ void NexusRetriever::getData(const string &location, NodeTree &tree){ //std::cout << "\"" << source << "\"." << "getData(" << location << ",tree)" << std::endl; // REMOVE if(location.size()<=0) throw invalid_argument("cannot parse empty string"); // get the name vector path=string_util::string_to_path(location); string name=*(path.rbegin()); // remove the last bit from the path path.pop_back(); // open the path to the node int num_group=0; int num_data=0; nexus_util::open_path(handle,path,num_group,num_data); // get the subtree if(num_data>0) getAttrAsNode(handle,tree,name); else get_subtree(handle,tree,tree.end(),name); // close the path to the node nexus_util::close_path(handle,num_group,num_data); } const string NexusRetriever::MIME_TYPE("application/x-NeXus"); string NexusRetriever::toString() const{ return "["+MIME_TYPE+"] "+source; }