HdfItem.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. //
  2. // Created by patrik on 11.08.17.
  3. //
  4. #ifndef HDF4CPP_HDFITEM_H
  5. #define HDF4CPP_HDFITEM_H
  6. #include <hdf4cpp/HdfDefines.h>
  7. #include <hdf4cpp/HdfAttribute.h>
  8. #include <iostream>
  9. #include <algorithm>
  10. #include <map>
  11. #include <memory>
  12. #include <vector>
  13. #include <hdf/hdf.h>
  14. struct Range {
  15. int32 begin;
  16. int32 quantity;
  17. int32 stride;
  18. Range(int32 begin = 0, int32 quantity = 0, int32 stride = 1) : begin(begin), quantity(quantity), stride(stride) {}
  19. intn size() const {
  20. return quantity / stride;
  21. }
  22. };
  23. class HdfItemBase {
  24. public:
  25. HdfItemBase(int32 id) : id(id) {}
  26. virtual ~HdfItemBase() {}
  27. virtual bool isValid() const { return id != FAIL; }
  28. virtual Type getType() const = 0;
  29. virtual int32 getId() const = 0;
  30. virtual std::string getName() const = 0;
  31. virtual std::vector<int32> getDims() = 0;
  32. virtual intn size() const = 0;
  33. template <class T> bool read(std::vector<T> &dest, const std::vector<Range>& ranges) {
  34. if(size() == FAIL) {
  35. return false;
  36. }
  37. std::vector<int32> dims = getDims();
  38. if(ranges.size() != dims.size()) {
  39. throw std::runtime_error("HDF4CPP: incorrect number of ranges");
  40. }
  41. intn length = 1;
  42. for(int i = 0; i < dims.size(); ++i) {
  43. if(ranges[i].begin < 0 || ranges[i].begin >= dims[i] || ranges[i].quantity < 0 || ranges[i].begin + ranges[i].quantity > dims[i] || ranges[i].stride <= 0) {
  44. throw std::runtime_error("HDF4CPP: incorrect range");
  45. }
  46. length *= ranges[i].size();
  47. }
  48. if(length > 0) {
  49. auto it = typeSizeMap.find(getDataType());
  50. if(it != typeSizeMap.end()) {
  51. if(it->second != sizeof(T)) {
  52. throw std::runtime_error("HDF4CPP: type size missmatch");
  53. }
  54. } else {
  55. throw std::runtime_error("HDF4CPP: hdf data set type not supported");
  56. }
  57. dest.resize(length);
  58. return read(dest.data(), ranges);
  59. } else {
  60. return false;
  61. }
  62. }
  63. template <class T> bool read(std::vector<T> &dest) {
  64. std::vector<int32> dims = getDims();
  65. std::vector<Range> ranges(dims.size());
  66. std::transform(dims.begin(), dims.end(), ranges.begin(), [](const int32& t) {
  67. return Range(0, t);
  68. });
  69. return read(dest, ranges);
  70. }
  71. virtual HdfAttribute getAttribute(const std::string& name) = 0;
  72. protected:
  73. int32 id;
  74. virtual bool read(void *dest, const std::vector<Range>& ranges) = 0;
  75. virtual int32 getDataType() const = 0;
  76. };
  77. class HdfDatasetItem : public HdfItemBase {
  78. public:
  79. HdfDatasetItem(int32 id);
  80. ~HdfDatasetItem();
  81. Type getType() const;
  82. int32 getId() const;
  83. std::string getName() const;
  84. std::vector<int32> getDims();
  85. intn size() const;
  86. HdfAttribute getAttribute(const std::string& name);
  87. private:
  88. intn _size;
  89. int32 dataType;
  90. std::string name;
  91. bool read(void *dest, const std::vector<Range>& ranges);
  92. int32 getDataType() const;
  93. };
  94. class HdfGroupItem : public HdfItemBase {
  95. public:
  96. HdfGroupItem(int32 id);
  97. ~HdfGroupItem();
  98. Type getType() const;
  99. int32 getId() const;
  100. std::string getName() const;
  101. std::vector<int32> getDims();
  102. intn size() const;
  103. HdfAttribute getAttribute(const std::string& name);
  104. private:
  105. std::string name;
  106. bool read(void *dest, const std::vector<Range>& ranges);
  107. int32 getDataType() const;
  108. };
  109. class HdfItem {
  110. public:
  111. HdfItem(HdfItemBase *item, int32 sId, int32 vId) : item(item), sId(sId), vId(vId) {}
  112. HdfItem(const HdfItem& item) = delete;
  113. HdfItem(HdfItem&& item);
  114. bool isValid() const;
  115. Type getType() const;
  116. std::string getName() const;
  117. std::vector<int32> getDims();
  118. intn size() const;
  119. HdfAttribute getAttribute(const std::string& name);
  120. template <class T> bool read(std::vector<T> &dest, const std::vector<Range>& ranges) {
  121. if(isValid()) {
  122. return item->read(dest, ranges);
  123. } else {
  124. return false;
  125. }
  126. }
  127. template <class T> bool read(std::vector<T> &dest) {
  128. if(isValid()) {
  129. return item->read(dest);
  130. } else {
  131. return false;
  132. }
  133. }
  134. class Iterator;
  135. Iterator begin() const;
  136. Iterator end() const;
  137. private:
  138. std::unique_ptr<HdfItemBase> item;
  139. int32 sId;
  140. int32 vId;
  141. };
  142. class HdfItem::Iterator : public std::iterator<std::bidirectional_iterator_tag, HdfItem> {
  143. public:
  144. Iterator(int32 sId, int32 vId, int32 key, int32 index) : sId(sId), vId(vId), key(key), index(index) {}
  145. bool operator!=(const Iterator& it) { return index != it.index; }
  146. bool operator==(const Iterator& it) { return index == it.index; }
  147. // bool operator<(const Iterator& it) { return index < it.index; }
  148. // bool operator>(const Iterator& it) { return index > it.index; }
  149. // bool operator>=(const Iterator& it) { return index >= it.index; }
  150. // bool operator<=(const Iterator& it) { return index <= it.index; }
  151. Iterator& operator++() {
  152. ++index;
  153. return *this;
  154. }
  155. Iterator operator++(int) {
  156. Iterator it(*this);
  157. ++index;
  158. return it;
  159. }
  160. Iterator& operator--() {
  161. --index;
  162. return *this;
  163. }
  164. Iterator operator--(int) {
  165. Iterator it(*this);
  166. --index;
  167. return it;
  168. }
  169. HdfItem operator*() {
  170. int32 tag, ref;
  171. if(Vgettagref(key, index, &tag, &ref) == FAIL) {
  172. throw std::runtime_error("HDF4CPP: cannot access invalid item");
  173. }
  174. if(Visvs(key, ref)) {
  175. throw std::runtime_error("HDF4CPP: vdata not supported yet");
  176. } else if(Visvg(key, ref)) {
  177. int32 id = Vattach(vId, ref, "r");
  178. return HdfItem(new HdfGroupItem(id), sId, vId);
  179. } else {
  180. int32 id = SDselect(sId, SDreftoindex(sId, ref));
  181. return HdfItem(new HdfDatasetItem(id), sId, vId);
  182. }
  183. }
  184. private:
  185. int32 sId;
  186. int32 vId;
  187. int32 key;
  188. int32 index;
  189. };
  190. #endif //HDF4CPP_HDFITEM_H