hdf5/tools/h5repack/h5repack_parse.c
Allen Byrne 145f1ce9e3 [svn-r24104] HDFFV-8345: add User Defined filters to h5repack.
Reviewed in H5T-61

Tested: local linux - cmake and autotools
2013-09-06 10:15:50 -05:00

715 lines
19 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "h5repack.h"
#include "h5tools.h"
#include "h5tools_utils.h"
/*-------------------------------------------------------------------------
* Function: parse_filter
*
* Purpose: read filter information
*
* Return: a list of names, the number of names and its compression type
*
* <name of filter> can be:
* GZIP, to apply the HDF5 GZIP filter (GZIP compression)
* SZIP, to apply the HDF5 SZIP filter (SZIP compression)
* SHUF, to apply the HDF5 shuffle filter
* FLET, to apply the HDF5 checksum filter
* NBIT, to apply the HDF5 NBIT filter (NBIT compression)
* SOFF, to apply the HDF5 scale+offset filter (compression)
* UD, to apply a User Defined filter k, m, n1[,…,nm]
* NONE, to remove the filter
*
* Examples:
* "GZIP=6"
* "A,B:NONE"
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
*
* Date: September, 23, 2003
*
*-------------------------------------------------------------------------
*/
obj_list_t* parse_filter(const char *str,
int *n_objs,
filter_info_t *filt,
pack_opt_t *options,
int *is_glb)
{
unsigned i, u;
char c;
size_t len=HDstrlen(str);
int j, m, n, k, l, p, r, q, end_obj=-1, no_param=0;
char sobj[MAX_NC_NAME];
char scomp[10];
char stype[5];
char smask[3];
obj_list_t* obj_list=NULL;
unsigned pixels_per_block;
/* initialize compression info */
HDmemset(filt,0,sizeof(filter_info_t));
*is_glb = 0;
/* check for the end of object list and number of objects */
for ( i = 0, n = 0; i < len; i++)
{
c = str[i];
if ( c==':' )
{
end_obj=i;
}
if ( c==',' )
{
n++;
}
}
if (end_obj==-1) /* missing : */
{
/* apply to all objects */
options->all_filter=1;
*is_glb = 1;
}
n++;
obj_list = (obj_list_t*) HDmalloc(n*sizeof(obj_list_t));
if (obj_list==NULL)
{
error_msg("could not allocate object list\n");
return NULL;
}
*n_objs=n;
/* get object list */
for ( j = 0, k = 0, n = 0; j < end_obj; j++, k++)
{
c = str[j];
sobj[k] = c;
if ( c==',' || j==end_obj-1)
{
if ( c==',') sobj[k]='\0'; else sobj[k+1]='\0';
HDstrcpy(obj_list[n].obj,sobj);
HDmemset(sobj,0,sizeof(sobj));
n++;
k=-1;
}
}
/* nothing after : */
if (end_obj+1==(int)len)
{
if (obj_list) HDfree(obj_list);
error_msg("input Error: Invalid compression type in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
/* get filter additional parameters */
m=0;
for ( i=end_obj+1, k=0, j=0; i<len; i++,k++)
{
c = str[i];
scomp[k]=c;
if ( c=='=' || i==len-1)
{
if ( c=='=') /*one more parameter */
{
scomp[k]='\0'; /*cut space */
/*-------------------------------------------------------------------------
* H5Z_FILTER_SZIP
* szip has the format SZIP=<pixels per block,coding>
* pixels per block is a even number in 2-32 and coding method is 'EC' or 'NN'
* example SZIP=8,NN
*-------------------------------------------------------------------------
*/
if (HDstrcmp(scomp,"SZIP")==0)
{
l=-1; /* mask index check */
for ( m=0,u=i+1; u<len; u++,m++)
{
if (str[u]==',')
{
stype[m]='\0'; /* end digit of szip */
l=0; /* start EC or NN search */
u++; /* skip ',' */
}
c = str[u];
if (!isdigit(c) && l==-1)
{
if (obj_list) HDfree(obj_list);
error_msg("compression parameter not digit in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
if (l==-1)
stype[m]=c;
else
{
smask[l]=c;
l++;
if (l==2)
{
smask[l]='\0';
i=len-1; /* end */
(*n_objs)--; /* we counted an extra ',' */
if (HDstrcmp(smask,"NN")==0)
filt->cd_values[j++]=H5_SZIP_NN_OPTION_MASK;
else if (HDstrcmp(smask,"EC")==0)
filt->cd_values[j++]=H5_SZIP_EC_OPTION_MASK;
else
{
error_msg("szip mask must be 'NN' or 'EC' \n");
HDexit(EXIT_FAILURE);
}
}
}
} /* u */
} /*if */
/*-------------------------------------------------------------------------
* H5Z_FILTER_SCALEOFFSET
* scaleoffset has the format SOFF=<scale_factor,scale_type>
* scale_type can be
* integer datatype, H5Z_SO_INT (IN)
* float datatype using D-scaling method, H5Z_SO_FLOAT_DSCALE (DS)
* float datatype using E-scaling method, H5Z_SO_FLOAT_ESCALE (ES) , not yet implemented
* for integer datatypes, scale_factor denotes Minimum Bits
* for float datatypes, scale_factor denotes decimal scale factor
* examples
* SOFF=31,IN
* SOFF=3,DF
*-------------------------------------------------------------------------
*/
else if (HDstrcmp(scomp,"SOFF")==0)
{
l=-1; /* mask index check */
for ( m=0,u=i+1; u<len; u++,m++)
{
if (str[u]==',')
{
stype[m]='\0'; /* end digit */
l=0; /* start 'IN' , 'DS', or 'ES' search */
u++; /* skip ',' */
}
c = str[u];
if (!isdigit(c) && l==-1)
{
if (obj_list) HDfree(obj_list);
error_msg("compression parameter is not a digit in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
if (l==-1)
stype[m]=c;
else
{
smask[l]=c;
l++;
if (l==2)
{
smask[l]='\0';
i=len-1; /* end */
(*n_objs)--; /* we counted an extra ',' */
if (HDstrcmp(smask,"IN")==0)
filt->cd_values[j++]=H5Z_SO_INT;
else if (HDstrcmp(smask,"DS")==H5Z_SO_FLOAT_DSCALE)
filt->cd_values[j++]=H5Z_SO_FLOAT_DSCALE;
else
{
error_msg("scale type must be 'IN' or 'DS' \n");
HDexit(EXIT_FAILURE);
}
}
}
} /* u */
} /*if */
/*-------------------------------------------------------------------------
* User Defined
* has the format UD=<filter_number,cd_value_count,value_1[,value_2,...,value_N]>
* BZIP2 example
* UD=307,1,9
*-------------------------------------------------------------------------
*/
else if (HDstrcmp(scomp,"UD")==0)
{
l=-1; /* filter number index check */
p=-1; /* CD_VAL count check */
r=-1; /* CD_VAL check */
for ( m=0,q=0,u=i+1; u<len; u++,m++,q++)
{
if (str[u]==',')
{
stype[q]='\0'; /* end digit */
if (l==-1)
{
filt->filtn=atoi(stype);
l=0;
}
else if (p==-1)
{
filt->cd_nelmts=atoi(stype);
p=0;
}
else
r=0;
q=0;
u++; /* skip ',' */
}
c = str[u];
if (!isdigit(c) && l==-1)
{
if (obj_list) HDfree(obj_list);
error_msg("filter number parameter is not a digit in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
stype[q]=c;
if (l==0 && p==0)
{
if (r==0)
filt->cd_values[j++]=atoi(stype);
}
} /* u */
stype[q]='\0';
} /*if */
/*-------------------------------------------------------------------------
* all other filters
*-------------------------------------------------------------------------
*/
else
{
/* here we could have 1 or 2 digits */
for ( m=0,u=i+1; u<len; u++,m++)
{
c = str[u];
if (!isdigit(c)){
if (obj_list) HDfree(obj_list);
error_msg("compression parameter is not a digit in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
stype[m]=c;
} /* u */
stype[m]='\0';
} /*if */
filt->cd_values[j++]=atoi(stype);
i+=m; /* jump */
}
else if (i==len-1)
{ /*no more parameters */
scomp[k+1]='\0';
no_param=1;
}
/*-------------------------------------------------------------------------
* translate from string to filter symbol
*-------------------------------------------------------------------------
*/
/*-------------------------------------------------------------------------
* H5Z_FILTER_NONE
*-------------------------------------------------------------------------
*/
if (HDstrcmp(scomp,"NONE")==0)
{
filt->filtn=H5Z_FILTER_NONE;
filt->cd_nelmts = 0;
}
/*-------------------------------------------------------------------------
* H5Z_FILTER_DEFLATE
*-------------------------------------------------------------------------
*/
else if (HDstrcmp(scomp,"GZIP")==0)
{
filt->filtn=H5Z_FILTER_DEFLATE;
filt->cd_nelmts = 1;
if (no_param)
{ /*no more parameters, GZIP must have parameter */
if (obj_list) HDfree(obj_list);
error_msg("missing compression parameter in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
}
/*-------------------------------------------------------------------------
* H5Z_FILTER_SZIP
*-------------------------------------------------------------------------
*/
else if (HDstrcmp(scomp,"SZIP")==0)
{
filt->filtn=H5Z_FILTER_SZIP;
filt->cd_nelmts = 2;
if (no_param)
{ /*no more parameters, SZIP must have parameter */
if (obj_list) HDfree(obj_list);
error_msg("missing compression parameter in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
}
/*-------------------------------------------------------------------------
* H5Z_FILTER_SHUFFLE
*-------------------------------------------------------------------------
*/
else if (HDstrcmp(scomp,"SHUF")==0)
{
filt->filtn=H5Z_FILTER_SHUFFLE;
filt->cd_nelmts = 0;
if (m>0)
{ /*shuffle does not have parameter */
if (obj_list) HDfree(obj_list);
error_msg("extra parameter in SHUF <%s>\n",str);
HDexit(EXIT_FAILURE);
}
}
/*-------------------------------------------------------------------------
* H5Z_FILTER_FLETCHER32
*-------------------------------------------------------------------------
*/
else if (HDstrcmp(scomp,"FLET")==0)
{
filt->filtn=H5Z_FILTER_FLETCHER32;
filt->cd_nelmts = 0;
if (m>0)
{ /*shuffle does not have parameter */
if (obj_list) HDfree(obj_list);
error_msg("extra parameter in FLET <%s>\n",str);
HDexit(EXIT_FAILURE);
}
}
/*-------------------------------------------------------------------------
* H5Z_FILTER_NBIT
*-------------------------------------------------------------------------
*/
else if (HDstrcmp(scomp,"NBIT")==0)
{
filt->filtn=H5Z_FILTER_NBIT;
filt->cd_nelmts = 0;
if (m>0)
{ /*nbit does not have parameter */
if (obj_list) HDfree(obj_list);
error_msg("extra parameter in NBIT <%s>\n",str);
HDexit(EXIT_FAILURE);
}
}
/*-------------------------------------------------------------------------
* H5Z_FILTER_SCALEOFFSET
*-------------------------------------------------------------------------
*/
else if (HDstrcmp(scomp,"SOFF")==0)
{
filt->filtn=H5Z_FILTER_SCALEOFFSET;
filt->cd_nelmts = 2;
if (no_param)
{ /*no more parameters, SOFF must have parameter */
if (obj_list) HDfree(obj_list);
error_msg("missing compression parameter in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
}
/*-------------------------------------------------------------------------
* User Defined Filter
*-------------------------------------------------------------------------
*/
else if (HDstrcmp(scomp,"UD")==0)
{
if (filt->cd_nelmts != j)
{ /* parameters does not match count */
if (obj_list) HDfree(obj_list);
error_msg("incorrect number of compression parameters in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
}
else {
if (obj_list) HDfree(obj_list);
error_msg("invalid filter type in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
}
} /*i*/
/*-------------------------------------------------------------------------
* check valid parameters
*-------------------------------------------------------------------------
*/
switch (filt->filtn)
{
/*-------------------------------------------------------------------------
* H5Z_FILTER_DEFLATE
*-------------------------------------------------------------------------
*/
case H5Z_FILTER_DEFLATE:
if (filt->cd_values[0]>9 )
{
if (obj_list) HDfree(obj_list);
error_msg("invalid compression parameter in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
break;
/*-------------------------------------------------------------------------
* H5Z_FILTER_SZIP
*-------------------------------------------------------------------------
*/
case H5Z_FILTER_SZIP:
pixels_per_block=filt->cd_values[0];
if ((pixels_per_block%2)==1)
{
if (obj_list) HDfree(obj_list);
error_msg("pixels_per_block is not even in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
if (pixels_per_block>H5_SZIP_MAX_PIXELS_PER_BLOCK)
{
if (obj_list) HDfree(obj_list);
error_msg("pixels_per_block is too large in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
if ( (HDstrcmp(smask,"NN")!=0) && (HDstrcmp(smask,"EC")!=0) )
{
if (obj_list) HDfree(obj_list);
error_msg("szip mask must be 'NN' or 'EC' \n");
HDexit(EXIT_FAILURE);
}
break;
default:
break;
};
return obj_list;
}
/*-------------------------------------------------------------------------
* Function: parse_layout
*
* Purpose: read layout info
*
* Return: a list of names, the number of names and its chunking info for
* chunked. NULL, on error
* the layout type can be:
* CHUNK, to apply chunking layout
* CONTI, to apply contiguous layout
* COMPA, to apply compact layout
*
* Example:
* "AA,B,CDE:CHUNK=10X10"
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
*
* Date: December 30, 2003
*
*-------------------------------------------------------------------------
*/
obj_list_t* parse_layout(const char *str,
int *n_objs,
pack_info_t *pack, /* info about layout needed */
pack_opt_t *options)
{
obj_list_t* obj_list=NULL;
unsigned i;
char c;
size_t len=HDstrlen(str);
int j, n, k, end_obj=-1, c_index;
char sobj[MAX_NC_NAME];
char sdim[10];
char slayout[10];
HDmemset(sdim, '\0', sizeof(sdim));
HDmemset(sobj, '\0', sizeof(sobj));
HDmemset(slayout, '\0', sizeof(slayout));
/* check for the end of object list and number of objects */
for ( i=0, n=0; i<len; i++)
{
c = str[i];
if ( c==':' )
{
end_obj=i;
}
if ( c==',' )
{
n++;
}
}
if (end_obj==-1) { /* missing : chunk all */
options->all_layout=1;
}
n++;
obj_list = (obj_list_t*) HDmalloc(n*sizeof(obj_list_t));
if (obj_list==NULL)
{
error_msg("could not allocate object list\n");
return NULL;
}
*n_objs=n;
/* get object list */
for ( j=0, k=0, n=0; j<end_obj; j++,k++)
{
c = str[j];
sobj[k]=c;
if ( c==',' || j==end_obj-1)
{
if ( c==',') sobj[k]='\0'; else sobj[k+1]='\0';
HDstrcpy(obj_list[n].obj,sobj);
HDmemset(sobj,0,sizeof(sobj));
n++;
k=-1;
}
}
/* nothing after : */
if (end_obj+1==(int)len)
{
if (obj_list) HDfree(obj_list);
error_msg("in parse layout, no characters after : in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
/* get layout info */
for ( j=end_obj+1, n=0; n<=5; j++,n++)
{
if (n==5)
{
slayout[n]='\0'; /*cut string */
if (HDstrcmp(slayout,"COMPA")==0)
pack->layout=H5D_COMPACT;
else if (HDstrcmp(slayout,"CONTI")==0)
pack->layout=H5D_CONTIGUOUS;
else if (HDstrcmp(slayout,"CHUNK")==0)
pack->layout=H5D_CHUNKED;
else {
error_msg("in parse layout, not a valid layout in <%s>\n",str);
HDexit(EXIT_FAILURE);
}
}
else
{
c = str[j];
slayout[n]=c;
}
} /* j */
if ( pack->layout==H5D_CHUNKED )
{
/*-------------------------------------------------------------------------
* get chunk info
*-------------------------------------------------------------------------
*/
k=0;
if (j>(int)len)
{
if (obj_list) HDfree(obj_list);
error_msg("in parse layout, <%s> Chunk dimensions missing\n",str);
HDexit(EXIT_FAILURE);
}
for ( i=j, c_index=0; i<len; i++)
{
c = str[i];
sdim[k]=c;
k++; /*increment sdim index */
if (!isdigit(c) && c!='x'
&& c!='N' && c!='O' && c!='N' && c!='E'
){
if (obj_list) HDfree(obj_list);
error_msg("in parse layout, <%s> Not a valid character in <%s>\n",
sdim,str);
HDexit(EXIT_FAILURE);
}
if ( c=='x' || i==len-1)
{
if ( c=='x') {
sdim[k-1]='\0';
k=0;
pack->chunk.chunk_lengths[c_index]=atoi(sdim);
if (pack->chunk.chunk_lengths[c_index]==0) {
if (obj_list) HDfree(obj_list);
error_msg("in parse layout, <%s> conversion to number in <%s>\n",
sdim,str);
HDexit(EXIT_FAILURE);
}
c_index++;
}
else if (i==len-1) { /*no more parameters */
sdim[k]='\0';
k=0;
if (HDstrcmp(sdim,"NONE")==0)
{
pack->chunk.rank=-2;
}
else
{
pack->chunk.chunk_lengths[c_index]=atoi(sdim);
if (pack->chunk.chunk_lengths[c_index]==0){
if (obj_list) HDfree(obj_list);
error_msg("in parse layout, <%s> conversion to number in <%s>\n",
sdim,str);
HDexit(EXIT_FAILURE);
}
pack->chunk.rank=c_index+1;
}
} /*if */
} /*if c=='x' || i==len-1 */
} /*i*/
} /*H5D_CHUNKED*/
return obj_list;
}