/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define H5Z_PACKAGE /*suppress error about including H5Zpkg */ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5MMprivate.h" /* Memory management */ #include "H5Ppublic.h" /* Property lists */ #include "H5Tpublic.h" /* Datatype functions */ #include "H5Zpkg.h" /* Data filters */ #ifdef H5_HAVE_FILTER_SHUFFLE /* Local function prototypes */ static herr_t H5Z_set_local_shuffle(hid_t dcpl_id, hid_t type_id, hid_t space_id); static size_t H5Z_filter_shuffle(unsigned flags, size_t cd_nelmts, const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf); /* This message derives from H5Z */ const H5Z_class_t H5Z_SHUFFLE[1] = {{ H5Z_FILTER_SHUFFLE, /* Filter id number */ "shuffle", /* Filter name for debugging */ NULL, /* The "can apply" callback */ H5Z_set_local_shuffle, /* The "set local" callback */ H5Z_filter_shuffle, /* The actual filter function */ }}; /* Local macros */ #define H5Z_SHUFFLE_USER_NPARMS 0 /* Number of parameters that users can set */ #define H5Z_SHUFFLE_TOTAL_NPARMS 1 /* Total number of parameters for filter */ #define H5Z_SHUFFLE_PARM_SIZE 0 /* "Local" parameter for shuffling size */ /*------------------------------------------------------------------------- * Function: H5Z_set_local_shuffle * * Purpose: Set the "local" dataset parameter for data shuffling to be * the size of the datatype. * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Monday, April 7, 2003 * * Modifications: * *------------------------------------------------------------------------- */ /* ARGSUSED */ static herr_t H5Z_set_local_shuffle(hid_t dcpl_id, hid_t type_id, hid_t UNUSED space_id) { unsigned flags; /* Filter flags */ size_t cd_nelmts=H5Z_SHUFFLE_USER_NPARMS; /* Number of filter parameters */ unsigned cd_values[H5Z_SHUFFLE_TOTAL_NPARMS]; /* Filter parameters */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5Z_set_local_shuffle, FAIL) /* Get the filter's current parameters */ if(H5Pget_filter_by_id(dcpl_id,H5Z_FILTER_SHUFFLE,&flags,&cd_nelmts, cd_values,0,NULL)<0) HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't get shuffle parameters") /* Set "local" parameter for this dataset */ if((cd_values[H5Z_SHUFFLE_PARM_SIZE]=(unsigned)H5Tget_size(type_id))==0) HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype size") /* Modify the filter's parameters for this dataset */ if(H5Pmodify_filter(dcpl_id, H5Z_FILTER_SHUFFLE, flags, H5Z_SHUFFLE_TOTAL_NPARMS, cd_values)<0) HGOTO_ERROR(H5E_PLINE, H5E_CANTSET, FAIL, "can't set local shuffle parameters") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5Z_set_local_shuffle() */ /*------------------------------------------------------------------------- * Function: H5Z_filter_shuffle * * Purpose: Implement an I/O filter which "de-interlaces" a block of data * by putting all the bytes in a byte-position for each element * together in the block. For example, for 4-byte elements stored * as: 012301230123, shuffling will store them as: 000111222333 * Usually, the bytes in each byte position are more related to * each other and putting them together will increase compression. * * Return: Success: Size of buffer filtered * Failure: 0 * * Programmer: Kent Yang * Wednesday, November 13, 2002 * * Modifications: * Quincey Koziol, November 13, 2002 * Cleaned up code. * *------------------------------------------------------------------------- */ static size_t H5Z_filter_shuffle(unsigned flags, size_t cd_nelmts, const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf) { void *dest = NULL; /* Buffer to deposit [un]shuffled bytes into */ unsigned char *_src=NULL; /* Alias for source buffer */ unsigned char *_dest=NULL; /* Alias for destination buffer */ unsigned bytesoftype; /* Number of bytes per element */ size_t numofelements; /* Number of elements in buffer */ size_t i; /* Local index variables */ #ifdef NO_DUFFS_DEVICE size_t j; /* Local index variable */ #endif /* NO_DUFFS_DEVICE */ size_t leftover; /* Extra bytes at end of buffer */ size_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5Z_filter_shuffle, 0) /* Check arguments */ if (cd_nelmts!=H5Z_SHUFFLE_TOTAL_NPARMS || cd_values[H5Z_SHUFFLE_PARM_SIZE]==0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid shuffle parameters") /* Get the number of bytes per element from the parameter block */ bytesoftype=cd_values[H5Z_SHUFFLE_PARM_SIZE]; /* Compute the number of elements in buffer */ numofelements=nbytes/bytesoftype; /* Don't do anything for 1-byte elements, or "fractional" elements */ if(bytesoftype > 1 && numofelements > 1) { /* Compute the leftover bytes if there are any */ leftover = nbytes%bytesoftype; /* Allocate the destination buffer */ if (NULL==(dest = H5MM_malloc(nbytes))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed for shuffle buffer") if(flags & H5Z_FLAG_REVERSE) { /* Get the pointer to the source buffer */ _src =(unsigned char *)(*buf); /* Input; unshuffle */ for(i=0; i 0) { DUFF_GUTS; j--; } /* end for */ #else /* NO_DUFFS_DEVICE */ { size_t duffs_index; /* Counting index for Duff's device */ duffs_index = (numofelements + 7) / 8; switch (numofelements % 8) { case 0: do { DUFF_GUTS case 7: DUFF_GUTS case 6: DUFF_GUTS case 5: DUFF_GUTS case 4: DUFF_GUTS case 3: DUFF_GUTS case 2: DUFF_GUTS case 1: DUFF_GUTS } while (--duffs_index > 0); } /* end switch */ } #endif /* NO_DUFFS_DEVICE */ #undef DUFF_GUTS } /* end for */ /* Add leftover to the end of data */ if(leftover>0) { /* Adjust back to end of shuffled bytes */ _dest -= (bytesoftype - 1); /*lint !e794 _dest is initialized */ HDmemcpy((void*)_dest, (void*)_src, leftover); } } /* end if */ else { /* Get the pointer to the destination buffer */ _dest =(unsigned char *)dest; /* Output; shuffle */ for(i=0; i 0) { DUFF_GUTS; j--; } /* end for */ #else /* NO_DUFFS_DEVICE */ { size_t duffs_index; /* Counting index for Duff's device */ duffs_index = (numofelements + 7) / 8; switch (numofelements % 8) { case 0: do { DUFF_GUTS case 7: DUFF_GUTS case 6: DUFF_GUTS case 5: DUFF_GUTS case 4: DUFF_GUTS case 3: DUFF_GUTS case 2: DUFF_GUTS case 1: DUFF_GUTS } while (--duffs_index > 0); } /* end switch */ } #endif /* NO_DUFFS_DEVICE */ #undef DUFF_GUTS } /* end for */ /* Add leftover to the end of data */ if(leftover>0) { /* Adjust back to end of shuffled bytes */ _src -= (bytesoftype - 1); /*lint !e794 _src is initialized */ HDmemcpy((void*)_dest, (void*)_src, leftover); } } /* end else */ /* Free the input buffer */ H5MM_xfree(*buf); /* Set the buffer information to return */ *buf = dest; *buf_size=nbytes; } /* end else */ /* Set the return value */ ret_value = nbytes; done: FUNC_LEAVE_NOAPI(ret_value) } #endif /*H5_HAVE_FILTER_SHUFFLE */