Skip to content

Commit

Permalink
Added support for validating NeXus files without an application defin…
Browse files Browse the repository at this point in the history
…ition.

As implemented now, validation happens against a minimal application definition containing
just an NXentry.

Refs #13
  • Loading branch information
mkoennecke committed Jul 15, 2016
1 parent 7988c50 commit cb4334c
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 13 deletions.
6 changes: 3 additions & 3 deletions nxvmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ int main(int argc, char *argv[])
/*
should all be 0 in production
*/
filt.warnOpt = 1;
filt.warnBase = 1;
filt.warnUndefined = 1;
filt.warnOpt = 0;
filt.warnBase = 0;
filt.warnUndefined = 0;
filt.debug = 0;


Expand Down
17 changes: 17 additions & 0 deletions src/minimal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
Just a morsel of code to define the minimal application definition. For
checking NeXus files without an application definition
*/

static const char xmlMinimal[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
<?xml-stylesheet type=\"text/xsl\" href=\"nxdlformat.xsl\" ?>\
<definition name=\"NXminimal\" extends=\"NXobject\" type=\"group\"\
category=\"application\"\
xmlns=\"http://definition.nexusformat.org/nxdl/3.1\"\
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\
xsi:schemaLocation=\"http://definition.nexusformat.org/nxdl/3.1 ../nxdl.xsd\"\
version=\"1.0b\"\
>\
<group type=\"NXentry\" name=\"entry\">\
</group>\
</definition>";
7 changes: 6 additions & 1 deletion src/nxdlutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ static void mergeInheritance(pNXVcontext self)
mergeInheritance(self);

}
#include "minimal.c"
/*--------------------------------------------------------------*/
int NXVloadAppDef(pNXVcontext self, char *nxdlFile)
{
Expand All @@ -257,7 +258,11 @@ int NXVloadAppDef(pNXVcontext self, char *nxdlFile)
pPtr = nxdlFile;
}

