PageRenderTime 61ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/applications/NXtranslate/nexus_retriever.cpp

https://github.com/Acidburn0zzz/code
C++ | 238 lines | 162 code | 29 blank | 47 comment | 33 complexity | 5e808012d501950d0383609d6740079c MD5 | raw file
Possible License(s): LGPL-2.1
  1. #include <fstream>
  2. #include <stdexcept>
  3. #include <string>
  4. #include <cstring>
  5. #include "nexus_retriever.h"
  6. #include "nexus_util.h"
  7. #include "node.h"
  8. #include "retriever.h"
  9. #include "string_util.h"
  10. #include "tree.hh"
  11. using std::invalid_argument;
  12. using std::runtime_error;
  13. using std::string;
  14. using std::vector;
  15. const static int GROUP_STRING_LEN = 128;
  16. const static string SDS = "SDS";
  17. typedef tree<Node> NodeTree;
  18. /**
  19. * The factory will call the constructor with a string. The string
  20. * specifies where to locate the data (e.g. a filename), but
  21. * interpreting the string is left up to the implementing code.
  22. */
  23. NexusRetriever::NexusRetriever(const string &str): source(str){
  24. // allocate memory for the handle
  25. handle=new NXhandle;
  26. // check if the filename is nonzero
  27. if(str.size()<=0)
  28. throw invalid_argument("Cannot initialize from an empty string");
  29. // check if the file is readable
  30. { // have the variable quickly go out of scope to enable cleanup
  31. std::ifstream checkFile(source.c_str());
  32. bool is_readable(checkFile);
  33. checkFile.close();
  34. if(!is_readable)
  35. throw runtime_error(source+" is not readable");
  36. }
  37. // open the file using NAPI
  38. char filename[50];
  39. strcpy(filename,str.c_str());
  40. if(NXopen(filename,NXACC_READ,handle)!=NX_OK){
  41. delete handle;
  42. throw runtime_error("NXopen failed");
  43. }
  44. }
  45. NexusRetriever::~NexusRetriever(){
  46. if(handle!=NULL){
  47. if(NXclose(handle)!=NX_OK)
  48. throw runtime_error("NXclose failed");
  49. delete handle;
  50. }
  51. }
  52. /**
  53. * This can throw a runtime_error if something goes wrong
  54. */
  55. static void getAttrAsNode(NXhandle *handle, NodeTree &tree, string &name){
  56. // get ready to find the correct attribute
  57. if(NXinitattrdir(*handle)!=NX_OK)
  58. throw runtime_error("NXinitattrdir failed");
  59. char attr_name[GROUP_STRING_LEN];
  60. int attr_type;
  61. int num_attr;
  62. int attr_len;
  63. if(NXgetattrinfo(*handle,&num_attr)!=NX_OK)
  64. throw runtime_error("NXgetattrinfo failed");
  65. // find the correct attribute
  66. bool found=false;
  67. for( int i=0 ; i<num_attr ; i++ ){
  68. if(NXgetnextattr(*handle,attr_name,&attr_len,&attr_type)!=NX_OK)
  69. throw runtime_error("NXgetnextattr failed");
  70. if(name==attr_name){
  71. found=true;
  72. break;
  73. }
  74. }
  75. if (!found) {
  76. throw runtime_error("failed to find attribute");
  77. }
  78. // get the value
  79. int attr_dims[1]={attr_len+1};
  80. void *attr_value;
  81. if(NXmalloc(&attr_value,1,attr_dims,attr_type)!=NX_OK)
  82. throw runtime_error("NXmalloc failed");
  83. if(NXgetattr(*handle,attr_name,attr_value,attr_dims,&attr_type)!=NX_OK)
  84. throw runtime_error("NXgetattr failed");
  85. Node node(name,attr_value,1,attr_dims,attr_type);
  86. if(NXfree(&attr_value)!=NX_OK)
  87. throw runtime_error("NXfree failed");
  88. // put the attribute in the tree
  89. tree.insert(tree.begin(),node);
  90. }
  91. /**
  92. * This can throw a runtime_error if something goes wrong
  93. */
  94. static void getDataNode(NXhandle *handle, string &name, Node &node){
  95. // get the node and all of its attributes
  96. int rank=0;
  97. int type=0;
  98. int dims[NX_MAXRANK];
  99. if(NXgetinfo(*handle,&rank,dims,&type)!=NX_OK)
  100. throw runtime_error("NXgetinfo failed");
  101. // allocate space for the data
  102. void *data;
  103. if(NXmalloc(&data,rank,dims,type)!=NX_OK)
  104. throw runtime_error("NXmalloc failed");
  105. // retrieve data from the file
  106. if(NXgetdata(*handle,data)!=NX_OK)
  107. throw runtime_error("NXgetdata failed");
  108. // retrieve attributes from the file
  109. if(NXinitattrdir(*handle)!=NX_OK)
  110. throw runtime_error("NXinitattrdir failed");
  111. char attr_name[GROUP_STRING_LEN];
  112. int attr_type;
  113. int num_attr;
  114. int attr_len;
  115. if(NXgetattrinfo(*handle,&num_attr)!=NX_OK)
  116. throw runtime_error("NXgetattrinfo failed");
  117. vector<Attr> attrs;
  118. for( int i=0 ; i<num_attr ; i++ ){
  119. if(NXgetnextattr(*handle,attr_name,&attr_len,&attr_type)!=NX_OK)
  120. throw runtime_error("NXgetnextattr failed");
  121. int attr_dims[1]={attr_len+1};
  122. void *attr_value;
  123. if(NXmalloc(&attr_value,1,attr_dims,attr_type)!=NX_OK)
  124. throw runtime_error("NXmalloc failed");
  125. if(NXgetattr(*handle,attr_name,attr_value,attr_dims,&attr_type)!=NX_OK)
  126. throw runtime_error("NXgetattr failed");
  127. Attr my_attr(attr_name,attr_value,attr_len,attr_type);
  128. if(NXfree(&attr_value)!=NX_OK)
  129. throw runtime_error("NXfree failed");
  130. attrs.push_back(my_attr);
  131. }
  132. // create the data
  133. node=Node(name,data,rank,dims,type);
  134. //node.set_name(name);
  135. //node.set_data(data,rank,dims,type);
  136. node.set_attrs(attrs);
  137. // free the temporary data
  138. if(NXfree(&data)!=NX_OK)
  139. throw runtime_error("NXfree failed");
  140. }
  141. void get_subtree(NXhandle *handle, NodeTree &tree, NodeTree::pre_order_iterator parent, string &name){
  142. //std::cout << "get_subtree(handle,tree,parent," << name << ")" << std::endl; // REMOVE
  143. static const string SDS="SDS";
  144. // open the correct level and deal with things correctly
  145. string type=nexus_util::open(handle,name);
  146. Node node(name,type);
  147. bool is_data=(type==SDS);
  148. // if we are at a data get it and return
  149. if(is_data){
  150. // get the data
  151. try{
  152. getDataNode(handle,name,node);
  153. }catch(runtime_error &e){ // cleanup and rethrow
  154. nexus_util::close(handle,node);
  155. throw;
  156. }
  157. }
  158. // add the node to the tree
  159. NodeTree::pre_order_iterator new_parent;
  160. if(parent==tree.end())
  161. new_parent=tree.insert(tree.begin(),node);
  162. else
  163. new_parent=tree.append_child(parent,node);
  164. if(!is_data){
  165. // get the listing and check result
  166. typedef vector<string> StringVec;
  167. StringVec listing=nexus_util::get_list(handle);
  168. if(listing.size()%2 || !listing.size()){
  169. nexus_util::close(handle,node);
  170. throw runtime_error("listing of NeXus file returned odd result");
  171. }
  172. // itterate through the listing
  173. for( StringVec::iterator it=listing.begin() ; it!=listing.end() ; it+=2 )
  174. get_subtree(handle,tree,new_parent,*it);
  175. }
  176. // close the path to the node
  177. nexus_util::close(handle,node);
  178. }
  179. /**
  180. * This is the method for retrieving data from a file. The whole
  181. * tree will be written to the new file immediately after being
  182. * called. Interpreting the string is left up to the implementing
  183. * code.
  184. */
  185. void NexusRetriever::getData(const string &location, NodeTree &tree){
  186. //std::cout << "\"" << source << "\"." << "getData(" << location << ",tree)" << std::endl; // REMOVE
  187. if(location.size()<=0)
  188. throw invalid_argument("cannot parse empty string");
  189. // get the name
  190. vector<string> path=string_util::string_to_path(location);
  191. string name=*(path.rbegin());
  192. // remove the last bit from the path
  193. path.pop_back();
  194. // open the path to the node
  195. int num_group=0;
  196. int num_data=0;
  197. nexus_util::open_path(handle,path,num_group,num_data);
  198. // get the subtree
  199. if(num_data>0)
  200. getAttrAsNode(handle,tree,name);
  201. else
  202. get_subtree(handle,tree,tree.end(),name);
  203. // close the path to the node
  204. nexus_util::close_path(handle,num_group,num_data);
  205. }
  206. const string NexusRetriever::MIME_TYPE("application/x-NeXus");
  207. string NexusRetriever::toString() const{
  208. return "["+MIME_TYPE+"] "+source;
  209. }