Apple的LZF算法解析

时间:2022-05-02 14:54:28

有关LZF算法的相关解析文档比较少,但是Apple对LZF的开源,可以让我们对该算法进行一个简单的解析。LZFSE 基于 Lempel-Ziv ,并使用了有限状态熵编码。LZF采用类似lz77和lzss的混合编码。使用3种“起始标记”来代表每段输出的数据串。

接下来看一下开源的LZF算法的实现源码。

1.定义的全局字段:

       private readonly long[] _hashTable = new long[Hsize];

        private const uint Hlog = ;

        private const uint Hsize = ( << );

        private const uint MaxLit = ( << );

        private const uint MaxOff = ( << );

        private const uint MaxRef = (( << ) + ( << ));

2.使用LibLZF算法压缩数据:

        /// <summary>
/// 使用LibLZF算法压缩数据
/// </summary>
/// <param name="input">需要压缩的数据</param>
/// <param name="inputLength">要压缩的数据的长度</param>
/// <param name="output">引用将包含压缩数据的缓冲区</param>
/// <param name="outputLength">压缩缓冲区的长度(应大于输入缓冲区)</param>
/// <returns>输出缓冲区中压缩归档的大小</returns>
public int Compress(byte[] input, int inputLength, byte[] output, int outputLength)
{
Array.Clear(_hashTable, , (int)Hsize);
uint iidx = ;
uint oidx = ;
var hval = (uint)(((input[iidx]) << ) | input[iidx + ]);
var lit = ;
for (; ; )
{
if (iidx < inputLength - )
{
hval = (hval << ) | input[iidx + ];
long hslot = ((hval ^ (hval << )) >> (int)((( * - Hlog)) - hval * ) & (Hsize - ));
var reference = _hashTable[hslot];
_hashTable[hslot] = iidx;
long off;
if ((off = iidx - reference - ) < MaxOff
&& iidx + < inputLength
&& reference >
&& input[reference + ] == input[iidx + ]
&& input[reference + ] == input[iidx + ]
&& input[reference + ] == input[iidx + ]
)
{
uint len = ;
var maxlen = (uint)inputLength - iidx - len;
maxlen = maxlen > MaxRef ? MaxRef : maxlen;
if (oidx + lit + + >= outputLength)
return ;
do
len++;
while (len < maxlen && input[reference + len] == input[iidx + len]);
if (lit != )
{
output[oidx++] = (byte)(lit - );
lit = -lit;
do
output[oidx++] = input[iidx + lit];
while ((++lit) != );
}
len -= ;
iidx++;
if (len < )
{
output[oidx++] = (byte)((off >> ) + (len << ));
}
else
{
output[oidx++] = (byte)((off >> ) + ( << ));
output[oidx++] = (byte)(len - );
}
output[oidx++] = (byte)off;
iidx += len - ;
hval = (uint)(((input[iidx]) << ) | input[iidx + ]);
hval = (hval << ) | input[iidx + ];
_hashTable[((hval ^ (hval << )) >> (int)((( * - Hlog)) - hval * ) & (Hsize - ))] = iidx;
iidx++;
hval = (hval << ) | input[iidx + ];
_hashTable[((hval ^ (hval << )) >> (int)((( * - Hlog)) - hval * ) & (Hsize - ))] = iidx;
iidx++;
continue;
}
}
else if (iidx == inputLength)
break;
lit++;
iidx++;
if (lit != MaxLit) continue;
if (oidx + + MaxLit >= outputLength)
return ; output[oidx++] = (byte)(MaxLit - );
lit = -lit;
do
output[oidx++] = input[iidx + lit];
while ((++lit) != );
}
if (lit == ) return (int)oidx;
if (oidx + lit + >= outputLength)
return ;
output[oidx++] = (byte)(lit - );
lit = -lit;
do
output[oidx++] = input[iidx + lit];
while ((++lit) != ); return (int)oidx;
}

3.

        /// <summary>
/// 使用LibLZF算法解压缩数据
/// </summary>
/// <param name="input">参考数据进行解压缩</param>
/// <param name="inputLength">要解压缩的数据的长度</param>
/// <param name="output">引用包含解压缩数据的缓冲区</param>
/// <param name="outputLength">输出缓冲区中压缩归档的大小</param>
/// <returns>返回解压缩大小</returns>
public int Decompress(byte[] input, int inputLength, byte[] output, int outputLength)
{
uint iidx = ;
uint oidx = ;
do
{
uint ctrl = input[iidx++]; if (ctrl < ( << ))
{
ctrl++; if (oidx + ctrl > outputLength)
{
return ;
} do
output[oidx++] = input[iidx++];
while ((--ctrl) != );
}
else
{
var len = ctrl >> ;
var reference = (int)(oidx - ((ctrl & 0x1f) << ) - );
if (len == )
len += input[iidx++];
reference -= input[iidx++];
if (oidx + len + > outputLength)
{
return ;
}
if (reference < )
{
return ;
}
output[oidx++] = output[reference++];
output[oidx++] = output[reference++];
do
output[oidx++] = output[reference++];
while ((--len) != );
}
}
while (iidx < inputLength); return (int)oidx;
}

以上是LZF算法的代码。

