Browse Source

finishing file iterator

Patrik Kovacs 6 years ago
parent
commit
c32295d871
4 changed files with 94 additions and 10 deletions
  1. 47 2
      include/hdf4cpp/HdfFile.h
  2. 10 6
      lib/HdfFile.cpp
  3. 37 2
      tests/HdfFileTest.cpp
  4. BIN
      tests/test_data/small_test.hdf

+ 47 - 2
include/hdf4cpp/HdfFile.h

@@ -9,6 +9,9 @@
 #include <vector>
 
 #include <hdf4cpp/HdfItem.h>
+#include <hdf4cpp/HdfAttribute.h>
+
+
 
 class HdfFile {
   public:
@@ -23,8 +26,8 @@ class HdfFile {
 
     class Iterator;
 
-    HdfItem::Iterator begin() const;
-    HdfItem::Iterator end() const;
+    Iterator begin() const;
+    Iterator end() const;
 
   private:
     int32 getDatasetId(const std::string& name);
@@ -35,6 +38,48 @@ class HdfFile {
 
     int32 sId;
     int32 vId;
+
+    int32 loneSize;
+    std::vector<int32> loneRefs;
+};
+
+class HdfFile::Iterator : public std::iterator<std::bidirectional_iterator_tag, HdfItem> {
+public:
+    Iterator(const HdfFile* file, int32 index) : file(file), index(index) {}
+
+    bool operator!=(const Iterator& it) { return index != it.index; }
+    bool operator==(const Iterator& it) { return index == it.index; }
+
+    Iterator& operator++() {
+        ++index;
+        return *this;
+    }
+    Iterator operator++(int) {
+        Iterator it(*this);
+        ++index;
+        return it;
+    }
+    Iterator& operator--() {
+        --index;
+        return *this;
+    }
+    Iterator operator--(int) {
+        Iterator it(*this);
+        --index;
+        return it;
+    }
+
+    HdfItem operator*() {
+        if(index < 0 || index >= file->loneSize) {
+            throw std::runtime_error("HDF4CPP: cannot access invalid item");
+        }
+        int32 ref = file->loneRefs[index];
+        int32 id = Vattach(file->vId, file->loneRefs[index], "r");
+        return HdfItem(new HdfGroupItem(id), file->sId, file->vId);
+    }
+private:
+    const HdfFile *file;
+    int32 index;
 };
 
 #endif //GRASP_SEGMENTER_HDFFILE_H

+ 10 - 6
lib/HdfFile.cpp

@@ -14,6 +14,10 @@ HdfFile::HdfFile(const std::string& path) {
     sId = SDstart(path.c_str(), DFACC_READ);
     vId = Hopen(path.c_str(), DFACC_READ, 0);
     Vstart(vId);
+
+    loneSize = Vlone(vId, nullptr, 0);
+    loneRefs.resize((size_t) loneSize);
+    Vlone(vId, loneRefs.data(), loneSize);
 }
 HdfFile::~HdfFile() {
     SDend(sId);
@@ -91,14 +95,14 @@ HdfAttribute HdfFile::getAttribute(const std::string &name) {
 bool HdfFile::isValid() {
     return sId != FAIL || vId != FAIL;
 }
-HdfItem::Iterator HdfFile::begin() const {
-    return HdfItem::Iterator(sId, vId, vId, 0);
+HdfFile::Iterator HdfFile::begin() const {
+    return Iterator(this, 0);
 }
-HdfItem::Iterator HdfFile::end() const {
-    // FIXME get the number of items in the root
-    int32 size = Vntagrefs(vId);
+HdfFile::Iterator HdfFile::end() const {
+    int32 size;
+    size = Vlone(vId, nullptr, 0);
     if(size == FAIL) {
         size = 0;
     }
-    return HdfItem::Iterator(sId, vId, vId, size);
+    return Iterator(this, size);
 }

+ 37 - 2
tests/HdfFileTest.cpp

@@ -9,6 +9,20 @@ class HdfFileTest : public ::testing::Test {
 protected:
     HdfFileTest() : file(std::string(TEST_DATA_PATH) + "small_test.hdf") {}
 
+    void writeOut(const HdfItem& item, std::ostream& out, const std::string& tab = std::string()) {
+        if(!item.isValid()) return;
+        out << tab << item.getName() << '\n';
+        for(const auto& it : item) {
+            writeOut(it, out, tab + "\t");
+        }
+    }
+
+    void writeOut(const HdfFile& file, std::ostream& out) {
+        for(const auto& it : file) {
+            writeOut(it, out);
+        }
+    }
+
     HdfFile file;
 };
 
@@ -152,10 +166,31 @@ TEST_F(HdfFileTest, GlobalAttribute) {
     ASSERT_EQ(vec, std::vector<int8>({11, 22}));
 }
 
-TEST_F(HdfFileTest, DISABLED_ItemIterator1) {
+TEST_F(HdfFileTest, ItemIterator1) {
     std::ostringstream out;
     for(auto it : file) {
         out << it.getName() << '*';
     }
-    ASSERT_EQ(out.str(), std::string("Group*GroupWithOnlyAttributes*DoubleDataset*DoubleDataset*"));
+    ASSERT_EQ(out.str(), std::string("Group*GroupWithOnlyAttribute*RIG0.0*/home/patrik/HDF4CPP/tests/test_data/small_test.hdf*"));
+}
+
+TEST_F(HdfFileTest, ItemIterator2) {
+    HdfItem item = file.get("Group");
+    ASSERT_TRUE(item.isValid());
+    std::ostringstream out;
+    for(auto it : item) {
+        out << it.getName() << '*';
+    }
+    ASSERT_EQ(out.str(), "Data*DataWithAttributes*");
+}
+
+TEST_F(HdfFileTest, ItemIterator3) {
+    auto it = file.begin();
+    HdfItem item = *it;
+    ASSERT_EQ(item.getName(), "Group");
+}
+
+TEST_F(HdfFileTest, HiddenGroup) {
+    HdfItem item = file.get("RIG0.0");
+    ASSERT_TRUE(item.isValid());
 }

BIN
tests/test_data/small_test.hdf