在压缩和解压数据时,常常需要在小于一个字节的数量级上进行数据操作。因此,首先必须熟悉一些对数据位进行的操作。
/* bit.h */
#ifndef BIT_H
#define BIT_H
/*
功 能: 获取缓冲区bits中处于位置pos的位的状态.缓冲区最左边的位置为0.
返回值: 相应位置的状态:1或0.
*/
int bit_get(const unsigned char *bits, int pos);
/*
功 能: 设置缓冲区bits中处于位置pos的位的状态(根据state值来设置).缓冲区最左边的值为0.状态值必须为0或1.
返回值: 无.
*/
void bit_set(unsigned char *bits, int pos, int state);
/*
功 能: 按位计算两个缓冲区bits1与bits2的异或值, 其中每个缓冲区包含size个位,然后将结果返回bitsx中.
返回值: 无.
*/
void bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned char *bitsx, int size);
/*
功 能: 轮转缓冲区bits(含size位),将位值向左移count位.此操作完成后,处于最左端的count位移动到缓冲区最右端,而且其它位也相应地轮转.
返回值: 无.
*/
void bit_rot_left(unsigned char *bits, int size, int count);
#endif
/* bit.c */
#include <string.h>
#include "bit.h"
/* 获取pos位 */
int
bit_get(const unsigned char *bits, int pos)
{
unsigned char mask;
int i;
/* Set a mask for the bit to get. */
mask = 0x80;
for (i = 0; i < (pos % 8); i++)
{
mask = mask >> 1;
}
/* Get the bis. */
return (((mask & bits[(int)(pos / 8)]) == mask) ? 1 : 0);
}
/* 设置pos位为state */
void
bit_set(unsigned char *bits, int pos, int state)
{
unsigned char mask;
int i;
/* Set a mask for the bit to set. */
mask = 0x80;
for (i = 0; i < (pos % 8); i++)
{
mask = mask >> 1;
}
/* Set the bit. */
if (state)
{
bits[pos / 8] = bits[pos / 8] | mask;
}
else
{
bits[pos / 8] = bits[pos / 8] & mask;
}
}
/* 位异或 */
void
bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned char *bitsx, int size)
{
int i;
/* Compute the bitwise XOR (exclusive OR) of the two buffers. */
for (i = 0; i < size; i++)
{
if (bit_get(bits1, i) != bit_get(bits2, i))
{
bit_set(bitsx, i, 1);
}
else
{
bit_set(bitsx, i, 0);
}
}
}
/* bit_rot_left */
void
bit_rot_left(unsigned char *bits, int size, int count)
{
int fbit, lbit, i, j;
/* Rotate the buffer to the left the specified number of bits. */
if (size > 0)
{
for (j = 0; j < count; j++)
{
for (i = 0; i <= ((size - 1) / 8); i++)
{
/* Get the bit about to be shifted off the current byte. */
lbit = bit_get(&bits[i], 0);
if (i == 0)
{
/* Save the bit shifted off the first byte for later. */
fbit = lbit;
}
else
{
/* Set the rightmost bit of the previous byte to the leftmost bit about to be shifted off the current byte. */
bit_set(&bits[i - 1], 7, lbit);
}
/* Shift the current byte to the left. */
bits[i] = bits[i] << 1;
}
/* Set the rightmost bit of the buffer to the bit shifted off the first byte. */
bit_set(bits, size - 1, fbit);
}
}
}