Skip to content

Commit

Permalink
added HDF5File::listAttributes() and test
Browse files Browse the repository at this point in the history
  • Loading branch information
ukoethe committed Apr 10, 2014
1 parent c91722c commit 636b94a
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 7 deletions.
54 changes: 51 additions & 3 deletions include/vigra/hdf5impex.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ void HDF5_ls_insert(void*, const std::string &);

VIGRA_EXPORT H5O_type_t HDF5_get_type(hid_t, const char*);
extern "C" VIGRA_EXPORT herr_t HDF5_ls_inserter_callback(hid_t, const char*, const H5L_info_t*, void*);
extern "C" VIGRA_EXPORT herr_t HDF5_listAttributes_inserter_callback(hid_t, const char*, const H5A_info_t*, void*);

/********************************************************/
/* */
Expand Down Expand Up @@ -917,13 +918,14 @@ class HDF5File

bool read_only_;

// helper class for ls()
// helper classes for ls() and listAttributes()
struct ls_closure
{
virtual void insert(const std::string &) = 0;
virtual ~ls_closure() {}
};
// datastructure to hold a list of dataset and group names

// datastructure to hold a std::vector<std::string>
struct lsOpData : public ls_closure
{
std::vector<std::string> & objects;
Expand All @@ -933,7 +935,8 @@ class HDF5File
objects.push_back(x);
}
};
// (associative-)container closure

// datastructure to hold an associative container
template<class Container>
struct ls_container_data : public ls_closure
{
Expand Down Expand Up @@ -1433,6 +1436,51 @@ class HDF5File
return HDF5Handle(openCreateGroup_(group_name), &H5Gclose, "Internal error");
}

// helper function for the various listAttributes() variants.
void ls_H5Aiterate(std::string const & group_or_dataset, ls_closure & data) const
{
H5O_type_t h5_type = get_object_type_(group_or_dataset);
vigra_precondition(h5_type == H5O_TYPE_GROUP || h5_type == H5O_TYPE_DATASET,
"HDF5File::listAttributes(): object \"" + group_or_dataset + "\" is neither a group nor a dataset.");
// get object handle
HDF5Handle object_handle(h5_type == H5O_TYPE_GROUP
? const_cast<HDF5File*>(this)->openCreateGroup_(group_or_dataset)
: getDatasetHandle_(group_or_dataset),
h5_type == H5O_TYPE_GROUP
? &H5Gclose
: &H5Dclose,
"HDF5File::listAttributes(): unable to open object.");
hsize_t n = 0;
H5Aiterate2(object_handle, H5_INDEX_NAME, H5_ITER_NATIVE, &n,
HDF5_listAttributes_inserter_callback, static_cast<void*>(&data));
}

/** \brief List the attribute names of the given group or dataset.
If \a group_or_dataset is empty or <tt>"."</tt> (a dot), the command
refers to the current group of this file object.
*/
inline std::vector<std::string> listAttributes(std::string const & group_or_dataset) const
{
std::vector<std::string> list;
lsOpData data(list);
ls_H5Aiterate(group_or_dataset, data);
return list;
}

/** \brief Insert the attribute names of the given group or dataset into the given
\a container by calling <tt>container.insert(std::string)</tt>.
If \a group_or_dataset is empty or <tt>"."</tt> (a dot), the command
refers to the current group of this file object.
*/
template<class Container>
void listAttributes(std::string const & group_or_dataset, Container & container) const
{
ls_container_data<Container> data(container);
ls_H5Aiterate(group_or_dataset, data);
}

/** \brief Obtain the HDF5 handle of a attribute.
*/
HDF5Handle getAttributeHandle(std::string dataset_name, std::string attribute_name) const
Expand Down
2 changes: 1 addition & 1 deletion include/vigra/threading.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
# if BOOST_VERSION >= 105300
# include <boost/atomic.hpp>
# define VIGRA_HAS_ATOMIC 1
#endif
# endif
# define VIGRA_THREADING_NAMESPACE boost
#else
# include <thread>
Expand Down
14 changes: 11 additions & 3 deletions src/impex/hdf5impex.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,8 @@ void HDF5_ls_insert(void* operator_data, const std::string & x)
{
static_cast<HDF5File::ls_closure*>(operator_data)->insert(x);
}
// callback function for ls(), called via HDF5File::H5Literate()
// see http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2
// for as to why.

// callback function for ls(), called via HDF5File::ls_H5Literate()
extern "C"
herr_t HDF5_ls_inserter_callback(hid_t loc_id, const char* name,
const H5L_info_t*, void* operator_data)
Expand All @@ -214,6 +213,15 @@ herr_t HDF5_ls_inserter_callback(hid_t loc_id, const char* name,
return 0;
}

// callback function for listAttributes(), called via HDF5File::ls_H5Literate()
extern "C"
herr_t HDF5_listAttributes_inserter_callback(hid_t loc_id, const char* name,
const H5A_info_t*, void* operator_data)
{
HDF5_ls_insert(operator_data, name);
return 0;
}

} // namespace vigra

#endif // HasHDF5
23 changes: 23 additions & 0 deletions test/hdf5impex/test.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <set>
#include "vigra/stdimage.hxx"
#include "vigra/unittest.hxx"
#include "vigra/hdf5impex.hxx"
Expand Down Expand Up @@ -733,6 +734,10 @@ class HDF5ExportImportTest
file.writeAttribute("/string/dataset","tinyvector attribute", out_attr_3);
file.writeAttribute("/string/dataset","rgb attribute", out_attr_4);

std::vector<std::string> attr = file.listAttributes("/double/dataset");
shouldEqual(attr.size(), 2);
shouldEqual(attr[0], "int attribute");
shouldEqual(attr[1], "string attribute");

// read attributes
MultiArray<2,int> in_attr_1(MultiArrayShape<2>::type(2,3));
Expand Down Expand Up @@ -775,6 +780,24 @@ class HDF5ExportImportTest
file.writeAttribute("attrset","set_string",std::string("abc").c_str());
file.writeAttribute("attrset","set_string2",std::string("abcdef"));

std::set<std::string> many_attr;
file.listAttributes("attrset", many_attr);
shouldEqual(many_attr.size(), 14);
should(many_attr.find("set_char") != many_attr.end());
should(many_attr.find("set_int8") != many_attr.end());
should(many_attr.find("set_int16") != many_attr.end());
should(many_attr.find("set_int32") != many_attr.end());
should(many_attr.find("set_int64") != many_attr.end());
should(many_attr.find("set_uint8") != many_attr.end());
should(many_attr.find("set_uint16") != many_attr.end());
should(many_attr.find("set_uint32") != many_attr.end());
should(many_attr.find("set_uint64") != many_attr.end());
should(many_attr.find("set_float") != many_attr.end());
should(many_attr.find("set_double") != many_attr.end());
should(many_attr.find("set_longdouble") != many_attr.end());
should(many_attr.find("set_string") != many_attr.end());
should(many_attr.find("set_string2") != many_attr.end());

char read_char = 0;
file.readAttribute("attrset","set_char",read_char);
should(read_char=='A');
Expand Down

0 comments on commit 636b94a

Please sign in to comment.