首页
社区
课程
招聘
[转帖]位操作
发表于: 2015-8-7 19:06 1733

[转帖]位操作

2015-8-7 19:06
1733
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

struct bitrdwr_pos {

        char *p;
        int   pos;  // 0~7
};

struct bit_buf {

        char *buf;
        int   len;
       
        struct bitrdwr_pos write_pos;
        struct bitrdwr_pos read_pos;
};

#define sizeof_bits(type) (sizeof(type)*8)

#define bit_buf_rdable(bitbuf_addr, bits) \
        (((((bitbuf_addr)->buf+(bitbuf_addr)->len) \
        - ((bitbuf_addr)->read_pos.p+1))*sizeof_bits(char)) \
        + ((bitbuf_addr)->read_pos.pos+1) >= (bits))
#define bit_buf_wrable(bitbuf_addr, bits) \
        (((((bitbuf_addr)->buf+(bitbuf_addr)->len) \
        - ((bitbuf_addr)->write_pos.p+1))*sizeof_bits(char)) \
        + ((bitbuf_addr)->write_pos.pos+1) >= (bits))

#define set_bitrdwr_position(pos_addr, _p, _pos) do { \
        (pos_addr)->p = (_p); \
        (pos_addr)->pos = (_pos); \
} while(0)

#define BIT_BUF_SIZE  1024

enum BIT_RDWR_MOD {

        MOD_NORMAL,
        MOD_STOP,
};

enum BIT_RDWR_RET {

        RET_NORMAL,
        RET_FINISH,
        RET_ERR,
};

/*
*       7      0
* char: xxxxxxxx
*        ↑  ↑ [from_bit,to_bit]
*        +---+
*          ↖num
* example:
* 5 -> [bit1, bit3]:  xxxx[101]x
* 10-> [bit1, bit3]:  xxxx[010]x, overflow
*/
static int bitwr_in_char(char *ch, int from_bit, int to_bit, unsigned char num)
{
        if (from_bit < 0 || from_bit >= sizeof_bits(char)
                        || to_bit < 0 || to_bit >= sizeof_bits(char))
                return -1;
       
        if (from_bit > to_bit) {
                from_bit ^= to_bit;
                to_bit ^= from_bit;
                from_bit ^= to_bit;
        }

        if ((1<<(to_bit-from_bit+1)) - 1 < num)
                printf("%s(), %d: overflow\n", __FUNCTION__, __LINE__);

        *ch &= ((((1<<sizeof_bits(char))-1)<<(to_bit+1)) | ((1<<from_bit)-1));
        *ch |= (num<<from_bit);

        return 0;
}

/*
*       7      0
* char: xXXXXXxx
*        ↑  ↑ [from_bit,to_bit]
*        +---+
*          ↘num
*/
static int bitrd_in_char(char *ch, int from_bit, int to_bit)
{
        if (from_bit < 0 || from_bit >= sizeof_bits(char)
                        || to_bit < 0 || to_bit >= sizeof_bits(char))
                return -1;
       
        if (from_bit > to_bit) {
                from_bit ^= to_bit;
                to_bit ^= from_bit;
                from_bit ^= to_bit;
        }
       
        //       ←1bit    →3bits
        // char: XXXXXxx0  000XXXXX
        //       ↑  ↑       ↑  ↑
        return (int)((*(unsigned char *)ch << (sizeof_bits(char)-(to_bit+1)))
                >> (sizeof_bits(char)-(to_bit-from_bit+1)));
}

/*
* 位读写缓冲区销毁
*/
static void bit_buf_destroy(struct bit_buf *bitbuf)
{
        if (bitbuf != NULL)
        {
                if (bitbuf->buf != NULL)
                        free(bitbuf->buf);
                free(bitbuf);
        }
}

/*
* 位读写缓冲区创建
*/
static struct bit_buf *bit_buf_create(int size)
{
        struct bit_buf *bitbuf = NULL;
       
        bitbuf = malloc(sizeof(struct bit_buf));
        if (bitbuf == NULL) {
                printf("%s(), %d: malloc failed\n", __FUNCTION__, __LINE__);
                goto err;
        }

        bitbuf->len = size;
        bitbuf->buf = malloc(size);
       
        if (bitbuf->buf == NULL) {
                printf("%s(), %d: malloc failed\n", __FUNCTION__, __LINE__);
                goto err;
        }
       
