/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Programmer: Raymond Lu<slu@ncsa.uiuc.edu>
* Jan 3, 2003
*/
#define H5Z_PACKAGE /*suppress error about including H5Zpkg */
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* File access */
#include "H5MMprivate.h" /* Memory management */
#include "H5Zpkg.h" /* Data filters */
#ifdef H5_HAVE_FILTER_FLETCHER32
/* Local function prototypes */
static size_t H5Z_filter_fletcher32 (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_FLETCHER32[1] = {{
H5Z_FILTER_FLETCHER32, /* Filter id number */
"fletcher32", /* Filter name for debugging */
NULL, /* The "can apply" callback */
NULL, /* The "set local" callback */
H5Z_filter_fletcher32, /* The actual filter function */
}};
#define FLETCHER_LEN 4
/*-------------------------------------------------------------------------
* Function: H5Z_filter_fletcher32_compute
*
* Purpose: Implement an Fletcher32 Checksum using 1's complement.
*
* Return: Success: Fletcher32 value
*
* Failure: Can't fail
*
* Programmer: Raymond Lu
* Jan 3, 2003
*
* Modifications: Pedro Vicente, March 10, 2004
* defined *SRC as unsigned char for all cases
*
*-------------------------------------------------------------------------
*/
static uint32_t
H5Z_filter_fletcher32_compute(void *_src, size_t len)
{
unsigned char *src=(unsigned char *)_src;
/*To handle unusual platforms like Cray*/
unsigned short tmp_src;
size_t count = len; /* Number of bytes left to checksum */
uint32_t s1 = 0, s2 = 0; /* Temporary partial checksums */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5Z_filter_fletcher32_compute)
/* Compute checksum */
while(count > 1) {
/*To handle unusual platforms like Cray*/
tmp_src = (((unsigned short)src[0])<<8) | ((unsigned short)src[1]);
src +=2;
s1 += tmp_src;
if(s1 & 0xFFFF0000) { /*Wrap around carry if occurred*/
s1 &= 0xFFFF;
s1++;
}
s2 += s1;
if(s2 & 0xFFFF0000) { /*Wrap around carry if occurred*/
s2 &= 0xFFFF;
s2++;
}
count -= 2;
}
if(count==1) {
s1 += *(unsigned char*)src;
if(s1 & 0xFFFF0000) { /*Wrap around carry if occurred*/
s1 &= 0xFFFF;
s1++;
}
s2 += s1;
if(s2 & 0xFFFF0000) { /*Wrap around carry if occurred*/
s2 &= 0xFFFF;
s2++;
}
}
FUNC_LEAVE_NOAPI((s2 << 16) + s1)
}
/*-------------------------------------------------------------------------
* Function: H5Z_filter_fletcher32
*
* Purpose: Implement an I/O filter of Fletcher32 Checksum
*
* Return: Success: Size of buffer filtered
* Failure: 0
*
* Programmer: Raymond Lu
* Jan 3, 2003
*
* Modifications:
* Raymond Lu
* July 8, 2005
* There was a bug in the calculating code of the Fletcher32
* checksum in the library before v1.6.3. The checksum
* value wasn't consistent between big-endian and little-endian
* systems. This bug was fixed in Release 1.6.3. However,
* after fixing the bug, the checksum value is no longer the
* same as before on little-endian system. We'll check both
* the correct checksum and the wrong checksum to be consistent
* with Release 1.6.2 and before.
*
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
static size_t
H5Z_filter_fletcher32 (unsigned flags, size_t UNUSED cd_nelmts, const unsigned UNUSED cd_values[],
size_t nbytes, size_t *buf_size, void **buf)
{
void *outbuf = NULL; /* Pointer to new buffer */
unsigned char *src = (unsigned char*)(*buf);
uint32_t fletcher; /* Checksum value */
uint32_t reversed_fletcher; /* Possible wrong checksum value */
uint8_t c[4];
uint8_t tmp;
size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5Z_filter_fletcher32, 0)
assert(sizeof(uint32_t)>=4);
if (flags & H5Z_FLAG_REVERSE) { /* Read */
/* Do checksum if it's enabled for read; otherwise skip it
* to save performance. */
if (!(flags & H5Z_FLAG_SKIP_EDC)) {
unsigned char *tmp_src; /* Pointer to checksum in buffer */
size_t src_nbytes = nbytes; /* Original number of bytes */
uint32_t stored_fletcher; /* Stored checksum value */
/* Get the stored checksum */
src_nbytes -= FLETCHER_LEN;
tmp_src=src+src_nbytes;
UINT32DECODE(tmp_src, stored_fletcher);
/* Compute checksum (can't fail) */
fletcher = H5Z_filter_fletcher32_compute(src,src_nbytes);
/* The reversed checksum. There was a bug in the calculating code of
* the Fletcher32 checksum in the library before v1.6.3. The checksum
* value wasn't consistent between big-endian and little-endian systems.
* This bug was fixed in Release 1.6.3. However, after fixing the bug,
* the checksum value is no longer the same as before on little-endian
* system. We'll check both the correct checksum and the wrong
* checksum to be consistent with Release 1.6.2 and before.
*/
HDmemcpy(c, &fletcher, 4);
tmp = c[1];
c[1] = c[0];
c[0] = tmp;
tmp = c[3];
c[3] = c[2];
c[2] = tmp;
HDmemcpy(&reversed_fletcher, c, 4);
/* Verify computed checksum matches stored checksum */
if(stored_fletcher != fletcher && stored_fletcher != reversed_fletcher)
HGOTO_ERROR(H5E_STORAGE, H5E_READERROR, 0, "data error detected by Fletcher32 checksum")
}
/* Set return values */
/* (Re-use the input buffer, just note that the size is smaller by the size of the checksum) */
ret_value = nbytes-FLETCHER_LEN;
} else { /* Write */
unsigned char *dst; /* Temporary pointer to destination buffer */
/* Compute checksum (can't fail) */
fletcher = H5Z_filter_fletcher32_compute(src,nbytes);
if (NULL==(dst=outbuf=H5MM_malloc(nbytes+FLETCHER_LEN)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "unable to allocate Fletcher32 checksum destination buffer")
/* Copy raw data */
HDmemcpy((void*)dst, (void*)(*buf), nbytes);
/* Append checksum to raw data for storage */
dst += nbytes;
UINT32ENCODE(dst, fletcher);
/* Free input buffer */
H5MM_xfree(*buf);
/* Set return values */
*buf_size = nbytes + FLETCHER_LEN;
*buf = outbuf;
outbuf = NULL;
ret_value = *buf_size;
}
done:
if(outbuf)
H5MM_xfree(outbuf);
FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5_HAVE_FILTER_FLETCHER32 */
syntax highlighted by Code2HTML, v. 0.9.1