unsafe class Decompressor
{
byte* _pSrc;
uint _srcLen;
byte* _pDst;
uint _dstLen;
uint _dstLenBeforeWriteNonVertexesData;
bool _toDoubleCoordValue;
double _factor_toDoubleCoordValue;
uint MerelyReadUInt32()
{
if (_srcLen < sizeof(uint))
throw new ArgumentException();
var result = *(uint*)_pSrc;
_pSrc += sizeof(uint);
_srcLen -= sizeof(uint);
return result;
}
ushort MerelyReadUInt16()
{
if (_srcLen < sizeof(ushort))
throw new ArgumentException();
var result = *(ushort*)_pSrc;
_pSrc += sizeof(ushort);
_srcLen -= sizeof(ushort);
return result;
}
void ReadRaw(uint numBytes)
{
if (_srcLen < numBytes || _dstLen < numBytes)
throw new ArgumentException();
Buffer.MemoryCopy(_pSrc, _pDst, _dstLen, numBytes);
_pSrc += numBytes;
_srcLen -= numBytes;
_pDst += numBytes;
_dstLen -= numBytes;
}
void ReadNonVertexesData()
{
var numBytes = MerelyReadUInt32();
ReadRaw(numBytes);
}
void ReadVertexesData()
{
//读取几何头的位置
var offset_GeomHead = MerelyReadUInt16();
if (offset_GeomHead != 0)
{
if (_dstLen + offset_GeomHead > _dstLenBeforeWriteNonVertexesData || offset_GeomHead < 8)
throw new ArgumentException();
var pCoordDim = (int*)(_pDst + (4 - offset_GeomHead));
if (*pCoordDim != 0x80)
throw new ArgumentException();
if (_toDoubleCoordValue)//更改坐标维度(消除“单精度”标志)
*pCoordDim = 0;
}
//读取首顶点
if (_srcLen < sizeof(int) * 2)
throw new ArgumentException();
var vLast = *(Vertex2I*)_pSrc;
_pSrc += sizeof(int) * 2;
_srcLen -= sizeof(int) * 2;
if (_toDoubleCoordValue)
{
if (_dstLen < sizeof(double) * 2)
throw new ArgumentException();
var pDst = (Vertex2d*)_pDst;
pDst->x = _factor_toDoubleCoordValue * vLast.x;
pDst->y = _factor_toDoubleCoordValue * vLast.y;
_pDst += sizeof(double) * 2;
_dstLen -= sizeof(double) * 2;
}
else
{
if (_dstLen < sizeof(int) * 2)
throw new ArgumentException();
*(Vertex2I*)_pDst = vLast;
_pDst += sizeof(int) * 2;
_dstLen -= sizeof(int) * 2;
}
var numVeretxes = MerelyReadUInt32();
if (numVeretxes == 0)
throw new ArgumentException();
uint numVertexesRead = 1;
while (numVertexesRead < numVeretxes)
{
var cnt = MerelyReadUInt16();
var cnt0 = (uint)(cnt & 0x7FFF);
long cnt1 = numVertexesRead;
cnt1 += cnt0;
if (cnt1 == numVertexesRead || cnt1 > numVeretxes)
throw new ArgumentException();
if ((cnt & 0x8000) != 0)
{//
if (_toDoubleCoordValue)
{
var srcLenChange = (uint)sizeof(int) * 2 * cnt0;
var dstLenChange = (uint)sizeof(double) * 2 * cnt0;
if (_srcLen < srcLenChange || _dstLen < dstLenChange)
throw new ArgumentException();
for (uint i = 0; i < cnt0; ++i)
{
((double*)_pDst)[i * 2] = _factor_toDoubleCoordValue * ((int*)_pSrc)[i * 2];
((double*)_pDst)[i * 2 + 1] = _factor_toDoubleCoordValue * ((int*)_pSrc)[i * 2 + 1];
}
_pSrc += srcLenChange;
_srcLen -= srcLenChange;
_pDst += dstLenChange;
_dstLen -= dstLenChange;
}
else
{
ReadRaw(cnt0 * sizeof(int) * 2);
}
vLast = ((Vertex2I*)_pSrc)[-1];
}
else
{
var srcLenChange = (uint)sizeof(short) * 2 * cnt0;
var dstLenChange = (uint)(_toDoubleCoordValue ? sizeof(double) : sizeof(int)) * 2 * cnt0;
if (_srcLen < srcLenChange || _dstLen < dstLenChange)
throw new ArgumentException();
if (_toDoubleCoordValue)
{
for (uint i = 0; i < cnt0; ++i)
{
((double*)_pDst)[i * 2] = _factor_toDoubleCoordValue * (vLast.x += ((short*)_pSrc)[i * 2]);
((double*)_pDst)[i * 2 + 1] = _factor_toDoubleCoordValue * (vLast.y += ((short*)_pSrc)[i * 2 + 1]);
}
}
else
{
for (uint i = 0; i < cnt0; ++i)
{
((int*)_pDst)[i * 2] = vLast.x += ((short*)_pSrc)[i * 2];
((int*)_pDst)[i * 2 + 1] = vLast.y += ((short*)_pSrc)[i * 2 + 1];
}
}
_pSrc += srcLenChange;
_srcLen -= srcLenChange;
_pDst += dstLenChange;
_dstLen -= dstLenChange;
}
numVertexesRead = (uint)cnt1;
}
}
public byte[] Result { get; }
internal Decompressor(byte[] compressedData, uint offset, uint length, double? factor_toDoubleCoordValue)
{
_srcLen = (uint)compressedData.Length;
if (_srcLen < offset)
throw new ArgumentException();
_srcLen -= offset;
if (_srcLen < length)
throw new ArgumentException();
_srcLen = length;
fixed (byte* pSrc0 = &compressedData[offset]) //fixed禁止垃圾回收器重定位可移动的变量。fixed语句只能出现在不安全的上下文中。
{
_pSrc = pSrc0; //
//读取顶点数量
if (_srcLen < sizeof(uint))
throw new ArgumentException();
var cntVertexes = *(uint*)(_pSrc + (_srcLen - sizeof(uint)));
_srcLen -= sizeof(uint);
//准备结果缓冲区
_dstLen = MerelyReadUInt32();
var numNonVertexDataBytes = _dstLen - (long)cntVertexes * sizeof(int) * 2;
if (numNonVertexDataBytes <= 0)
throw new ArgumentException();
if (_toDoubleCoordValue = factor_toDoubleCoordValue.HasValue)
_factor_toDoubleCoordValue = factor_toDoubleCoordValue.Value;
Result = new byte[numNonVertexDataBytes + cntVertexes * (_toDoubleCoordValue ? sizeof(double) : sizeof(int)) * 2];
_dstLen = (uint)Result.Length;
fixed (byte* pDst0 = &Result[0])
{
_pDst = pDst0;
//
while (_srcLen != 0 || _dstLen != 0)
{
_dstLenBeforeWriteNonVertexesData = _dstLen;
ReadNonVertexesData();
ReadVertexesData();
}
}
}
}
}
能否更新成js书写