        set_bitrdwr_position(&bitbuf->write_pos, bitbuf->buf, sizeof_bits(char)-1);
        set_bitrdwr_position(&bitbuf->read_pos, bitbuf->buf, sizeof_bits(char)-1);

        return bitbuf;
err:
        bit_buf_destroy(bitbuf);
        return NULL;
}

/*
* buf->read_pos.p:pos开始处,读取bits位对应的值
* bits>sizeof_bits(int),取低sizeof(int)位
*/
static int bit_buf_read(struct bit_buf *bitbuf, int bits)
{
        int num = 0;

        while (bits > 0)
        {
                int _bits;
               
                if (bits > sizeof_bits(int))
                {
                        // 忽略int范围以外的高位
                        _bits = (bitbuf->read_pos.pos+1) < bits-sizeof_bits(int) ?
                                (bitbuf->read_pos.pos+1) : bits-sizeof_bits(int);
                }
                else
                {
                        // int范围内的值
                        int _num;
                       
                        _bits = (bitbuf->read_pos.pos+1) < bits ? (bitbuf->read_pos.pos+1) : bits;
                        _num = bitrd_in_char(bitbuf->read_pos.p, bitbuf->read_pos.pos, (bitbuf->read_pos.pos+1)-_bits);
                        num |= ((_num <<(bits-_bits)) & ~(((unsigned int)((1LL<<sizeof_bits(int))-1) << bits) | ((1<<(bits-_bits))-1)));
                }

                if (_bits < bitbuf->read_pos.pos+1)
                        bitbuf->read_pos.pos -= _bits;
                else {
                        bitbuf->read_pos.p ++;
                        bitbuf->read_pos.pos = sizeof_bits(char)-1;
                }
               
                bits -= _bits;
        }
       
        return num;
}

/*
* buf->write_pos.p:pos开始处的bits位,填充为num值
* bits>sizeof(int),高位填充0.
*/
static int bit_buf_write(struct bit_buf *bitbuf, int num, int bits)
{
        while (bits > 0)
        {
                // 根据buf->write_pos->pos,和剩余bits,确定当前要写的区间
                // (high, low] →buf->write_pos.pos
                int _bits = (bitbuf->write_pos.pos+1) < bits ? (bitbuf->write_pos.pos+1) : bits;
                int  low = bits-_bits;
                unsigned char fill_num = 0;
               
                if (low < sizeof_bits(int)) {
                        int high = bits > sizeof_bits(int) ? sizeof_bits(int) : bits;
                        fill_num = (num & ~((unsigned int)((1LL<<sizeof_bits(int))-1)<<high)) >> low;
                }
               
                if (bitbuf->write_pos.p >= bitbuf->buf+bitbuf->len) {
                        printf("%s(), %d: no enough buf\n", __FUNCTION__, __LINE__);
                        return -1;
                }
               
                bitwr_in_char(bitbuf->write_pos.p, bitbuf->write_pos.pos, (bitbuf->write_pos.pos+1)-_bits, fill_num);

                // never: _bits > bitbuf->write_pos.pos+1
                if (_bits < bitbuf->write_pos.pos+1)
                        bitbuf->write_pos.pos -= _bits;
                else {
                        bitbuf->write_pos.p ++;
                        bitbuf->write_pos.pos = sizeof_bits(char)-1;
                }
               
                bits -= _bits;
        }

        return 0;
}

/*
* 读文件内容,以指定位数为一个值
*/
static int bits_read(char *file, enum BIT_RDWR_MOD mod, int bits, int *num)
{
        static int fd = 0;
        static struct bit_buf *bitbuf = NULL;

        #define close_buf_fd() do { \
                if (bitbuf != NULL) { \
                        bit_buf_destroy(bitbuf); \
                        bitbuf = NULL; \
                } \
                if (fd > 0) { \
                        close(fd); \
                        fd = 0; \
                } \
        } while(0)

        if (mod == MOD_STOP) {
                close_buf_fd();
                return RET_NORMAL;
        }

        if (fd <= 0)
        {
                if ((fd = open(file, O_RDONLY)) < 0) {
                        printf("%s(), %d: open file \"%s\" failed\n", __FUNCTION__, __LINE__, file);
                        goto err;
                }
               
                if ((bitbuf = bit_buf_create(BIT_BUF_SIZE)) == NULL)
                        goto err;

                set_bitrdwr_position(&bitbuf->read_pos, bitbuf->buf+bitbuf->len, sizeof_bits(char)-1);
        }
       
        if (!bit_buf_rdable(bitbuf, bits))
        {
                int i = 0, len;
               
                while (bitbuf->read_pos.p+i < bitbuf->buf+bitbuf->len)
                {
                        bitbuf->buf[i] = bitbuf->read_pos.p[i];
                        i ++;
                }

                len = read(fd, bitbuf->buf+i, bitbuf->len-i);
                if (len < 0)
                        goto err;

                bitbuf->read_pos.p = bitbuf->buf;
                bitbuf->len = len+i;
               
#ifdef LZW_DEBUG
                {
                        int j = 0;
                        for (; j < bitbuf->len; j ++)
                                printf("%02x ", (unsigned char)bitbuf->buf[j]);
                        printf("\n");
                        printf("pos: %d\n", bitbuf->read_pos.pos);
                }
#endif
                if (!bit_buf_rdable(bitbuf, bits)) {
                        close_buf_fd();
                        return RET_FINISH;
                }
        }

