LZ77算法 的分析与实现(4)

/*写入头部信息*/
    hsize = sizeof(int);
    if((comp = (unsigned char *)malloc(hsize)) == NULL)
        return -1;
    memcpy(comp,&size,sizeof(int));

/*初始化滑动窗口和前向缓冲区(用0填充)*/
    memset(window, 0 , LZ77_WINDOW_SIZE);
    memset(buffer, 0 , LZ77_BUFFER_SIZE);

/*加载前向缓冲区*/
    ipos = 0;

for(i=0; i<LZ77_BUFFER_SIZE && ipos < size; i++)
    {
        buffer[i] = original[ipos];
        ipos++;
    }

/*压缩数据*/
    opos = hsize * 8;
    remaining = size;

while(remaining > 0)
    {
        if((length = compare_win(window,buffer,&offset,&next)) != 0)
        {
            /*编码短语标记*/
            token = 0x00000001 << (LZ77_PHRASE_BITS - 1);

/*设置在滑动窗口找到匹配的偏移量*/
            token = token | (offset << (LZ77_PHRASE_BITS - LZ77_TYPE_BITS - LZ77_WINOFF_BITS));

/*设置匹配串的长度*/
            token = token | (length << (LZ77_PHRASE_BITS - LZ77_TYPE_BITS - LZ77_WINOFF_BITS - LZ77_BUFLEN_BITS));

/*设置前向缓冲区中匹配串后面紧邻的字符*/
            token = token | next;

/*设置标记的位数*/
            tbits = LZ77_PHRASE_BITS;
        }
        else
        {
            /*编码一个字符标记*/
            token = 0x00000000;

/*设置未匹配的字符*/
            token = token | next;

/*设置标记的位数*/
            tbits = LZ77_SYMBOL_BITS;
        }

/*确定标记是大端格式*/
        token = htonl(token);

/*将标记写入压缩缓冲区*/
        for(i=0; i<tbits; i++)
        {
            if(opos % 8 == 0)
            {
                /*为压缩缓冲区分配临时空间*/
                if((temp = (unsigned char *)realloc(comp,(opos / 8) + 1)) == NULL)
                {
                    free(comp);
                    return -1;
                }
                comp = temp;
            }

tpos = (sizeof(unsigned long ) * 8) - tbits + i;
            bit_set(comp,opos,bit_get((unsigned char *)&token,tpos));
            opos++;
        }
        /*调整短语长度*/
        length++;

/*从前向缓冲区中拷贝数据到滑动窗口中*/
        memmove(&window[0],&window[length],LZ77_WINDOW_SIZE - length);
        memmove(&window[LZ77_WINDOW_SIZE - length],&buffer[0],length);
        memmove(&buffer[0],&buffer[length],LZ77_BUFFER_SIZE - length);
        /*向前向缓冲区中读取更多数据*/
        for(i = LZ77_BUFFER_SIZE - length; i<LZ77_BUFFER_SIZE && ipos <size; i++)
        {
            buffer[i] = original[ipos];
            ipos++;
        }

/*调整剩余未匹配的长度*/
        remaining = remaining - length;
    }
    /*指向压缩数据缓冲区*/
    *compressed = comp;
    /*返回压缩数据中的字节数*/
    return ((opos - 1) / 8) + 1;
}

/*lz77_uncompress  解压缩由lz77_compress压缩的数据*/
int lz77_uncompress(const unsigned char *compressed,unsigned char **original)
{
    unsigned char window[LZ77_WINDOW_SIZE],
                  buffer[LZ77_BUFFER_SIZE]
                  *orig,
                  *temp,
                  next;
    int          offset,
                  length,
                  remaining,
                  hsize,
                  size,
                  ipos,
                  opos,
                  tpos,
                  state,
                  i;
    /*使指向原始数据的指针暂时无效*/
    *original = orig = NULL;

/*获取头部信息*/
    hsize = sizeof(int);
    memcpy(&size,compressed,sizeof(int));

/*初始化滑动窗口和前向缓冲区*/
    memset(window, 0, LZ77_WINDOW_SIZE);
    memset(buffer, 0, LZ77_BUFFER_SIZE);

/*解压缩数据*/
    ipos = hsize * 8;
    opos = 0;
    remaining = size;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/63ea8e8e21f6166bd56ddba031d50800.html