Apple的LZF算法解析的更多相关文章

  1. 地理围栏算法解析(Geo-fencing)

    地理围栏算法解析 http://www.cnblogs.com/LBSer/p/4471742.html 地理围栏(Geo-fencing)是LBS的一种应用,就是用一个虚拟的栅栏围出一个虚拟地理边界 ...

  2. KMP串匹配算法解析与优化

    朴素串匹配算法说明 串匹配算法最常用的情形是从一篇文档中查找指定文本.需要查找的文本叫做模式串,需要从中查找模式串的串暂且叫做查找串吧. 为了更好理解KMP算法,我们先这样看待一下朴素匹配算法吧.朴素 ...

  3. Peterson算法与Dekker算法解析

    进来Bear正在学习巩固并行的基础知识,所以写下这篇基础的有关并行算法的文章. 在讲述两个算法之前,需要明确一些概念性的问题, Race Condition(竞争条件),Situations  lik ...

  4. python常见排序算法解析

    python——常见排序算法解析   算法是程序员的灵魂. 下面的博文是我整理的感觉还不错的算法实现 原理的理解是最重要的,我会常回来看看,并坚持每天刷leetcode 本篇主要实现九(八)大排序算法 ...

  5. Java虚拟机对象存活标记及垃圾收集算法解析

    一.对象存活标记 1. 引用计数算法 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加1:当引用失效时,计数器就减1:任何时刻计数器都为0的对象就是不可能再被使用的. 引用计数算法(Re ...

  6. JVM垃圾回收算法解析

    JVM垃圾回收算法解析 标记-清除算法 该算法为最基础的算法.它分为标记和清除两个阶段,首先标记出需要回收的对象,在标记结束后,统一回收.该算法存在两个问题:一是效率问题,标记和清除过程效率都不太高, ...

  7. DeepFM算法解析及Python实现

    1. DeepFM算法的提出 由于DeepFM算法有效的结合了因子分解机与神经网络在特征学习中的优点:同时提取到低阶组合特征与高阶组合特征,所以越来越被广泛使用. 在DeepFM中,FM算法负责对一阶 ...

  8. GBDT&plus;LR算法解析及Python实现

    1. GBDT + LR 是什么 本质上GBDT+LR是一种具有stacking思想的二分类器模型,所以可以用来解决二分类问题.这个方法出自于Facebook 2014年的论文 Practical L ...

  9. 最长上升子序列&lpar;LIS&rpar;n2 nlogn算法解析

    题目描述 给定一个数列,包含N个整数,求这个序列的最长上升子序列. 例如 2 5 3 4 1 7 6 最长上升子序列为 4. 1.O(n2)算法解析 看到这个题,大家的直觉肯定都是要用动态规划来做,那 ...

随机推荐

  1. GitHub 用到的英语

    1.Github首页Pull requests   Issues Gist请求 问题 要点Learn Git and GitHub without any code!没有任何代码学习Git和GitHu ...

  2. javascript 面向对象编程小记

    虽然平常用jquery用的很熟,但是基本都是面向过程的写法.一个事件一个function,很少有面向对象的写法.今天得写一个日期控件,不得不用上面向对象编程. 刚开始我的想法是: var datepi ...

  3. yii2&period;0配置以pathinfo的形式访问

    yii2.0默认的访问形式为:dxr.com/index.php?r=index/list,一般我们都会配置成pathinfo的形式来访问:dxr.com/index/list,这样更符合用户习惯. ...

  4. 关于EntityFramework在vs2012无法引用的问题

    这段时间学习MVC,发现一个问题,我公司的电脑可以直接引用EntityFrameWork这个命名空间,但我家里面的电脑就不能直接引用,刚开始以为是我电脑配置问题,后重装电脑,发现问题并没有解决. 今天 ...

  5. 有关OpenCV1&period;0中GUI命令的几个函数学习总结

    1.修改窗口背景色或者光标形状 在OpenCV1.0版本利用函数int cvNamedWindow( const char* name, int flags )初始化创建一个窗口后,窗口的背景色是灰色 ...

  6. &lbrack;JavaEE&rsqb; SSH框架笔记&lowbar;S&period;S&period;H框架各自的优缺点

    Struts的原理和优点.Struts工作原理MVC即Model-View-Controller的缩写,是一种常用的设计模式.MVC 减弱了业务逻辑接口和数据接口之间的耦合,以及让视图层更富于变化.M ...

  7. MoonWarriors-lua——《雷电战机》游戏-Lua移植版

    MoonWarriors是一个使用Cocos2d-Html5引擎开发的类似雷电战机的游戏Demo,源代码发布在Cocos2d-x官网的引擎示例当中.MoonWarriors-lua是为了学习Cocos ...

  8. sqlplus登录问题

    问题1.sqlplus login -- SP2-0750: You may need to set ORACLE_HOME to your Oracle software directory 在/e ...

  9. 简单的cd命令

    cd ~ :进入home目录 cd   :进入home目录 cd - :进入上一个目录 cd /home/venn : 进入指定目录 当然,我想说的是cd(不加任何路径),进入home目录

  10. Java之split方法

    Java之split方法 1.间隔号"." (1)str.split(".") String str = "10.156.35.87"; S ...