xmlData = self->nxdlRetriever(pPtr,self->retrieverUserData);
if(strstr(pPtr,"NXminimal") == NULL){
xmlData = self->nxdlRetriever(pPtr,self->retrieverUserData);
} else {
xmlData = strdup(xmlMinimal);
}
if(xmlData == NULL){
NXVsetLog(self,"sev","fatal");
NXVsetLog(self,"message","Failed to load application definition");
Expand Down
12 changes: 12 additions & 0 deletions src/nxvcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,15 @@ int testISO8601(char *date);
* strings are not properly read by this HDF5 function. Implemented in nxvutil.c
*/
herr_t H5NXget_attribute_string( hid_t loc_id, const char *obj_name, const char *attr_name, char *data );

/*
* validate a base class filed as fas as this is possible. Implemented in nxvfield.c
*/
void validateBaseClassField(pNXVcontext self, hid_t groupID, hid_t dataID);

/*
validation of the depends_on chain. In nxvgroup.c
*/
void validateDependsOn(pNXVcontext self, hid_t groupID,
hid_t fieldID);

46 changes: 46 additions & 0 deletions src/nxvfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -1060,3 +1060,49 @@ int NXVvalidateField(pNXVcontext self, hid_t fieldID,
self->nxdlPath = myPath;
return 0;
}
/*-----------------------------------------------------------------------*/
void validateBaseClassField(pNXVcontext self, hid_t groupID, hid_t dataID)
{
char fName[512];

H5Iget_name(dataID,fName,sizeof(fName));
NXVsetLog(self,"sev","debug");
NXVsetLog(self,"message","Validating field");
NXVsetLog(self,"dataPath",fName);
NXVlog(self);

validateDataOffsetStride(self, dataID);
validateAxes(self, dataID);
validateInterpretation(self,dataID);
validateCalibration(self,dataID);

if(H5LTfind_attribute(dataID,"depends_on") == 1){
validateDependsOn(self,groupID,dataID);
}

if(H5LTfind_attribute(dataID,"axis") == 1 &&
testAttType(dataID,"axis",H5T_INTEGER) == 0 &&
testAttType(dataID,"axis",H5T_STRING) == 0){
NXVsetLog(self,"sev","error");
NXVprintLog(self,"message","Attribute %s to %s has wrong type", "axis",fName);
NXVlog(self);
}

if(H5LTfind_attribute(dataID,"signal") == 1 &&
testAttType(dataID,"signal",H5T_INTEGER) == 0 &&
testAttType(dataID,"signal",H5T_STRING) == 0){
NXVsetLog(self,"sev","error");
NXVprintLog(self,"message","Attribute %s to %s has wrong type", "signal",fName);
NXVlog(self);
}

if(H5LTfind_attribute(dataID,"primary") == 1 &&
testAttType(dataID,"primary",H5T_INTEGER) == 0 &&
testAttType(dataID,"primary",H5T_STRING) == 0){
NXVsetLog(self,"sev","error");
NXVprintLog(self,"message","Attribute %s to %s has wrong type", "primary",fName);
NXVlog(self);
}

}

50 changes: 48 additions & 2 deletions src/nxvgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ static void validateDependsOnField(pNXVcontext self,
}
}
/*--------------------------------------------------------------*/
static void validateDependsOn(pNXVcontext self, hid_t groupID,
void validateDependsOn(pNXVcontext self, hid_t groupID,
hid_t fieldID)
{
char fname[512], dpData[1024];
Expand Down Expand Up @@ -632,6 +632,48 @@ typedef struct {
hash_table *baseNames;
pNXVcontext self;
} SecondPassData;
/*------------------ forward declaration ----------------------------*/
static herr_t SecondPassIterator(hid_t g_id,
const char *name,
const H5L_info_t *info, void *op_data);

/*--------------------------------------------------------------*/
static void validateBaseClassGroup(pNXVcontext self, hid_t group_id, char *baseClass)
{
SecondPassData spd;
char *oldNXDLPath;
char myNXDLPath[512], fName[1024];
hash_table namesSeen, baseNames;
hsize_t idx = 0;

oldNXDLPath = self->nxdlPath;
snprintf(myNXDLPath,sizeof(myNXDLPath),"/BASE/%s", baseClass);
self->nxdlPath = myNXDLPath;
NXVsetLog(self,"nxdlPath", myNXDLPath);

H5Iget_name(group_id,fName,sizeof(fName));
NXVsetLog(self,"sev","debug");
NXVsetLog(self,"dataPath",fName);
NXVsetLog(self,"message","Validating group against base class");
NXVlog(self);

hash_construct_table(&baseNames,100);
hash_construct_table(&namesSeen,2);
NXVloadBaseClass(self,&baseNames,baseClass);
spd.baseNames = &baseNames;
spd.namesSeen = &namesSeen;
spd.self = self;
H5Literate(group_id, H5_INDEX_NAME, H5_ITER_INC, &idx,
SecondPassIterator, &spd);

/*
clean up
*/
hash_free_table(&namesSeen,free);
hash_free_table(&baseNames,free);
self->nxdlPath = oldNXDLPath;
NXVsetLog(self,"nxdlPath", oldNXDLPath);
}
/*--------------------------------------------------------------*/
static herr_t SecondPassIterator(hid_t g_id,
const char *name,
Expand Down Expand Up @@ -667,13 +709,15 @@ static herr_t SecondPassIterator(hid_t g_id,
name, nxClass);
NXVlog(spd->self);
spd->self->warnCount++;
validateBaseClassGroup(spd->self, groupID, nxClass);
} else {
NXVsetLog(spd->self,"sev","warnbase");
NXVprintLog(spd->self,"message",
"Additional base class group %s of type %s found",
name, nxClass);
NXVlog(spd->self);
spd->self->warnCount++;
validateBaseClassGroup(spd->self, groupID, nxClass);
}
} else {
NXVsetLog(spd->self,"sev","warnundef");
Expand All @@ -687,7 +731,6 @@ static herr_t SecondPassIterator(hid_t g_id,
} else if (obj_info.type == H5O_TYPE_DATASET) {
dataID = H5Dopen(g_id,name,H5P_DEFAULT);
H5Iget_name(dataID, fname,sizeof(fname));
H5Dclose(dataID);
NXVsetLog(spd->self,"dataPath",fname);
if(hash_lookup((char *)name,spd->baseNames) == NULL){
NXVsetLog(spd->self,"sev","warnundef");
Expand All @@ -701,7 +744,10 @@ static herr_t SecondPassIterator(hid_t g_id,
name);
NXVlog(spd->self);
spd->self->warnCount++;
validateBaseClassField(spd->self, g_id, dataID);

}
H5Dclose(dataID);
}

return 0;
Expand Down
9 changes: 5 additions & 4 deletions src/nxvmainloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static int validatePath(pNXVcontext self, char *path, char *rawNxdlFile)
hid_t groupID;
xmlNodePtr groupNode = NULL;
char nxdlFile[512];

/*
first fix the appDef: the nxdl.xml postfix may be missing
*/
Expand Down Expand Up @@ -195,7 +195,7 @@ static herr_t NXVrootIterator(hid_t g_id,
if(strcmp(nxClass,"NXentry") != 0){
NXVsetLog(self,"sev","error");
NXVprintLog(self,"dataPath","/%s",name);
NXVprintLog(self,"message",
NXVprintLog(self,"message",
"Wrong root group class %s, expected NXentry",nxClass);
NXVlog(self);
}
Expand Down Expand Up @@ -241,10 +241,11 @@ static herr_t NXVrootIterator(hid_t g_id,
NXVsetLog(self,"sev","error");
NXVprintLog(self,"dataPath","/%s",name);
NXVprintLog(self,"message",
"Cannot validate %s, failed to find application definition",
"No application definition found for %s, continuing with NXminimal",
name);
self->errCount++;
NXVlog(self);
NXVlog(self);
validatePath(self,nxPath,"NXminimal");
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/nxvutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,9 @@ herr_t H5NXget_attribute_string( hid_t loc_id, const char *obj_name, const char
This is a memory issue waiting to happen. IMHO, there is a design issue with
H5LTget_attribute_string in itself that it does not pass in the length of the
string. Thus no check can be performed.
There is also a mmeory leak with varData. However, if I call the reclaim function
from the HDF5 API on it, I get a core dump.....
*/
strcpy(data,varData);
H5Dvlen_reclaim(attr_type, space, H5P_DEFAULT, &varData);
} else {
result = H5Aread(attr_id,attr_type,data);
}
Expand Down

0 comments on commit cb4334c

Please sign in to comment.