summaryrefslogtreecommitdiffstats
path: root/src/H5Tbit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Tbit.c')
-rw-r--r--src/H5Tbit.c192
1 files changed, 170 insertions, 22 deletions
diff --git a/src/H5Tbit.c b/src/H5Tbit.c
index 0524dcc..b9a830d 100644
--- a/src/H5Tbit.c
+++ b/src/H5Tbit.c
@@ -32,25 +32,22 @@ void
H5T_bit_copy (uint8 *dst, size_t dst_offset, const uint8 *src,
size_t src_offset, size_t size)
{
- uintn shift;
+ intn shift;
uintn mask_lo, mask_hi;
intn s_idx, d_idx;
-
+
/*
- * Calculate shifts and masks. See diagrams below. MASK_LO in this
- * example is 0x1f (the low five bits) and MASK_HI is 0xe0 (the high three
- * bits). SHIFT is three since the source must be shifted right three bits
- * to line up with the destination.
+ * Normalize the offset to be a byte number and a bit offset within that
+ * byte.
*/
- shift = (dst_offset%8)-(src_offset%8);
- mask_lo = (1<<(8-shift))-1;
- mask_hi = ((1<<shift)-1) << (8-shift);
s_idx = src_offset / 8;
d_idx = dst_offset / 8;
+ src_offset %= 8;
+ dst_offset %= 8;
/*
* Get things rolling. This means copying bits until we're aligned on a
- * source byte. This the following example, four bits are copied to the
+ * source byte. This the following example, five bits are copied to the
* destination.
*
* src[s_idx]
@@ -64,11 +61,26 @@ H5T_bit_copy (uint8 *dst, size_t dst_offset, const uint8 *src,
* ...+---------------+---------------+
* dst[d_idx+1] dst[d_idx]
*/
- if (src_offset%8 && size>0) {
+ while (src_offset && size>0) {
+ unsigned nbits = MIN3 (size, 8-dst_offset, 8-src_offset);
+ unsigned mask = (1<<nbits) - 1;
+
+ dst[d_idx] &= ~(mask<<dst_offset);
+ dst[d_idx] |= ((src[s_idx]>>src_offset)&mask) << dst_offset;
+
+ src_offset += nbits;
+ if (src_offset>=8) {
+ s_idx++;
+ src_offset %= 8;
+ }
+ dst_offset += nbits;
+ if (dst_offset>=8) {
+ d_idx++;
+ dst_offset %= 8;
+ }
+ size -= nbits;
}
-
-
/*
* The middle bits. We are aligned on a source byte which needs to be
* copied to two (or one in the degenerate case) destination bytes.
@@ -84,24 +96,47 @@ H5T_bit_copy (uint8 *dst, size_t dst_offset, const uint8 *src,
* +---------------+---------------+
* dst[d_idx+1] dst[d_idx]
*
+ *
+ * Calculate shifts and masks. See diagrams below. MASK_LO in this
+ * example is 0x1f (the low five bits) and MASK_HI is 0xe0 (the high three
+ * bits). SHIFT is three since the source must be shifted right three bits
+ * to line up with the destination.
*/
+ shift = dst_offset;
+ mask_lo = (1<<(8-shift))-1;
+ mask_hi = ~mask_lo;
+
for (/*void*/; size>8; size-=8, d_idx++, s_idx++) {
if (shift) {
- dst[d_idx+0] &= mask_lo;
- dst[d_idx+0] |= (src[s_idx] << shift) & mask_hi;
- dst[d_idx+1] &= mask_hi;
- dst[d_idx+1] |= (src[s_idx] >> (8-shift)) & mask_lo;
+ dst[d_idx+0] &= ~(mask_lo<<shift);
+ dst[d_idx+0] |= (src[s_idx] & mask_lo) << shift;
+ dst[d_idx+1] &= ~(mask_hi>>(8-shift));
+ dst[d_idx+1] |= (src[s_idx] & mask_hi) >> (8-shift);
} else {
dst[d_idx] = src[s_idx];
}
}
-
-
-
/* Finish up */
-
-
+ while (size>0) {
+ unsigned nbits = MIN3 (size, 8-dst_offset, 8-src_offset);
+ unsigned mask = (1<<nbits) - 1;
+
+ dst[d_idx] &= ~(mask<<dst_offset);
+ dst[d_idx] |= ((src[s_idx]>>src_offset)&mask) << dst_offset;
+
+ src_offset += nbits;
+ if (src_offset>=8) {
+ s_idx++;
+ src_offset %= 8;
+ }
+ dst_offset += nbits;
+ if (dst_offset>=8) {
+ d_idx++;
+ dst_offset %= 8;
+ }
+ size -= nbits;
+ }
}
@@ -123,6 +158,38 @@ H5T_bit_copy (uint8 *dst, size_t dst_offset, const uint8 *src,
void
H5T_bit_set (uint8 *buf, size_t offset, size_t size, hbool_t value)
{
+ intn idx;
+
+ /* Normalize */
+ idx = offset / 8;
+ offset %= 8;
+
+ /* The first partial byte */
+ if (size && offset%8) {
+ size_t nbits = MIN (size, 8-offset);
+ unsigned mask = (1<<nbits)-1;
+ if (value) {
+ buf[idx++] |= mask << offset;
+ } else {
+ buf[idx++] &= ~(mask << offset);
+ }
+ size -= nbits;
+ }
+
+ /* The middle bytes */
+ while (size>=8) {
+ buf[idx++] = value ? 0xff : 0x00;
+ size -= 8;
+ }
+
+ /* The last partial byte */
+ if (size) {
+ if (value) {
+ buf[idx] |= (1<<size)-1;
+ } else {
+ buf[idx] &= ~((1<<size)-1);
+ }
+ }
}
@@ -150,5 +217,86 @@ ssize_t
H5T_bit_find (uint8 *buf, size_t offset, size_t size, H5T_sdir_t direction,
hbool_t value)
{
+ size_t base=offset;
+ ssize_t idx, i;
+
+ /* Some functions call this with value=TRUE */
+ assert (TRUE==1);
+
+
+ switch (direction) {
+ case H5T_BIT_LSB:
+ /* Calculate index */
+ idx = offset / 8;
+ offset %= 8;
+
+ /* Beginning */
+ if (offset) {
+ for (i=offset; i<8 && size>0; i++, size--) {
+ if (value==((buf[idx]>>i) & 0x01)) {
+ return 8*idx+i - base;
+ }
+ }
+ offset = 0;
+ idx++;
+ }
+ /* Middle */
+ while (size>=8) {
+ if ((value?0x00:0xff)!=buf[idx]) {
+ for (i=0; i<8; i++) {
+ if (value==((buf[idx]>>i) & 0x01)) {
+ return 8*idx+i - base;
+ }
+ }
+ }
+ size -= 8;
+ idx++;
+ }
+ /* End */
+ for (i=0; i<(ssize_t)size; i++) {
+ if (value==((buf[idx]>>i) & 0x01)) {
+ return 8*idx+i - base;
+ }
+ }
+ break;
+
+ case H5T_BIT_MSB:
+ /* Calculate index */
+ idx = (offset+size-1) / 8;
+ offset %= 8;
+
+ /* Beginning */
+ if (size>8-offset && (offset+size)%8) {
+ for (i=(offset+size)%8-1; i>=0; --i, --size) {
+ if (value==((buf[idx]>>i) & 0x01)) {
+ return 8*idx+i - base;
+ }
+ }
+ --idx;
+ }
+ /* Middle */
+ while (size>=8) {
+ if ((value?0x00:0xff)!=buf[idx]) {
+ for (i=7; i>=0; --i) {
+ if (value==((buf[idx]>>i) & 0x01)) {
+ return 8*idx+i - base;
+ }
+ }
+ }
+ size -= 8;
+ --idx;
+ }
+ /* End */
+ if (size>0) {
+ for (i=offset+size-1; i>=(ssize_t)offset; --i) {
+ if (value==((buf[idx]>>i) & 0x01)) {
+ return 8*idx+i - base;
+ }
+ }
+ }
+ break;
+ }
+
+
return -1;
}