Skip to content

Commit

Permalink
implement string attribute reading in c++ api
Browse files Browse the repository at this point in the history
also fix related bug in napi5

refs #417
  • Loading branch information
Simon Bader authored and zjttoefs committed Apr 12, 2016
1 parent 86f5e09 commit c431b5c
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 15 deletions.
74 changes: 70 additions & 4 deletions bindings/cpp/NeXusFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1109,14 +1109,38 @@ AttrInfo File::getNextAttr() {
//string & name, int & length, NXnumtype type) {
char name[NX_MAXNAMELEN];
int type;
int length;
NXstatus status = NXgetnextattr(this->m_file_id, name, &length, &type);
int rank;
int dim[NX_MAXRANK];
NXstatus status = NXgetnextattra(this->m_file_id, name, &rank, dim, &type);
if (status == NX_OK) {
AttrInfo info;
info.type = static_cast<NXnumtype>(type);
info.length = length;
info.name = string(name);
return info;

// scalar value
if (rank == 0 || (rank == 1 && dim[0] == 1)) {
info.length = 1;
return info;
}

// char (=string) or number array (1 dim)
if (rank == 1) {
info.length = dim[0];
return info;
}

// string array (2 dim char array)
if (rank == 2 && type == NX_CHAR) {
info.length = 1;
for( unsigned int d=0; d<rank; ++d){
info.dims.push_back(dim[d]);
info.length *= dim[d];
}
return info;
}

std::cerr << "ERROR iterating through attributes found array attribute not understood by this api" << std::endl;
throw Exception("getNextAttr failed", NX_ERROR);
}
else if (status == NX_EOD) {
AttrInfo info;
Expand Down Expand Up @@ -1214,6 +1238,48 @@ string File::getStrAttr(const AttrInfo & info) {
return res;
}

void File::getAttr(const std::string& name, std::vector<std::string>& array) {
if (name == NULL_STR) {
throw Exception("Supplied bad attribute name \"" + NULL_STR + "\"");
}
if (name.empty()) {
throw Exception("Supplied empty name to getAttr");
}

// get attrInfo
char attr_name[name.size()+1];
strcpy(attr_name, name.c_str());

int type;
int rank;
int dim[NX_MAXRANK];
NXstatus status = NXgetattrainfo(this->m_file_id, attr_name, &rank, dim, &type);
if (status != NX_OK) {
throw Exception("Attribute \"" + name + "\" not found");
}

if (rank != 2 || type != NX_CHAR) {
throw Exception("Attribute is not an array of strings");
}

// read data
std::string sep(", ");
char* char_data = new char[dim[0] * (dim[1] + sep.size())];
status = NXgetattra(this->m_file_id, attr_name, char_data);

// split data to strings
std::string data(char_data);

std::size_t start = 0;
std::size_t end = data.find(sep, start);
while( end!=std::string::npos) {
array.push_back(data.substr(start, (end-start)));
start = end+sep.size();
end = data.find(sep, start);
}
array.push_back(data.substr(start));
}

vector<AttrInfo> File::getAttrInfos() {
vector<AttrInfo> infos;
this->initAttrDir();
Expand Down
11 changes: 11 additions & 0 deletions bindings/cpp/NeXusFile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ namespace NeXus {
unsigned length;
/** The name of the attribute. */
std::string name;
/** The dimensions of the attribute. */
std::vector<int> dims;
};

/**
Expand Down Expand Up @@ -779,6 +781,15 @@ namespace NeXus {
*/
std::string getStrAttr(const AttrInfo & info);

/**
* Get the value of a string array attribute.
*
* \param info Which attribute to read.
*
* \param array The values of the attribute.
*/
void getAttr(const std::string& name, std::vector<std::string>& array);

/**
* \return The id of the group used for linking.
*/
Expand Down
17 changes: 6 additions & 11 deletions src/napi5.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,22 +123,18 @@ static herr_t readStringAttribute(hid_t attr, char **data)
}
} else if (ndims == 1) {
int i;
hid_t memtype;
char **strings;

strings = (char **) malloc(thedims[0] * sizeof(char*));
memtype = H5Tcopy(H5T_C_S1);
if (H5Tis_variable_str(atype)) {
H5Tset_size(memtype, H5T_VARIABLE);
} else {
strings[0] = (char *) malloc(thedims[0] * (sdim + 1) * sizeof(char));

if (! H5Tis_variable_str(atype)) {
strings[0] = (char *) malloc(thedims[0] * sdim * sizeof(char));
for(i=1; i<thedims[0]; i++) {
strings[i] = strings[0] + i * (sdim + 1);
strings[i] = strings[0] + i * sdim;
}
H5Tset_size(memtype, sdim + 1);
}

iRet = H5Aread(attr, memtype, strings);
iRet = H5Aread(attr, atype, strings[0]);
*data = malloc((sdim + 2) * thedims[0] * sizeof(char));
for(i=0; i<thedims[0]; i++) {
if (i==0) {
Expand All @@ -149,13 +145,12 @@ static herr_t readStringAttribute(hid_t attr, char **data)
}
}
if (H5Tis_variable_str(atype)) {
H5Dvlen_reclaim(memtype, space, H5P_DEFAULT, strings);
H5Dvlen_reclaim(atype, space, H5P_DEFAULT, strings);
} else {
free(strings[0]);
}

free(strings);
H5Tclose(memtype);
} else {
*data = strdup(" higher dimensional string array");
}
Expand Down

0 comments on commit c431b5c

Please sign in to comment.