C代码解压代码更换成js代码


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书写

该回答引用ChatGPT
将C#代码转化成JavaScript代码需要注意的几个点:

1. 在JavaScript中是没有指针的,需要使用数组模拟指针的操作;

2. JavaScript中没有fixed关键字,需要通过创建ArrayBuffer类型的数据进行操作;

3. 在JavaScript中ByteBuffer中没有Buffer.MemoryCopy方法,需要使用ArrayBuffer的slice方法来实现;

4. 在JavaScript中使用typed数组能够更好地模拟C中的数据类型,例如Int32Array、Uint16Array等。

下面是JavaScript代码:


class Decompressor {
constructor(compressedData, offset, length, factor_toDoubleCoordValue) {
var buffer = new ArrayBuffer(compressedData.length);
var uint8Array = new Uint8Array(buffer);
for (var i = 0; i < compressedData.length; i++) {
uint8Array[i] = compressedData[i];
}
var pSrc0 = uint8Array.slice(offset);
this.result = new ArrayBuffer(0);
this.pDst = new Uint8Array(this.result);
this.pSrc = new Uint8Array(pSrc0);
this._srcLen = compressedData.length - offset;
this._srcLen -= offset;
if (this._srcLen < length) {
throw new Error("decoded data too large");
}
this._srcLen = length;
this._dstLen = this.merelyReadUInt32();
var cntVertexes = this.merelyReadUInt32();
var numNonVertexDataBytes = this._dstLen - cntVertexes * 2 * 4;
if (numNonVertexDataBytes <= 0) {
throw new Error("decoded data has invalid format");
}
if (factor_toDoubleCoordValue !== undefined) {
this._toDoubleCoordValue = true;
this._factor_toDoubleCoordValue = factor_toDoubleCoordValue;
}
this.result = new ArrayBuffer(numNonVertexDataBytes + cntVertexes * (this._toDoubleCoordValue ? 2 * 8 : 2 * 4));
this.pDst = new Uint8Array(this.result);
this._dstLen = this.result.byteLength;
var numVertexesRead = 1;
while (this._srcLen != 0 || this._dstLen != 0) {
var dstLenBeforeWriteNonVertexesData = this._dstLen;
this.readNonVertexesData();
this.readVertexesData(numVertexesRead);
numVertexesRead = this.merelyReadUInt32();
if (numVertexesRead == 0) {
break;
}
}
}
readDouble(pVal) {
if (this._srcLen < 8) {
throw new Error("data underflow");
}
this._srcLen -= 8;
pVal[0] = new Float64Array(this.pSrc.slice(0, 8).buffer)[0];
for (var i = 0; i < 8; i++) {
this.pSrc = this.pSrc.slice(1);
}
}
readInt(pVal) {
if (this._srcLen < 4) {
throw new Error("data underflow");
}
this._srcLen -= 4;
pVal[0] = new Int32Array(this.pSrc.slice(0, 4).buffer)[0];
for (var i = 0; i < 4; i++) {
this.pSrc = this.pSrc.slice(1);
}
}
merelyReadUInt32() {
if (this._srcLen < 4) {
throw new Error("data underflow");
}
this._srcLen -= 4;
var uint32Array = new Uint32Array(this.pSrc.slice(0, 4).buffer);
var result = uint32Array[0];
for (var i = 0; i < 4; i++) {
this.pSrc = this.pSrc.slice(1);
}
return result;
}
merelyReadUInt16() {
if (this._srcLen < 2) {
throw new Error("data underflow");
}
this._srcLen -= 2;
var uint16Array = new Uint16Array

js你要看什么环境,如果是浏览器配合客户端,或者手机app小程序,那么应该不行。
如果是nodejs这种服务器的或者 Electronjs,还差不多

class Decompressor {
constructor(compressedData, offset, length, factor_toDoubleCoordValue) {
this.compressedData = compressedData;
this.srcLen = compressedData.length - offset < length ? compressedData.length - offset : length;
this.pSrc = new Uint8Array(compressedData.buffer, offset + compressedData.byteOffset, this.srcLen);
this.dstLen = 0;
this.pDst = null;
this.dstLenBeforeWriteNonVertexesData = 0;
this.toDoubleCoordValue = false;
this.factor_toDoubleCoordValue = NaN;
this.result = null;

    // Start decompression
    let cntVertexes = this.merelyReadUInt32();
    this.dstLen = this.merelyReadUInt32();
    let numNonVertexDataBytes = this.dstLen - cntVertexes * 2 * 4;
    if (numNonVertexDataBytes <= 0)
        throw new Error("Invalid compressed data");

    if (factor_toDoubleCoordValue) {
        this.toDoubleCoordValue = true;
        this.factor_toDoubleCoordValue = factor_toDoubleCoordValue;
    }

    this.result = new Uint8Array(numNonVertexDataBytes + cntVertexes * (this.toDoubleCoordValue ? 2 * 8 : 2 * 4));
    this.pDst = new DataView(this.result.buffer);

    while (this.srcLen > 0 || this.dstLen > 0) {
        this.dstLenBeforeWriteNonVertexesData = this.dstLen;
        this.readNonVertexesData();
        this.readVertexesData();
    }
}

merelyReadUInt32() {
    if (this.srcLen < 4)
        throw new Error("Invalid compressed data");
    let result = this.pSrc[0] | (this.pSrc[1] << 8) | (this.pSrc[2] << 16) | (this.pSrc[3] << 24);
    this.pSrc = this.pSrc.subarray(4);
    this.srcLen -= 4;
    return result >>> 0;
}

merelyReadUInt16() {
    if (this.srcLen < 2)
        throw new Error("Invalid compressed data");
    let result = this.pSrc[0] | (this.pSrc[1] << 8);
    this.pSrc = this.pSrc.subarray(2);
    this.srcLen -= 2;
    return result >>> 0;
}

readRaw(numBytes) {
    if (this.srcLen < numBytes || this.dstLen < numBytes)
        throw new Error("Invalid compressed data");
    for (let i = 0; i < numBytes; i++) {
        this.pDst.setUint8(this.dstLen - numBytes + i, this.pSrc[i]);
    }
    this.pSrc = this.pSrc.subarray(numBytes);
    this.srcLen -= numBytes;
    this.dstLen -= numBytes;
}

readNonVertexesData() {
    let numBytes = this.merelyReadUInt32();
    this.readRaw(numBytes);
}

readVertexesData() {
    let offset_GeomHead = this.merelyReadUInt16();
    if (offset_GeomHead != 0) {
        if (this.dstLen + offset_GeomHead > this.dstLenBeforeWriteNonVertexesData || offset_GeomHead < 8)
            throw new Error("Invalid compressed data");
        let pCoordDim = new Int32Array(this.result.buffer, this.result.byteLength - this.dstLenBeforeWriteNonVertexesData + 4 - offset_GeomHead, 1);
        if (pCoordDim[0] != 0x80)
            throw new Error("Invalid compressed data");
        if (this.toDoubleCoordValue) // Change coordinate dimensions (remove the "single-precision" flag)
            pCoordDim[0] = 0;
    }

    let vLast = { x: 0, y: 0 };
    vLast.x = this.merelyReadUInt32();
    vLast.y = this.merelyReadUInt32();

    if (this.toDoubleCoordValue) {
        if (this.dstLen < 2 * 8)
            throw new Error("Invalid compressed data");
        this.pDst.setFloat64(this.result.byteLength - this.dstLen, this.factor_toDoubleCoordValue * vLast.x, true);
        this.pDst.setFloat64(this.result.byteLength - this.dstLen + 8, this.factor_toDoubleCoordValue * vLast.y, true);
        this.dstLen -= 2 * 8;
    } else {
        if


引用chatGPT作答,以下是转换成js的代码:

class Decompressor {
    constructor(pSrc, srcLen, pDst, dstLen, dstLenBeforeWriteNonVertexesData, toDoubleCoordValue, factor_toDoubleCoordValue) {
    this._pSrc = pSrc;
    this._srcLen = srcLen;
    this._pDst = pDst;
    this._dstLen = dstLen;
    this._dstLenBeforeWriteNonVertexesData = dstLenBeforeWriteNonVertexesData;
    this._toDoubleCoordValue = toDoubleCoordValue;
    this._factor_toDoubleCoordValue = factor_toDoubleCoordValue;
}
MerelyReadUInt32() {
    if (this._srcLen < 4) {
        throw new Error('ArgumentException');
    }
    const result = new DataView(this._pSrc).getUint32(0, true);
    this._pSrc += 4;
    this._srcLen -= 4;
    return result;
}

MerelyReadUInt16() {
    if (this._srcLen < 2) {
        throw new Error('ArgumentException');
    }
    const result = new DataView(this._pSrc).getUint16(0, true);
    this._pSrc += 2;
    this._srcLen -= 2;
    return result;
}

ReadRaw(numBytes) {
    if (this._srcLen < numBytes || this._dstLen < numBytes) {
        throw new Error('ArgumentException');
    }
    const srcView = new DataView(this._pSrc);
    const dstView = new DataView(this._pDst.buffer);
    for (let i = 0; i < numBytes; i++) {
        dstView.setUint8(i, srcView.getUint8(i));
    }
    this._pSrc += numBytes;
    this._srcLen -= numBytes;
    this._pDst += numBytes;
    this._dstLen -= numBytes;
}

ReadNonVertexesData() {
    const numBytes = this.MerelyReadUInt32();
    this.ReadRaw(numBytes);
}

ReadVertexesData() {
    const offset_GeomHead = this.MerelyReadUInt16();
    if (offset_GeomHead !== 0) {
        if (this._dstLen + offset_GeomHead > this._dstLenBeforeWriteNonVertexesData || offset_GeomHead < 8) {
            throw new Error('ArgumentException');
        }
        const pCoordDim = new Int32Array(this._pDst.buffer, (4 - offset_GeomHead));
        if (pCoordDim[0] !== 0x80) {
            throw new Error('ArgumentException');
        }
        if (this._toDoubleCoordValue) {
            pCoordDim[0] = 0;
        }
    }
    if (this._srcLen < 8) {
        throw new Error('ArgumentException');
    }
    const vLast = new Int32Array(this._pSrc.buffer, 0, 2);
    this._pSrc += 8;
    this._srcLen -= 8;
    if (this._toDoubleCoordValue) {
        if (this._dstLen < 16) {
            throw new Error('ArgumentException');
        }
        const pDst = new Float64Array(this._pDst.buffer);
        pDst[0] = this._factor_toDoubleCoordValue * vLast[0];
        pDst[1] = this._factor_toDoubleCoordValue * vLast[1];
        this._pDst += 16;
        this._dstLen -= 16;
    } else {
                    }
                    else
                    {
                        // 将顶点坐标写入输出缓冲区
                        for (int i = 0; i < cnt0; ++i)
                        {
                            ((Vertex2I*)_pDst)[i] = vLast;
                            vLast.x += ((short*)_pSrc)[i * 2];
                            vLast.y += ((short*)_pSrc)[i * 2 + 1];
                        }
                        _pSrc += srcLenChange;
                        _srcLen -= srcLenChange;
                        _pDst += dstLenChange;
                        _dstLen -= dstLenChange;
                    }
                }
                numVertexesRead = cnt1;
            }
        }

        public byte[] Decompress(byte[] src, uint dstLen, bool toDoubleCoordValue, double factor_toDoubleCoordValue)
        {
            if (src == null)
                throw new ArgumentNullException();
            if (dstLen < src.Length)
                throw new ArgumentException();

            unsafe
            {
                fixed (byte* pSrc = &src[0])
                {
                    _pSrc = pSrc;
                    _srcLen = (uint)src.Length;
                    _toDoubleCoordValue = toDoubleCoordValue;
                    _factor_toDoubleCoordValue = factor_toDoubleCoordValue;
                    _dstLenBeforeWriteNonVertexesData = 0;

                    // 获取压缩数据中非顶点数据的长度,并跳过
                    ReadNonVertexesData();

                    // 获取输出缓冲区的首地址,并跳过写入非顶点数据的部分
                    fixed (byte* pDst = new byte[dstLen])
                    {
                        _pDst = pDst;
                        _dstLen = dstLen;
                        _dstLenBeforeWriteNonVertexesData = _dstLen;
                        ReadVertexesData();
                        return new Span<byte>(pDst, (int)(_pDst - pDst)).ToArray();
                    }
                }
            }
        }
    }
            }
            //读取拓扑结构
            ReadRaw(numTopoBytes);
        }
        public void Decompress(byte[] src, byte[] dst, uint dstLenBeforeWriteNonVertexesData, bool toDoubleCoordValue, double factor_toDoubleCoordValue)
        {
            if (src == null || dst == null)
                throw new ArgumentNullException();
            if (dstLenBeforeWriteNonVertexesData > (uint)dst.Length)
                throw new ArgumentException();
            _pSrc = (byte*)src;
            _srcLen = (uint)src.Length;
            _pDst = (byte*)dst;
            _dstLen = (uint)dst.Length;
            _dstLenBeforeWriteNonVertexesData = dstLenBeforeWriteNonVertexesData;
            _toDoubleCoordValue = toDoubleCoordValue;
            _factor_toDoubleCoordValue = factor_toDoubleCoordValue;
            //读取并跳过“TBR”字节(TrueBendRelaxer压缩器的标识)
            ReadRaw(3);
            //读取并跳过最初的四字节
            ReadRaw(4);
            //读取顶点和非顶点数据
            ReadVertexesData();
            ReadNonVertexesData();
        }
    }

