diff --git a/src/include/base/to_string.cc.h b/src/include/base/to_string.cc.h index 3d31a08..bf1f9d7 100644 --- a/src/include/base/to_string.cc.h +++ b/src/include/base/to_string.cc.h @@ -33,11 +33,16 @@ namespace CNORXZ { std::stringstream ss; ss << "["; - auto it = a.begin(); - for(; it != a.end()-1; ++it){ - ss << toString(*it) << ","; + if(a.size() == 0){ + ss << "]"; + } + else { + auto it = a.begin(); + for(; it != a.end()-1; ++it){ + ss << toString(*it) << ","; + } + ss << toString(*it) << "]"; } - ss << toString(*it) << "]"; return ss.str(); } @@ -46,11 +51,16 @@ namespace CNORXZ { std::stringstream ss; ss << "("; - auto it = a.begin(); - for(; it != a.end()-1; ++it){ - ss << toString(*it) << ","; + if constexpr(N == 0){ + ss << ")"; + } + else { + auto it = a.begin(); + for(; it != a.end()-1; ++it){ + ss << toString(*it) << ","; + } + ss << toString(*it) << ")"; } - ss << toString(*it) << ")"; return ss.str(); } @@ -73,6 +83,26 @@ namespace CNORXZ return String("(") + toString(p.first) + "," + toString(p.second) + ")"; } + template + String ToString>::func(const std::map& p) + { + std::stringstream ss; + ss << "{"; + if(p.size() == 0){ + ss << "}"; + } + else { + auto it = p.begin(); + auto e = p.end(); + e--; + for(; it != e; ++it){ + ss << toString(it->first) << ":" << toString(it->second) << ","; + } + ss << toString(it->first) << ":" << toString(it->second) << "}"; + } + return ss.str(); + } + template String toString(const T& a) { diff --git a/src/include/base/to_string.h b/src/include/base/to_string.h index c64711f..1b00959 100644 --- a/src/include/base/to_string.h +++ b/src/include/base/to_string.h @@ -97,6 +97,20 @@ namespace CNORXZ static String func(const std::pair& t); }; + /** *** + Specialization of ToString for maps + @tparam T key type + @tparam S value type + */ + template + struct ToString> + { + /** cast to string + @param a map to be casted + */ + static String func(const std::map& t); + }; + /** *** Specialization of ToString for DType */ diff --git a/src/opt/hdf5/include/h5_content_base.cc.h b/src/opt/hdf5/include/h5_content_base.cc.h index c4bfcd6..690f82e 100644 --- a/src/opt/hdf5/include/h5_content_base.cc.h +++ b/src/opt/hdf5/include/h5_content_base.cc.h @@ -78,9 +78,9 @@ namespace CNORXZ template - inline herr_t writeAttr(hid_t id, const String& name, const T& v, hid_t space_id) + inline herr_t writeAttr(hid_t id, const String& name, const T& v) { - return CreateAttribute::write(id, name, v, space_id); + return CreateAttribute::write(id, name, v); } } diff --git a/src/opt/hdf5/include/h5_content_base.h b/src/opt/hdf5/include/h5_content_base.h index 0c21be4..bdf346a 100644 --- a/src/opt/hdf5/include/h5_content_base.h +++ b/src/opt/hdf5/include/h5_content_base.h @@ -45,8 +45,8 @@ namespace CNORXZ ContentBase& addAttribute(const String& name, const T& value); DType getAttribute(const String& name) const; bool attributeExists(const String& name) const; - Vector getAttributes() const; - Vector getRecursiveAttributes() const; // + all parent's attributes + std::map getAttributes() const; + std::map getRecursiveAttributes() const; // + all parent's attributes protected: String mName; diff --git a/src/opt/hdf5/include/h5_group.cc.h b/src/opt/hdf5/include/h5_group.cc.h index 033c2d2..a50c64c 100644 --- a/src/opt/hdf5/include/h5_group.cc.h +++ b/src/opt/hdf5/include/h5_group.cc.h @@ -71,6 +71,23 @@ namespace CNORXZ recursion(c, std::forward(f)); }); } + + template + decltype(auto) Group::iter(F&& f) + { + RangePtr gr = *mCont.range()->sub().begin(); + auto gi = std::make_shared>(gr); + return gi->ifor( operation(std::forward(f), mCont(gi)), NoF{} ); + } + + template + decltype(auto) Group::iterRecursive(F&& f) + { + return iter( [&](const auto& c) { + f(c); + recursion(c, std::forward(f)); + }); + } } } diff --git a/src/opt/hdf5/include/h5_group.h b/src/opt/hdf5/include/h5_group.h index 28c6616..afee4b1 100644 --- a/src/opt/hdf5/include/h5_group.h +++ b/src/opt/hdf5/include/h5_group.h @@ -47,7 +47,13 @@ namespace CNORXZ template decltype(auto) iterRecursive(F&& f) const; - + + template + decltype(auto) iter(F&& f); + + template + decltype(auto) iterRecursive(F&& f); + protected: template diff --git a/src/opt/hdf5/include/h5_table.h b/src/opt/hdf5/include/h5_table.h index 603631d..8885230 100644 --- a/src/opt/hdf5/include/h5_table.h +++ b/src/opt/hdf5/include/h5_table.h @@ -50,10 +50,13 @@ namespace CNORXZ STable& appendRecord(const Tuple& t); STable& appendRecord(const MArray>& t); + + MArray> read(); template decltype(auto) iterRecords(F&& f) const; }; + } } diff --git a/src/opt/hdf5/lib/h5_content_base.cc b/src/opt/hdf5/lib/h5_content_base.cc index 3418a01..ce338a6 100644 --- a/src/opt/hdf5/lib/h5_content_base.cc +++ b/src/opt/hdf5/lib/h5_content_base.cc @@ -56,11 +56,37 @@ namespace CNORXZ } case H5T_STRING: { const SizeT asize = H5Tget_size(atype_id); - Vector v(asize); + Vector v(asize+1); H5Aread(attr, atype_id, v.data()); o = DType( String( v.data() ) ); break; } + case H5T_ARRAY: { + const int ndims = H5Tget_array_ndims(atype_id); + CXZ_ASSERT(ndims, "array of dimension " << ndims << " not supported"); + hsize_t dims; + H5Tget_array_dims(atype_id, &dims); + const hid_t att_id = H5Tget_super(atype_id); + const H5T_class_t atc = H5Tget_class(att_id); + switch(atc){ + case H5T_INTEGER: { + Vector v(dims); + H5Aread(attr, atype_id, v.data()); + o = DType(v); + break; + } + case H5T_FLOAT: { + Vector v(dims); + H5Aread(attr, atype_id, v.data()); + o = DType(v); + break; + } + default: + CXZ_ERROR("attribute type id " << atype_id << " not supported"); + } + H5Tclose(att_id); + break; + } default: CXZ_ERROR("attribute type id " << atype_id << " not supported"); } @@ -78,12 +104,12 @@ namespace CNORXZ return ret; } - Vector ContentBase::getAttributes() const + std::map ContentBase::getAttributes() const { CXZ_ASSERT(isOpen(), "tried to get attribute of closed object"); struct ItData { - Vector d; + std::map d; const ContentBase* _this; } itdata; itdata._this = this; @@ -91,7 +117,8 @@ namespace CNORXZ const H5A_info_t* ainfo, void *op_data) { ItData* x = reinterpret_cast(op_data); - x->d.push_back( x->_this->getAttribute( String(attr_name) ) ); + const String n = attr_name; + x->d[n] = x->_this->getAttribute( String(attr_name) ); return static_cast(0); }; H5Aiterate(id(), H5_INDEX_NAME, H5_ITER_NATIVE, nullptr, @@ -99,12 +126,12 @@ namespace CNORXZ return itdata.d; } - Vector ContentBase::getRecursiveAttributes() const + std::map ContentBase::getRecursiveAttributes() const { - Vector out = getAttributes(); + std::map out = getAttributes(); if(mParent){ - Vector par = mParent->getRecursiveAttributes(); - out.insert(out.begin(), par.begin(), par.end()); + std::map par = mParent->getRecursiveAttributes(); + out.insert(par.begin(), par.end()); } return out; } diff --git a/src/opt/hdf5/lib/h5_file.cc b/src/opt/hdf5/lib/h5_file.cc index d1ba58c..ea05180 100644 --- a/src/opt/hdf5/lib/h5_file.cc +++ b/src/opt/hdf5/lib/h5_file.cc @@ -28,6 +28,9 @@ namespace CNORXZ File& File::open() { + if(isOpen()){ + return *this; + } Int ex = this->exists(); const String fn = this->filename(); CXZ_ASSERT( ex != 2, "tried to open non-h5 file '" << fn << "'" ); diff --git a/src/opt/hdf5/lib/h5_group.cc b/src/opt/hdf5/lib/h5_group.cc index f89b0f4..bc4bbbe 100644 --- a/src/opt/hdf5/lib/h5_group.cc +++ b/src/opt/hdf5/lib/h5_group.cc @@ -30,14 +30,16 @@ namespace CNORXZ Group& Group::open() { - if(this->exists()){ - mId = H5Gopen( mParent->id(), mName.c_str(), H5P_DEFAULT ); + if(not isOpen()){ + if(this->exists()){ + mId = H5Gopen( mParent->id(), mName.c_str(), H5P_DEFAULT ); + } + else { + mId = H5Gcreate( mParent->id(), mName.c_str(), + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT ); + } + this->mkCont(); } - else { - mId = H5Gcreate( mParent->id(), mName.c_str(), - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT ); - } - this->mkCont(); return *this; } diff --git a/src/opt/hdf5/tests/h5_basic_unit_test.cc b/src/opt/hdf5/tests/h5_basic_unit_test.cc index a0f1ce8..1221aaa 100644 --- a/src/opt/hdf5/tests/h5_basic_unit_test.cc +++ b/src/opt/hdf5/tests/h5_basic_unit_test.cc @@ -80,16 +80,27 @@ namespace File h5f(mFileName, false); EXPECT_FALSE(h5f.ro()); h5f.open(); + h5f.addAttribute("fprop", static_cast(3.141)); h5f.addGroup("gr1"); + h5f.getGroup("gr1")->addAttribute("att1", String("text")); h5f.addGroup("gr2"); h5f.addGroup("foo"); - h5f.addGroup("moregroups"); h5f.addGroup("bar"); - h5f.getGroup("moregroups")->open().addGroup("evenmore"); - h5f.getGroup("moregroups")->getGroup("evenmore")->open().addGroup("we"); - h5f.getGroup("moregroups")->getGroup("evenmore")->addGroup("need"); - h5f.getGroup("moregroups")->getGroup("evenmore")->addGroup("more"); - h5f.getGroup("moregroups")->getGroup("evenmore")->addGroup("groups"); + h5f.addGroup("moregroups"); + auto moregroups = h5f.getGroup("moregroups"); + moregroups->open().addGroup("evenmore"); + auto evenmore = moregroups->getGroup("evenmore"); + evenmore->open(); + evenmore->addAttribute("moreatt", static_cast(12)); + evenmore->addGroup("we"); + evenmore->getGroup("we")->addAttribute("wex", static_cast(9)); + evenmore->getGroup("we")->addAttribute("xy", String("xys")); + evenmore->addGroup("need"); + evenmore->getGroup("need")->addAttribute("wex", static_cast(7)); + evenmore->addGroup("more"); + evenmore->getGroup("more")->addAttribute("wex", static_cast(4)); + evenmore->addGroup("groups"); + evenmore->getGroup("groups")->addAttribute("wex", static_cast(2)); EXPECT_EQ(h5f.get().size(), 5u); h5f.close(); } @@ -100,6 +111,7 @@ namespace h5f.open(); h5f.getGroup("gr1")->open().addTable("tab1", mTabA, mFs); h5f.getGroup("gr2")->open().addTable("tab1", mTabA, mFs); + h5f.getGroup("moregroups")->open().getGroup("evenmore")->open().getGroup("need")->open().addTable("tab1", mTabA, mFs); h5f.close(); } @@ -114,13 +126,30 @@ namespace auto gr1 = h5f.getGroup("gr1"); gr1->open(); auto tab = gr1->getTable("tab1"); + DType att = gr1->getAttribute("att1"); + EXPECT_EQ(att.str(), "text"); VCHECK(tab->path()); EXPECT_EQ(tab->fields()->size(), 3u); EXPECT_EQ(tab->records()->size(), 5u); h5f.iter( [](const auto& c) { VCHECK(c->path()); } )(); h5f.iterRecursive( [](const auto& c) { VCHECK(c->path()); } )(); + h5f.iterRecursive( [](const auto& c) { c->open(); VCHECK(toString(c->getRecursiveAttributes())); } )(); + h5f.iterRecursive( [](const auto& c) { + if(c->type() == ContentType::TABLE) { c->open(); VCHECK(toString(c->getRecursiveAttributes())); } + } )(); h5f.close(); } + + TEST_F(Group_Test, ReadTable) + { + File h5f(mFileName, true); + h5f.open(); + auto tab = h5f.getGroup("gr1")->open().getTable("tab1"); + EXPECT_EQ(tab->fields()->size(), 3u); + EXPECT_EQ(tab->records()->size(), 5u); + + + } } // check write to new file