#include "H5Zmodule.h"
#include "H5private.h"
#include "H5Eprivate.h"
#include "H5Iprivate.h"
#include "H5MMprivate.h"
#include "H5Ppublic.h"
#include "H5Oprivate.h"
#include "H5Sprivate.h"
#include "H5Tprivate.h"
#include "H5Zpkg.h"
typedef struct {
unsigned size;
unsigned order;
unsigned precision;
unsigned offset;
} parms_atomic;
static htri_t H5Z__can_apply_nbit(hid_t dcpl_id, hid_t type_id, hid_t space_id);
static herr_t H5Z__set_local_nbit(hid_t dcpl_id, hid_t type_id, hid_t space_id);
static size_t H5Z__filter_nbit(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
size_t nbytes, size_t *buf_size, void **buf);
static void H5Z__calc_parms_nooptype(size_t *cd_values_actual_nparms);
static void H5Z__calc_parms_atomic(size_t *cd_values_actual_nparms);
static herr_t H5Z__calc_parms_array(const H5T_t *type, size_t *cd_values_actual_nparms);
static herr_t H5Z__calc_parms_compound(const H5T_t *type, size_t *cd_values_actual_nparms);
static herr_t H5Z__set_parms_nooptype(const H5T_t *type, unsigned *cd_values_index,
unsigned cd_values[]);
static herr_t H5Z__set_parms_atomic(const H5T_t *type, unsigned *cd_values_index,
unsigned cd_values[], hbool_t *need_not_compress);
static herr_t H5Z__set_parms_array(const H5T_t *type, unsigned *cd_values_index,
unsigned cd_values[], hbool_t *need_not_compress);
static herr_t H5Z__set_parms_compound(const H5T_t *type, unsigned *cd_values_index,
unsigned cd_values[], hbool_t *need_not_compress);
static void H5Z__nbit_next_byte(size_t *j, size_t *buf_len);
static void H5Z__nbit_decompress_one_byte(unsigned char *data, size_t data_offset,
unsigned k, unsigned begin_i, unsigned end_i, unsigned char *buffer, size_t *j,
size_t *buf_len, const parms_atomic *p, size_t datatype_len);
static void H5Z__nbit_compress_one_byte(unsigned char *data, size_t data_offset, unsigned k, unsigned begin_i,
unsigned end_i, unsigned char *buffer, size_t *j, size_t *buf_len, const parms_atomic *p, size_t datatype_len);
static void H5Z__nbit_decompress_one_nooptype(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, unsigned size);
static void H5Z__nbit_decompress_one_atomic(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const parms_atomic *p);
static herr_t H5Z__nbit_decompress_one_array(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const unsigned parms[],
unsigned *parms_index);
static herr_t H5Z__nbit_decompress_one_compound(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const unsigned parms[],
unsigned *parms_index);
static herr_t H5Z__nbit_decompress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer,
const unsigned parms[]);
static void H5Z__nbit_compress_one_nooptype(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, unsigned size);
static void H5Z__nbit_compress_one_array(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const unsigned parms[],
unsigned *parms_index);
static void H5Z__nbit_compress_one_compound(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const unsigned parms[],
unsigned *parms_index);
static void H5Z__nbit_compress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer,
size_t *buffer_size, const unsigned parms[]);
H5Z_class2_t H5Z_NBIT[1] = {{
H5Z_CLASS_T_VERS,
H5Z_FILTER_NBIT,
1,
1,
"nbit",
H5Z__can_apply_nbit,
H5Z__set_local_nbit,
H5Z__filter_nbit,
}};
#define H5Z_NBIT_ATOMIC 1
#define H5Z_NBIT_ARRAY 2
#define H5Z_NBIT_COMPOUND 3
#define H5Z_NBIT_NOOPTYPE 4
#define H5Z_NBIT_MAX_NPARMS 4096
#define H5Z_NBIT_ORDER_LE 0
#define H5Z_NBIT_ORDER_BE 1
static htri_t
H5Z__can_apply_nbit(hid_t H5_ATTR_UNUSED dcpl_id, hid_t type_id, hid_t H5_ATTR_UNUSED space_id)
{
const H5T_t *type;
htri_t ret_value = TRUE;
FUNC_ENTER_STATIC
if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
if(H5T_get_class(type, TRUE) == H5T_NO_CLASS)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype class")
if(H5T_get_size(type) == 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype size")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void
H5Z__calc_parms_nooptype(size_t *cd_values_actual_nparms)
{
*cd_values_actual_nparms += 1;
*cd_values_actual_nparms += 1;
}
static void
H5Z__calc_parms_atomic(size_t *cd_values_actual_nparms)
{
*cd_values_actual_nparms += 1;
*cd_values_actual_nparms += 1;
*cd_values_actual_nparms += 1;
*cd_values_actual_nparms += 1;
*cd_values_actual_nparms += 1;
}
static herr_t
H5Z__calc_parms_array(const H5T_t *type, size_t *cd_values_actual_nparms)
{
H5T_t *dtype_base = NULL;
H5T_class_t dtype_base_class;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
*cd_values_actual_nparms += 1;
*cd_values_actual_nparms += 1;
if(NULL == (dtype_base = H5T_get_super(type)))
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad base datatype")
if((dtype_base_class = H5T_get_class(dtype_base, TRUE)) == H5T_NO_CLASS)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad base datatype class")
switch(dtype_base_class) {
case H5T_INTEGER:
case H5T_FLOAT:
H5Z__calc_parms_atomic(cd_values_actual_nparms);
break;
case H5T_ARRAY:
if(H5Z__calc_parms_array(dtype_base, cd_values_actual_nparms) == FAIL)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot compute parameters for datatype")
break;
case H5T_COMPOUND:
if(H5Z__calc_parms_compound(dtype_base, cd_values_actual_nparms) == FAIL)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot compute parameters for datatype")
break;
case H5T_TIME:
case H5T_STRING:
case H5T_BITFIELD:
case H5T_OPAQUE:
case H5T_REFERENCE:
case H5T_ENUM:
case H5T_VLEN:
H5Z__calc_parms_nooptype(cd_values_actual_nparms);
break;
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit received bad datatype")
break;
}
done:
if(dtype_base)
if(H5T_close_real(dtype_base) < 0)
HDONE_ERROR(H5E_PLINE, H5E_CLOSEERROR, FAIL, "Unable to close base datatype")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5Z__calc_parms_compound(const H5T_t *type, size_t *cd_values_actual_nparms)
{
int nmembers;
H5T_t *dtype_member = NULL;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
*cd_values_actual_nparms += 1;
*cd_values_actual_nparms += 1;
if((nmembers = H5T_get_nmembers(type)) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype number of members")
*cd_values_actual_nparms += 1;
for(u = 0; u < (unsigned)nmembers; u++) {
H5T_class_t dtype_member_class;
if(NULL == (dtype_member = H5T_get_member_type(type, u)))
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad member datatype")
if((dtype_member_class = H5T_get_class(dtype_member, TRUE)) == H5T_NO_CLASS)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad member datatype class")
*cd_values_actual_nparms += 1;
switch(dtype_member_class) {
case H5T_INTEGER:
case H5T_FLOAT:
H5Z__calc_parms_atomic(cd_values_actual_nparms);
break;
case H5T_ARRAY:
if(H5Z__calc_parms_array(dtype_member, cd_values_actual_nparms) == FAIL)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot compute parameters for datatype")
break;
case H5T_COMPOUND:
if(H5Z__calc_parms_compound(dtype_member, cd_values_actual_nparms) == FAIL)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot compute parameters for datatype")
break;
case H5T_TIME:
case H5T_STRING:
case H5T_BITFIELD:
case H5T_OPAQUE:
case H5T_REFERENCE:
case H5T_ENUM:
case H5T_VLEN:
H5Z__calc_parms_nooptype(cd_values_actual_nparms);
break;
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit received bad datatype")
break;
}
if(H5T_close_real(dtype_member) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CLOSEERROR, FAIL, "Unable to close member datatype")
dtype_member = NULL;
}
done:
if(dtype_member)
if(H5T_close_real(dtype_member) < 0)
HDONE_ERROR(H5E_PLINE, H5E_CLOSEERROR, FAIL, "Unable to close member datatype")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5Z__set_parms_nooptype(const H5T_t *type, unsigned *cd_values_index, unsigned cd_values[])
{
size_t dtype_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
cd_values[(*cd_values_index)++] = H5Z_NBIT_NOOPTYPE;
if((dtype_size = H5T_get_size(type)) == 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype size")
H5_CHECK_OVERFLOW(dtype_size, size_t, unsigned);
cd_values[(*cd_values_index)++] = (unsigned)dtype_size;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5Z__set_parms_atomic(const H5T_t *type, unsigned *cd_values_index,
unsigned cd_values[], hbool_t *need_not_compress)
{
H5T_order_t dtype_order;
size_t dtype_size;
size_t dtype_precision;
int sdtype_offset;
unsigned dtype_offset;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
cd_values[(*cd_values_index)++] = H5Z_NBIT_ATOMIC;
if((dtype_size = H5T_get_size(type)) == 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype size")
H5_CHECK_OVERFLOW(dtype_size, size_t, unsigned);
cd_values[(*cd_values_index)++] = (unsigned)dtype_size;
if((dtype_order = H5T_get_order(type)) == H5T_ORDER_ERROR)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype endianness order")
switch(dtype_order) {
case H5T_ORDER_LE:
cd_values[(*cd_values_index)++] = H5Z_NBIT_ORDER_LE;
break;
case H5T_ORDER_BE:
cd_values[(*cd_values_index)++] = H5Z_NBIT_ORDER_BE;
break;
case H5T_ORDER_VAX:
case H5T_ORDER_MIXED:
case H5T_ORDER_ERROR:
case H5T_ORDER_NONE:
default:
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype endianness order")
}
if((dtype_precision = H5T_get_precision(type)) == 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype precision")
if((sdtype_offset = H5T_get_offset(type)) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype offset")
dtype_offset = (unsigned)sdtype_offset;
if(dtype_precision > dtype_size * 8 || (dtype_precision + dtype_offset) > dtype_size * 8)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "invalid datatype precision/offset")
H5_CHECK_OVERFLOW(dtype_precision, size_t, unsigned);
cd_values[(*cd_values_index)++] = (unsigned)dtype_precision;
cd_values[(*cd_values_index)++] = dtype_offset;
if(*need_not_compress)
if(dtype_offset != 0 || dtype_precision != dtype_size * 8)
*need_not_compress = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5Z__set_parms_array(const H5T_t *type, unsigned *cd_values_index,
unsigned cd_values[], hbool_t *need_not_compress)
{
H5T_t *dtype_base = NULL;
H5T_class_t dtype_base_class;
size_t dtype_size;
htri_t is_vlstring;
herr_t ret_value=SUCCEED;
FUNC_ENTER_STATIC
cd_values[(*cd_values_index)++] = H5Z_NBIT_ARRAY;
if((dtype_size = H5T_get_size(type)) == 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype size")
H5_CHECK_OVERFLOW(dtype_size, size_t, unsigned);
cd_values[(*cd_values_index)++] = (unsigned)dtype_size;
if(NULL == (dtype_base = H5T_get_super(type)))
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad base datatype")
if((dtype_base_class = H5T_get_class(dtype_base, TRUE)) == H5T_NO_CLASS)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad base datatype class")
switch(dtype_base_class) {
case H5T_INTEGER:
case H5T_FLOAT:
if(H5Z__set_parms_atomic(dtype_base, cd_values_index, cd_values, need_not_compress) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_ARRAY:
if(H5Z__set_parms_array(dtype_base, cd_values_index, cd_values, need_not_compress) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_COMPOUND:
if(H5Z__set_parms_compound(dtype_base, cd_values_index, cd_values, need_not_compress) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_VLEN:
if((is_vlstring = H5T_is_variable_str(dtype_base)) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot determine if datatype is a variable-length string")
if(dtype_base_class == H5T_VLEN || is_vlstring)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "datatype not supported by nbit")
if(H5Z__set_parms_nooptype(dtype_base, cd_values_index, cd_values) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_TIME:
case H5T_STRING:
case H5T_BITFIELD:
case H5T_OPAQUE:
case H5T_REFERENCE:
case H5T_ENUM:
if(H5Z__set_parms_nooptype(dtype_base, cd_values_index, cd_values) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit received bad datatype")
break;
}
done:
if(dtype_base)
if(H5T_close_real(dtype_base) < 0)
HDONE_ERROR(H5E_PLINE, H5E_CLOSEERROR, FAIL, "Unable to close base datatype")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5Z__set_parms_compound(const H5T_t *type, unsigned *cd_values_index,
unsigned cd_values[], hbool_t *need_not_compress)
{
int snmembers;
unsigned nmembers;
H5T_t *dtype_member = NULL;
H5T_class_t dtype_member_class;
size_t dtype_member_offset;
size_t dtype_next_member_offset;
size_t dtype_size;
htri_t is_vlstring;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
cd_values[(*cd_values_index)++] = H5Z_NBIT_COMPOUND;
if((dtype_size = H5T_get_size(type)) == 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype size")
H5_CHECK_OVERFLOW(dtype_size, size_t, unsigned);
cd_values[(*cd_values_index)++] = (unsigned)dtype_size;
if((snmembers = H5T_get_nmembers(type)) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype number of members")
nmembers = (unsigned)snmembers;
cd_values[(*cd_values_index)++] = nmembers;
for(u = 0; u < nmembers; u++) {
if(NULL == (dtype_member = H5T_get_member_type(type, u)))
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad member datatype")
if((dtype_member_class = H5T_get_class(dtype_member, TRUE)) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad member datatype class")
dtype_member_offset = H5T_get_member_offset(type, u);
H5_CHECK_OVERFLOW(dtype_member_offset, size_t, unsigned);
cd_values[(*cd_values_index)++] = (unsigned)dtype_member_offset;
switch(dtype_member_class) {
case H5T_INTEGER:
case H5T_FLOAT:
if(H5Z__set_parms_atomic(dtype_member, cd_values_index, cd_values, need_not_compress) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_ARRAY:
if(H5Z__set_parms_array(dtype_member, cd_values_index, cd_values, need_not_compress) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_COMPOUND:
if(H5Z__set_parms_compound(dtype_member, cd_values_index, cd_values, need_not_compress) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_VLEN:
if((is_vlstring = H5T_is_variable_str(dtype_member)) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot determine if datatype is a variable-length string")
if(dtype_member_class == H5T_VLEN || is_vlstring) {
cd_values[(*cd_values_index)++] = H5Z_NBIT_NOOPTYPE;
if(u != nmembers - 1)
dtype_next_member_offset = H5T_get_member_offset(type, u + 1);
else
dtype_next_member_offset = dtype_size;
H5_CHECK_OVERFLOW(dtype_member_offset, size_t, unsigned);
H5_CHECK_OVERFLOW(dtype_next_member_offset, size_t, unsigned);
cd_values[(*cd_values_index)++] = (unsigned)dtype_next_member_offset - (unsigned)dtype_member_offset;
}
break;
case H5T_TIME:
case H5T_STRING:
case H5T_BITFIELD:
case H5T_OPAQUE:
case H5T_REFERENCE:
case H5T_ENUM:
if(H5Z__set_parms_nooptype(dtype_member, cd_values_index, cd_values) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit was passed bad datatype")
break;
}
if(H5T_close_real(dtype_member) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CLOSEERROR, FAIL, "Unable to close member datatype")
dtype_member = NULL;
}
done:
if(dtype_member)
if(H5T_close_real(dtype_member) < 0)
HDONE_ERROR(H5E_PLINE, H5E_CLOSEERROR, FAIL, "Unable to close member datatype")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5Z__set_local_nbit(hid_t dcpl_id, hid_t type_id, hid_t space_id)
{
H5P_genplist_t *dcpl_plist;
const H5T_t *type;
const H5S_t *ds;
unsigned flags;
unsigned cd_values_index;
size_t cd_values_actual_nparms;
size_t cd_nelmts = H5Z_NBIT_USER_NPARMS;
unsigned *cd_values = NULL;
hssize_t npoints;
H5T_class_t dtype_class;
hbool_t need_not_compress;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
if((dtype_class = H5T_get_class(type, TRUE)) == H5T_NO_CLASS)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype class")
cd_values_actual_nparms = 3;
switch(dtype_class) {
case H5T_INTEGER:
case H5T_FLOAT:
H5Z__calc_parms_atomic(&cd_values_actual_nparms);
break;
case H5T_ARRAY:
if(H5Z__calc_parms_array(type, &cd_values_actual_nparms) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot compute parameters for datatype")
break;
case H5T_COMPOUND:
if(H5Z__calc_parms_compound(type, &cd_values_actual_nparms) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot compute parameters for datatype")
break;
case H5T_TIME:
case H5T_STRING:
case H5T_BITFIELD:
case H5T_OPAQUE:
case H5T_REFERENCE:
case H5T_ENUM:
case H5T_VLEN:
break;
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit received bad datatype")
break;
}
if(cd_values_actual_nparms > H5Z_NBIT_MAX_NPARMS)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "datatype needs too many nbit parameters")
if(NULL == (cd_values = (unsigned *)H5MM_malloc(cd_values_actual_nparms * sizeof(unsigned))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for cd_values[]")
if(NULL == (dcpl_plist = H5P_object_verify(dcpl_id, H5P_DATASET_CREATE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
if(H5P_get_filter_by_id(dcpl_plist, H5Z_FILTER_NBIT, &flags, &cd_nelmts, cd_values, (size_t)0, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't get nbit parameters")
if(NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
if((npoints = H5S_GET_EXTENT_NPOINTS(ds)) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "unable to get number of points in the dataspace")
HDassert(npoints);
cd_values_index = 2;
H5_CHECK_OVERFLOW(npoints, hssize_t, unsigned);
cd_values[cd_values_index++] = (unsigned)npoints;
need_not_compress = TRUE;
switch(dtype_class) {
case H5T_INTEGER:
case H5T_FLOAT:
if(H5Z__set_parms_atomic(type, &cd_values_index, cd_values, &need_not_compress) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_ARRAY:
if(H5Z__set_parms_array(type, &cd_values_index, cd_values, &need_not_compress) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_COMPOUND:
if(H5Z__set_parms_compound(type, &cd_values_index, cd_values, &need_not_compress) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit cannot set parameters for datatype")
break;
case H5T_TIME:
case H5T_STRING:
case H5T_BITFIELD:
case H5T_OPAQUE:
case H5T_REFERENCE:
case H5T_ENUM:
case H5T_VLEN:
break;
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "nbit received bad datatype")
break;
}
HDassert(cd_values_actual_nparms == cd_values_index);
H5_CHECK_OVERFLOW(cd_values_actual_nparms, size_t, unsigned);
cd_values[0] = (unsigned)cd_values_actual_nparms;
cd_values[1] = (unsigned)need_not_compress;
if(H5P_modify_filter(dcpl_plist, H5Z_FILTER_NBIT, flags, cd_values_actual_nparms, cd_values) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTSET, FAIL, "can't set local nbit parameters")
done:
if(cd_values)
H5MM_xfree(cd_values);
FUNC_LEAVE_NOAPI(ret_value)
}
static size_t
H5Z__filter_nbit(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
size_t nbytes, size_t *buf_size, void **buf)
{
unsigned char *outbuf;
size_t size_out = 0;
unsigned d_nelmts = 0;
size_t ret_value = 0;
FUNC_ENTER_STATIC
if(cd_nelmts != cd_values[0])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid nbit aggression level")
if(cd_values[1])
HGOTO_DONE(*buf_size)
d_nelmts = cd_values[2];
if(flags & H5Z_FLAG_REVERSE) {
size_out = d_nelmts * cd_values[4];
if(NULL == (outbuf = (unsigned char *)H5MM_malloc(size_out)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed for nbit decompression")
if(H5Z__nbit_decompress(outbuf, d_nelmts, (unsigned char *)*buf, cd_values) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, 0, "can't decompress buffer")
}
else {
HDassert(nbytes == d_nelmts * cd_values[4]);
size_out = nbytes;
if(NULL == (outbuf = (unsigned char *)H5MM_malloc(size_out)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed for nbit compression")
H5Z__nbit_compress((unsigned char *)*buf, d_nelmts, outbuf, &size_out, cd_values);
}
H5MM_xfree(*buf);
*buf = outbuf;
*buf_size = size_out;
ret_value = size_out;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void
H5Z__nbit_next_byte(size_t *j, size_t *buf_len)
{
++(*j);
*buf_len = 8 * sizeof(unsigned char);
}
static void
H5Z__nbit_decompress_one_byte(unsigned char *data, size_t data_offset, unsigned k,
unsigned begin_i, unsigned end_i, unsigned char *buffer, size_t *j, size_t *buf_len,
const parms_atomic *p, size_t datatype_len)
{
size_t dat_len;
size_t dat_offset;
unsigned char val;
val = buffer[*j];
dat_offset = 0;
if(begin_i != end_i) {
if(k == begin_i)
dat_len = 8 - (datatype_len - p->precision - p->offset) % 8;
else if(k == end_i) {
dat_len = 8 - p->offset % 8;
dat_offset = 8 - dat_len;
}
else
dat_len = 8;
} else {
dat_offset = p->offset % 8;
dat_len = p->precision;
}
if(*buf_len > dat_len) {
data[data_offset + k] = (unsigned char)(
((unsigned)(val >> (*buf_len - dat_len)) & (unsigned)(~((unsigned)(~0) << dat_len))) << dat_offset);
*buf_len -= dat_len;
} else {
data[data_offset + k] = (unsigned char)(
((val & ~((unsigned)(~0) << *buf_len)) << (dat_len - *buf_len)) << dat_offset);
dat_len -= *buf_len;
H5Z__nbit_next_byte(j, buf_len);
if(dat_len == 0)
return;
val = buffer[*j];
data[data_offset + k] |= (unsigned char)(
((unsigned)(val >> (*buf_len - dat_len)) & (unsigned)(~((unsigned)(~0) << dat_len))) << dat_offset);
*buf_len -= dat_len;
}
}
static void
H5Z__nbit_decompress_one_nooptype(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, unsigned size)
{
unsigned i;
size_t dat_len;
unsigned char val;
for(i = 0; i < size; i++) {
val = buffer[*j];
dat_len = sizeof(unsigned char) * 8;
data[data_offset + i] = (unsigned char)(((val & ~((unsigned)(~0) << *buf_len)) << (dat_len - *buf_len)));
dat_len -= *buf_len;
H5Z__nbit_next_byte(j, buf_len);
if(dat_len == 0)
continue;
val = buffer[*j];
data[data_offset + i] |= (unsigned char)((unsigned)(val >> (*buf_len - dat_len)) & (unsigned)(~((unsigned)(~0) << dat_len)));
*buf_len -= dat_len;
}
}
static void
H5Z__nbit_decompress_one_atomic(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const parms_atomic *p)
{
int k;
unsigned begin_i, end_i;
size_t datatype_len;
datatype_len = p->size * 8;
if(p->order == H5Z_NBIT_ORDER_LE) {
if((p->precision + p->offset) % 8 != 0)
begin_i = (p->precision + p->offset) / 8;
else
begin_i = (p->precision + p->offset) / 8 - 1;
end_i = p->offset / 8;
for(k = (int)begin_i; k >= (int)end_i; k--)
H5Z__nbit_decompress_one_byte(data, data_offset, (unsigned)k, begin_i, end_i,
buffer, j, buf_len, p, datatype_len);
}
else {
HDassert(p->order == H5Z_NBIT_ORDER_BE);
begin_i = ((unsigned)datatype_len - p->precision - p->offset) / 8;
if(p->offset % 8 != 0)
end_i = ((unsigned)datatype_len - p->offset) / 8;
else
end_i = ((unsigned)datatype_len - p->offset) / 8 - 1;
for(k = (int)begin_i; k <= (int)end_i; k++)
H5Z__nbit_decompress_one_byte(data, data_offset, (unsigned)k, begin_i, end_i,
buffer, j, buf_len, p, datatype_len);
}
}
static herr_t
H5Z__nbit_decompress_one_array(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const unsigned parms[],
unsigned *parms_index)
{
unsigned i, total_size, base_class, base_size, n, begin_index;
parms_atomic p;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
total_size = parms[(*parms_index)++];
base_class = parms[(*parms_index)++];
switch(base_class) {
case H5Z_NBIT_ATOMIC:
p.size = parms[(*parms_index)++];
p.order = parms[(*parms_index)++];
p.precision = parms[(*parms_index)++];
p.offset = parms[(*parms_index)++];
if(p.precision > p.size * 8 || (p.precision + p.offset) > p.size * 8)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "invalid datatype precision/offset")
n = total_size / p.size;
for(i = 0; i < n; i++)
H5Z__nbit_decompress_one_atomic(data, data_offset + i * p.size,
buffer, j, buf_len, &p);
break;
case H5Z_NBIT_ARRAY:
base_size = parms[*parms_index];
n = total_size / base_size;
begin_index = *parms_index;
for(i = 0; i < n; i++) {
if(H5Z__nbit_decompress_one_array(data, data_offset + i * base_size,
buffer, j, buf_len, parms, parms_index) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "can't decompress array")
*parms_index = begin_index;
}
break;
case H5Z_NBIT_COMPOUND:
base_size = parms[*parms_index];
n = total_size / base_size;
begin_index = *parms_index;
for(i = 0; i < n; i++) {
if(H5Z__nbit_decompress_one_compound(data, data_offset + i * base_size,
buffer, j, buf_len, parms, parms_index) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "can't decompress compound")
*parms_index = begin_index;
}
break;
case H5Z_NBIT_NOOPTYPE:
(*parms_index)++;
H5Z__nbit_decompress_one_nooptype(data, data_offset, buffer, j, buf_len, total_size);
break;
default:
HDassert(0 && "This Should never be executed!");
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5Z__nbit_decompress_one_compound(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const unsigned parms[],
unsigned *parms_index)
{
unsigned i, nmembers, member_offset, member_class, member_size, used_size = 0, size;
parms_atomic p;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
size = parms[(*parms_index)++];
nmembers = parms[(*parms_index)++];
for(i = 0; i < nmembers; i++) {
member_offset = parms[(*parms_index)++];
member_class = parms[(*parms_index)++];
member_size = parms[*parms_index];
used_size += member_size;
if(used_size > size)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "compound member offset overflowed compound size")
switch(member_class) {
case H5Z_NBIT_ATOMIC:
p.size = member_size;
(*parms_index)++;
p.order = parms[(*parms_index)++];
p.precision = parms[(*parms_index)++];
p.offset = parms[(*parms_index)++];
if(p.precision > p.size * 8 || (p.precision + p.offset) > p.size * 8)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "invalid datatype precision/offset")
H5Z__nbit_decompress_one_atomic(data, data_offset + member_offset,
buffer, j, buf_len, &p);
break;
case H5Z_NBIT_ARRAY:
if(H5Z__nbit_decompress_one_array(data, data_offset + member_offset,
buffer, j, buf_len, parms, parms_index) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "can't decompress array")
break;
case H5Z_NBIT_COMPOUND:
if(H5Z__nbit_decompress_one_compound(data, data_offset+member_offset,
buffer, j, buf_len, parms, parms_index) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "can't decompress compound")
break;
case H5Z_NBIT_NOOPTYPE:
(*parms_index)++;
H5Z__nbit_decompress_one_nooptype(data, data_offset+member_offset,
buffer, j, buf_len, member_size);
break;
default:
HDassert(0 && "This Should never be executed!");
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5Z__nbit_decompress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer,
const unsigned parms[])
{
unsigned i;
size_t j, size;
size_t buf_len;
parms_atomic p;
unsigned parms_index;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDmemset(data, 0, d_nelmts * parms[4]);
j = 0;
buf_len = sizeof(unsigned char) * 8;
switch(parms[3]) {
case H5Z_NBIT_ATOMIC:
p.size = parms[4];
p.order = parms[5];
p.precision = parms[6];
p.offset = parms[7];
if(p.precision > p.size * 8 || (p.precision + p.offset) > p.size * 8)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "invalid datatype precision/offset")
for(i = 0; i < d_nelmts; i++)
H5Z__nbit_decompress_one_atomic(data, i * p.size, buffer, &j, &buf_len, &p);
break;
case H5Z_NBIT_ARRAY:
size = parms[4];
parms_index = 4;
for(i = 0; i < d_nelmts; i++) {
if(H5Z__nbit_decompress_one_array(data, i * size, buffer, &j, &buf_len, parms, &parms_index) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "can't decompress array")
parms_index = 4;
}
break;
case H5Z_NBIT_COMPOUND:
size = parms[4];
parms_index = 4;
for(i = 0; i < d_nelmts; i++) {
if(H5Z__nbit_decompress_one_compound(data, i * size, buffer, &j, &buf_len, parms, &parms_index) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "can't decompress compound")
parms_index = 4;
}
break;
default:
HDassert(0 && "This Should never be executed!");
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void
H5Z__nbit_compress_one_byte(unsigned char *data, size_t data_offset, unsigned k,
unsigned begin_i, unsigned end_i, unsigned char *buffer, size_t *j, size_t *buf_len,
const parms_atomic *p, size_t datatype_len)
{
size_t dat_len;
unsigned char val;
val = data[data_offset + k];
if(begin_i != end_i) {
if(k == begin_i)
dat_len = 8 - (datatype_len - p->precision - p->offset) % 8;
else if(k == end_i) {
dat_len = 8 - p->offset % 8;
val = (unsigned char)(val >> (8 - dat_len));
}
else
dat_len = 8;
} else {
val = (unsigned char)(val >> (p->offset % 8));
dat_len = p->precision;
}
if(*buf_len > dat_len) {
buffer[*j] |= (unsigned char)((val & ~((unsigned)(~0) << dat_len)) << (*buf_len - dat_len));
*buf_len -= dat_len;
} else {
buffer[*j] |= (unsigned char)((unsigned)(val >> (dat_len - *buf_len)) & ~((unsigned)(~0) << *buf_len));
dat_len -= *buf_len;
H5Z__nbit_next_byte(j, buf_len);
if(dat_len == 0)
return;
buffer[*j] = (unsigned char)((val & ~((unsigned)(~0) << dat_len)) << (*buf_len - dat_len));
*buf_len -= dat_len;
}
}
static void
H5Z__nbit_compress_one_nooptype(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, unsigned size)
{
unsigned i;
size_t dat_len;
unsigned char val;
for(i = 0; i < size; i++) {
val = data[data_offset + i];
dat_len = sizeof(unsigned char) * 8;
buffer[*j] |= (unsigned char)((unsigned)(val >> (dat_len - *buf_len)) & ~((unsigned)(~0) << *buf_len));
dat_len -= *buf_len;
H5Z__nbit_next_byte(j, buf_len);
if(dat_len == 0)
continue;
buffer[*j] = (unsigned char)((val & ~((unsigned)(~0) << dat_len)) << (*buf_len - dat_len));
*buf_len -= dat_len;
}
}
static void
H5Z__nbit_compress_one_atomic(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const parms_atomic *p)
{
int k;
unsigned begin_i, end_i;
size_t datatype_len;
datatype_len = p->size * 8;
if(p->order == H5Z_NBIT_ORDER_LE) {
if((p->precision + p->offset) % 8 != 0)
begin_i = (p->precision + p->offset) / 8;
else
begin_i = (p->precision + p->offset) / 8 - 1;
end_i = p->offset / 8;
for(k = (int)begin_i; k >= (int)end_i; k--)
H5Z__nbit_compress_one_byte(data, data_offset, (unsigned)k, begin_i, end_i,
buffer, j, buf_len, p, datatype_len);
}
else {
HDassert(p->order == H5Z_NBIT_ORDER_BE);
begin_i = ((unsigned)datatype_len - p->precision - p->offset) / 8;
if(p->offset % 8 != 0)
end_i = ((unsigned)datatype_len - p->offset) / 8;
else
end_i = ((unsigned)datatype_len - p->offset) / 8 - 1;
for(k = (int)begin_i; k <= (int)end_i; k++)
H5Z__nbit_compress_one_byte(data, data_offset, (unsigned)k, begin_i, end_i,
buffer, j, buf_len, p, datatype_len);
}
}
static void
H5Z__nbit_compress_one_array(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const unsigned parms[],
unsigned *parms_index)
{
unsigned i, total_size, base_class, base_size, n, begin_index;
parms_atomic p;
total_size = parms[(*parms_index)++];
base_class = parms[(*parms_index)++];
switch(base_class) {
case H5Z_NBIT_ATOMIC:
p.size = parms[(*parms_index)++];
p.order = parms[(*parms_index)++];
p.precision = parms[(*parms_index)++];
p.offset = parms[(*parms_index)++];
n = total_size / p.size;
for(i = 0; i < n; i++)
H5Z__nbit_compress_one_atomic(data, data_offset + i * p.size,
buffer, j, buf_len, &p);
break;
case H5Z_NBIT_ARRAY:
base_size = parms[*parms_index];
n = total_size / base_size;
begin_index = *parms_index;
for(i = 0; i < n; i++) {
H5Z__nbit_compress_one_array(data, data_offset + i * base_size,
buffer, j, buf_len, parms, parms_index);
*parms_index = begin_index;
}
break;
case H5Z_NBIT_COMPOUND:
base_size = parms[*parms_index];
n = total_size / base_size;
begin_index = *parms_index;
for(i = 0; i < n; i++) {
H5Z__nbit_compress_one_compound(data, data_offset + i * base_size,
buffer, j, buf_len, parms, parms_index);
*parms_index = begin_index;
}
break;
case H5Z_NBIT_NOOPTYPE:
(*parms_index)++;
H5Z__nbit_compress_one_nooptype(data, data_offset, buffer, j, buf_len, total_size);
break;
default:
HDassert(0 && "This Should never be executed!");
}
}
static void
H5Z__nbit_compress_one_compound(unsigned char *data, size_t data_offset,
unsigned char *buffer, size_t *j, size_t *buf_len, const unsigned parms[],
unsigned *parms_index)
{
unsigned i, nmembers, member_offset, member_class, size;
parms_atomic p;
(*parms_index)++;
nmembers = parms[(*parms_index)++];
for(i = 0; i < nmembers; i++) {
member_offset = parms[(*parms_index)++];
member_class = parms[(*parms_index)++];
switch(member_class) {
case H5Z_NBIT_ATOMIC:
p.size = parms[(*parms_index)++];
p.order = parms[(*parms_index)++];
p.precision = parms[(*parms_index)++];
p.offset = parms[(*parms_index)++];
H5Z__nbit_compress_one_atomic(data, data_offset + member_offset,
buffer, j, buf_len, &p);
break;
case H5Z_NBIT_ARRAY:
H5Z__nbit_compress_one_array(data, data_offset + member_offset,
buffer, j, buf_len, parms, parms_index);
break;
case H5Z_NBIT_COMPOUND:
H5Z__nbit_compress_one_compound(data, data_offset+member_offset,
buffer, j, buf_len, parms, parms_index);
break;
case H5Z_NBIT_NOOPTYPE:
size = parms[(*parms_index)++];
H5Z__nbit_compress_one_nooptype(data, data_offset+member_offset,
buffer, j, buf_len, size);
break;
default:
HDassert(0 && "This Should never be executed!");
}
}
}
static void
H5Z__nbit_compress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer,
size_t *buffer_size, const unsigned parms[])
{
unsigned i;
size_t size;
size_t new_size = 0;
size_t buf_len;
parms_atomic p;
unsigned parms_index;
HDmemset(buffer, 0, *buffer_size);
buf_len = sizeof(unsigned char) * 8;
switch(parms[3]) {
case H5Z_NBIT_ATOMIC:
p.size = parms[4];
p.order = parms[5];
p.precision = parms[6];
p.offset = parms[7];
for(i = 0; i < d_nelmts; i++)
H5Z__nbit_compress_one_atomic(data, i * p.size, buffer, &new_size, &buf_len, &p);
break;
case H5Z_NBIT_ARRAY:
size = parms[4];
parms_index = 4;
for(i = 0; i < d_nelmts; i++) {
H5Z__nbit_compress_one_array(data, i * size, buffer, &new_size, &buf_len, parms, &parms_index);
parms_index = 4;
}
break;
case H5Z_NBIT_COMPOUND:
size = parms[4];
parms_index = 4;
for(i = 0; i < d_nelmts; i++) {
H5Z__nbit_compress_one_compound(data, i * size, buffer, &new_size, &buf_len, parms, &parms_index);
parms_index = 4;
}
break;
default:
HDassert(0 && "This Should never be executed!");
}
*buffer_size = new_size + 1;
}