该回答引用ChatGPT
对于将C#代码转换为JS代码,可以参考以下几个方面:

1. 类和属性的声明方式不同。在C#中,可以使用class和unsafe定义类和指针类型;而在JS中,使用class和type等方式定义类和类型声明,以及字面量语法等方式定义对象。

2. 指针类型的使用。C#中有指针类型,而JS中没有这种类型。因此,需要用其他方式替代指针类型,比如使用数组和对象等方式。

3. 数据类型的映射。在C#和JS之间,有一些相同和不同的数据类型,比如uint、byte、bool、double等,需要使用不同的方式映射。

下面是将C#代码转换为JS代码的一个示例,在这个示例中使用了ES6语法,需要在浏览器或NodeJS环境下运行:

js
class Vertex2I {
constructor() {
this.x = 0;
this.y = 0;
}
}

class Vertex2d {
constructor() {
this.x = 0.0;
this.y = 0.0;
}
}

class Decompressor {
constructor(compressedData, offset, length, factor_toDoubleCoordValue) {
this._srcLen = compressedData.length;
if (this._srcLen < offset) throw new Error('ArgumentOutOfRangeException');
this._srcLen -= offset;
if (this._srcLen < length) throw new Error('ArgumentOutOfRangeException');
this._srcLen = length;
this._pSrc = new Uint8Array(compressedData.buffer, compressedData.byteOffset + offset, length);
this._dstLen = this.MerelyReadUInt32();
const numVertexes = this.CountVertexes();
const numNonVertexDataBytes = this._dstLen - numVertexes * 8;

this._toDoubleCoordValue = false;
if (factor_toDoubleCoordValue) {
this._toDoubleCoordValue = true;
this._factor_toDoubleCoordValue = factor_toDoubleCoordValue;
}

this.result = new ArrayBuffer(numNonVertexDataBytes + numVertexes * (this._toDoubleCoordValue ? 16 : 8));
this.view = new DataView(this.result);
this._dstLen = this.result.byteLength;
this._dstPos = 0;

while (this._srcLen > 0 || this._dstLen > 0) {
this._dstLenBeforeWriteNonVertexesData = this._dstLen;
this.ReadNonVertexesData();
this.ReadVertexesData();
}
}

MerelyReadUInt16() {
if (this._srcLen < 2) throw new Error('ArgumentOutOfRangeException');
const result = this._view.getUint16(this._srcPos, true);
this._srcPos += 2;
this._srcLen -= 2;
return result;
}

MerelyReadUInt32() {
if (this._srcLen < 4) throw new Error('ArgumentOutOfRangeException');
const result = this._view.getUint32(this._srcLen - 4, true);
this._srcLen -= 4;
return result;
}

CountVertexes() {
if (this._srcLen < 4) throw new Error('ArgumentOutOfRangeException');
return this._view.getUint32(this._srcLen - 4, true);
}

ReadRaw(numBytes) {
if (this._srcLen < numBytes || this._dstLen < numBytes) throw new Error('ArgumentOutOfRangeException');
const srcArray = new Uint8Array(this._src.buffer, this._src.byteOffset + this._srcPos, numBytes);
const dstArray = new Uint8Array(this.result, this._dstPos, numBytes);
dstArray.set(srcArray);
this._srcPos += numBytes;
this._srcLen -= numBytes;
this._dstPos += numBytes;
this._dstLen -= numBytes;
}

ReadNonVertexesData() {
const numBytes = this.MerelyReadUInt32();
this.ReadRaw(numBytes);
}

以下内容部分参考ChatGPT模型:
由于涉及到指针、内存操作等不安全操作,在JavaScript中无法进行直接的转换。建议使用其他能够支持这些操作的语言进行转换。
如果我的建议对您有帮助、请点击采纳、祝您生活愉快

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^