#ifdef LZW_DEBUG
        printf("%s(), %d: %p, %d -----\n", __FUNCTION__, __LINE__, bitbuf->read_pos.p, bitbuf->read_pos.pos);
#endif
        *num = bit_buf_read(bitbuf, bits);

        return RET_NORMAL;
err:
        close_buf_fd();
        return RET_ERR;
}

/*
* 将num值以指定位数写进文件
*/
static int bits_write(char *file, enum BIT_RDWR_MOD mod, int bits, int num)
{
        static int fd = 0;
        static struct bit_buf *bitbuf = NULL;

        #define close_buf_fd() do { \
                if (bitbuf != NULL) { \
                        bit_buf_destroy(bitbuf); \
                        bitbuf = NULL; \
                } \
                if (fd > 0) { \
                        close(fd); \
                        fd = 0; \
                } \
        } while(0)

        if (mod == MOD_STOP)
        {
                if (fd >0 && (bitbuf->write_pos.p > bitbuf->buf
                                || bitbuf->write_pos.pos != sizeof_bits(char)-1)) {
                        write(fd, bitbuf->buf, (bitbuf->write_pos.p+1)-bitbuf->buf);
                       
#ifdef LZW_DEBUG
                        {
                                int i = 0;
                                for (; i < (bitbuf->write_pos.p+1)-bitbuf->buf; i ++)
                                        printf("%02x ", (unsigned char)bitbuf->buf[i]);
                                printf("\n");
                                printf("%s(), %d: flush !!!!!\n", __FUNCTION__, __LINE__);
                                printf("pos: %d\n", bitbuf->write_pos.pos);
                        }
#endif
                }
               
                close_buf_fd();
                return RET_NORMAL;
        }

        if (fd <= 0)
        {
                if ((fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0644)) < 0) {
                        printf("%s(), %d: open file \"%s\" failed\n", __FUNCTION__, __LINE__, file);
                        goto err;
                }
               
                if ((bitbuf = bit_buf_create(BIT_BUF_SIZE)) == NULL)
                        goto err;
        }
       
        if (!bit_buf_wrable(bitbuf, bits))
        {
                int len = bitbuf->write_pos.p - bitbuf->buf;

                write(fd, bitbuf->buf, len);
#ifdef LZW_DEBUG
                {
                        int i = 0;
                        for (; i < len; i ++)
                                printf("%02x ", (unsigned char)bitbuf->buf[i]);
                        printf("\n");
                        printf("%s(), %d: flush, %d, len: %d, *p: %x !!!!!\n",
                                __FUNCTION__, __LINE__, num, len, *(unsigned char*)bitbuf->write_pos.p);
                }
#endif

                bitbuf->buf[0] = *bitbuf->write_pos.p;
                bitbuf->write_pos.p = bitbuf->buf;
        }
       
        bit_buf_write(bitbuf, num, bits);

        return RET_NORMAL;
err:
        close_buf_fd();
        return RET_ERR;
}

int main()
{
#define BITS  11
        int i, ret;

        for (i = 0; i < 1024; i ++)
                bits_write("./test.txt", MOD_NORMAL, BITS, i);
        bits_write("./test.txt", MOD_STOP, 0, 0);

        while(1)
        {
                ret = bits_read("./test.txt", MOD_NORMAL, BITS, &i);
               
                switch (ret)
                {
                case RET_NORMAL:
                        printf("%d +++++\n", i);
                        break;
                case RET_FINISH:
                        goto finish;
                case RET_ERR:
                default:
                        goto err;
                }
        }

finish:
        return 0;
err:
        return -1;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//