diff options
Diffstat (limited to 'src/xmlview.cc')
-rw-r--r-- | src/xmlview.cc | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/src/xmlview.cc b/src/xmlview.cc new file mode 100644 index 0000000..bad9443 --- /dev/null +++ b/src/xmlview.cc @@ -0,0 +1,272 @@ +/*-------------------< >--------------------------- + +Currently missing markup for EXTENTS and DIMSCALES +If an attribute is a text string, then it will print the attribute +with a tag of <DATA>. Otherwise, it will just provide information +about the attribute (the range, length, type, name... etc). + +Does not provide refs for data right now, but I don't think they +are necessary (the query will need to be based on index anyways). + +DTD for HDF XML Markup +---------------------- +<!ELEMENT HDF4 (FILENAME?,SDS*,ANNOTATION*,ATTRIBUTE*,ERROR?)> +<!ELEMENT ERROR (#PCDATA)> +<!ELEMENT FILENAME (#PCDATA)> +<!ELEMENT SDS (DIMS,TYPE,UNITS?,NAME?,RANGE?,EXTENTS?,ANNOTATION*,ATTRIBUTE*)> +<!ELEMENT NAME (#PCDATA)> +<!ELEMENT DIMS (#PCDATA)> +<!ATTRIBUTE RANK CDATA "3"> +<!ELEMENT TYPE (#PCDATA)> +<!ELEMENT ANNOTATION (#PCDATA)> +<!ELEMENT EXTENTS (#PCDATA)> +<!ELEMENT RANGE (#PCDATA)> +<!ELEMENT ATTRIBUTE (LENGTH,TYPE,NAME,RANGE?,EXTENTS?)> + + ----------------------------------------------------*/ +#include <stdio.h> +#include <stdlib.h> +#ifdef WITH_HDF4 +#include <HDFIO.hh> +#endif +#ifdef WITH_HDF5 +#include <H5IO.hh> +#endif +#include <IEEEIO.hh> + +char filedrivername[128]; + +#define FindMinMax(dt) { \ + dt *data = (dt*)buffer; \ + min = max = (double)(data[0]); \ + for(int i=1;i<nelem;i++){ \ + double v = (double)(data[i]); \ + if(v<min) min=v; \ + if(v>max) max=v; \ + } \ + } + +// Print an XML tag for the name of the data element +// tabover<NAME>name</NAME> +void PrintNameXML(char *tab,// leading whitespace (for formating) + char *name); +// Print an XML tag for the dimensions of an array +// tabover <DIMS RANK=rank>dim1,dim2..dimN</DIMS> +void PrintDimsXML(char *tab,// leading whitespace (for formating) + int rank, + int *dims); +// Print an XML tag for the length of an array +// tabover <LENGTH>length</LENGTH> +void PrintLengthXML(char *tab,// leading whitespace (for formating) + int length); +// Print an XML tag for the data type of an array +// Must be one of Float32,Float64,Int16,Int32,Int64,Byte,Char +// Byte indicates data whereas Char indicates text (a string) +// even though both ar 8 bits +// tabover <TYPE>datatype</TYPE> +void PrintTypeXML(char *tab, // OK, you get the picture... + IObase::DataType datatype); + +// Compute the min and max for a data array. +void GetRangeXML(IObase::DataType datatype, + int nelem, + char *buffer, + double &min, + double &max); +// Print an XML tag for the Range of the data (the min/max) +// Uses GetRangeXML. +// tabover <RANGE>min,max</RANGE> +// Problem is that this forces a load of the dataset into memory +// which can be slow and memory intensive. Need to change this +// so that it can load a subset of the data into RAM (load in +// 8k blocks rather than the entire thing). +void PrintRangeXML(char *tab, + IObase::DataType datatype, + int nelem, + char *buffer); + +int main(int argc,char *argv[]){ + sprintf(filedrivername,"ERROR"); + if(argc<2){ + printf("<ERROR>missing filename</ERROR>\n"); + exit(0); + } + IObase *file = 0; + + IEEEIO *ifile = new IEEEIO(argv[1],IObase::Read); + if(!ifile->isValid()){ delete ifile; ifile=0;} + else { + sprintf(filedrivername,"IEEEIO"); + file = ifile; // success + } + +#ifdef WITH_HDF4 + HDFIO *hfile=0; + if(!file){ + hfile = new HDFIO(argv[1],IObase::Read); + if(!hfile->isValid()) {delete hfile; hfile=0;} + else { + sprintf(filedrivername,"HDF4"); + file = hfile; // success + } + } +#else + IObase *hfile=0; +#endif + +#ifdef WITH_HDF5 + H5IO *h5file=0; + if(!file){ + h5file = new H5IO(argv[1],IObase::Read); + if(!h5file->isValid()) {delete h5file; h5file=0;} + else { + sprintf(filedrivername,"HDF5"); + file = h5file; // success + } + } +#endif + + if(!file){ + printf("<ERROR>could not open file %s</ERROR>\n",argv[1]); + exit(0); + } + printf("<%s>\n",filedrivername); + // now say anything you want about the HDF file + for(int n=0,ndatasets=file->nDatasets();n<ndatasets;n++){ // for each dataset + int rank,dims[5]; + char name[128]; + IObase::DataType datatype; + puts("\t<SDS>");// begin an sds + if(hfile){ +#ifdef WITH_HDF4 + hfile->readInfo(name,datatype,rank,dims); +#endif + } + else{ + name[0]='\0'; + file->readInfo(datatype,rank,dims); + } + if(strlen(name)>0) + PrintNameXML("\t\t",name); + PrintTypeXML("\t\t",datatype); + PrintDimsXML("\t\t",rank,dims); + if(datatype!=IObase::Char){ + char *buffer = new char[IObase::nBytes(datatype,rank,dims)]; + file->read(buffer); // read the data + PrintRangeXML("\t\t",datatype,IObase::nElements(rank,dims),buffer); + delete buffer; + } + // for now, skip the annotations + for(int an=0,nannotations=file->nAnnotations();an<nannotations;an++){ + int length; + file->readAnnotationInfo(an,length); + printf("\t\t <ANNOTATION>%u</ANNOTATION>\n",length); + } + // cycle through each of the attributes + for(int a=0,nattribs=file->nAttributes();a<nattribs;a++){ + int length; + printf("\t\t<ATTRIBUTE>\n"); + file->readAttributeInfo(a,name,datatype,length); + PrintNameXML("\t\t ",name); + PrintTypeXML("\t\t ",datatype); + PrintLengthXML("\t\t ",length); + if(datatype==IObase::Char){ // its a string, so print it + char *s = new char[length+1]; + file->readAttribute(a,s); + printf("\t\t <DATA>%s</DATA>\n",s); + delete s; + } + else { + char *buffer = new char[IObase::nBytes(datatype,1,&length)]; + file->readAttribute(a,buffer); // read the data + PrintRangeXML("\t\t",datatype,length,buffer); + delete buffer; + } + printf("\t\t</ATTRIBUTE>\n"); + } + puts("\t</SDS>"); + } + printf("</%s>\n",filedrivername); + delete file; + return 0; +} + + +void PrintNameXML(char *tab,char *name){ + printf("%s<NAME>%s</NAME>\n",tab,name); +} + +void PrintDimsXML(char *tab,int rank,int *dims){ + printf("%s<DIMS RANK=\"%u\">",tab,rank); + printf("%u",dims[0]); for(int i=1;i<rank;i++) printf(",%u",dims[i]); + puts("</DIMS>"); +} + +void PrintLengthXML(char *tab,int length){ + printf("%s<LENGTH>%u</LENGTH>\n",tab,length); +} + +void PrintTypeXML(char *tab,IObase::DataType datatype){ + printf("%s<TYPE>",tab); + switch(datatype){ + case IObase::Float32: + printf("Float32"); + break; + case IObase::Float64: + printf("Float64"); + break; + case IObase::Int16: + printf("Int16"); + break; + case IObase::Int32: + printf("Int32"); + break; + case IObase::Int64: + printf("Int64"); + break; + case IObase::Byte: + printf("Byte"); + break; + case IObase::Char: + printf("Char"); + break; + default: + printf("Unknown(%d)",(int)datatype); + } + puts("</TYPE>"); +} + + +void GetRangeXML(IObase::DataType datatype,int nelem,char *buffer, + double &min,double &max){ + switch(datatype){ + case IObase::Float32: + FindMinMax(float); + break; + case IObase::Float64: + FindMinMax(double); + break; + case IObase::Int16: + FindMinMax(short); + break; + case IObase::Int32: + FindMinMax(int); + break; + case IObase::Int64: + FindMinMax(long); // well. long long for 32bit compiles + break; + case IObase::Byte: + case IObase::Char: + FindMinMax(char); + break; + default: + //printf("Unknown(%d)",(int)datatype); + return; // don't print + } +} +void PrintRangeXML(char *tab,IObase::DataType datatype,int nelem,char *buffer){ + // now compute the range in a datatype-dependent manner + double min,max; + GetRangeXML(datatype,nelem,buffer,min,max); + printf("%s<RANGE>%lf,%lf</RANGE>\n",tab,min,max); +} |