public CompressedChunk(XlBinaryReader Data) { this.CompressedChunkStart = Data.i; this.CompressedHeader = new CompressedChunkHeader(Data); this.CompressedData = new CompressedChunkData(this.CompressedHeader, Data); }
//protected TokenSequence _TokenSequence; public CompressedChunkData(CompressedChunkHeader header, XlBinaryReader Data) { this.header = header; if (header.CompressedChunkFlag == (Byte)0x00) { // page 57: CompressedChunkData contains an array of CompressedChunkHeader.CompressedChunkSize // elements plus 3 bytes of uncompressed data int ArraySize = header.CompressedChunkSize + 3; this.Data = new Byte[ArraySize]; int CopySize = header.CompressedChunkSize; // todo: this is my fix... Array.Copy(Data.ReadBytes(CopySize), 0, this.Data, 0, CopySize); //Array.Copy(Data, ArrayIndex, this.Data, 0, CopySize); //ArrayIndex += header.CompressedChunkSize; this.Decompress = (buffer, state) => DecompressRawChunk(buffer, state, this.Data); } else if (header.CompressedChunkFlag == (Byte)0x01) { // TODO: DO something like when compressedcurrent < compressedend -> add a new tokensequence // page 57: CompressedChunkData contains an array of TokenSequence elements var size = Math.Min(header.CompressedChunkSize, Data.Length - Data.i); var tokenSequences = new List <TokenSequence>(); int processedBytes = 0; while (processedBytes < size) { int remainingBytes = size - processedBytes; var tokenSequence = new TokenSequence(Data, remainingBytes); tokenSequences.Add(tokenSequence); processedBytes += tokenSequence.GetSizeInBytes(); } //var tokenSequenceBytes = tokenSequence.GetDataInRawBytes(); //this.Data = tokenSequenceBytes; //var tokenSequenceSize = tokenSequenceBytes.Count(); //if(tokenSequenceSize != header.CompressedChunkSize+3) //{ //throw new InvalidOperationException(String.Format("CompressedChunkData Data-array size expected {0}, but was {1}", header.CompressedChunkSize+3, tokenSequenceSize)); //} this.Decompress = (buffer, state) => DecompressTokenSequence(buffer, state, tokenSequences); } else { throw new Exception(); } //this._TokenSequence = new TokenSequence(ref Data); //Data = Data.Skip(N); }
// 2.4.1.3.7 Compressing a DecompressedChunk // page 62 private static void CompressDecompressedChunk(byte[] Data, CompressedBuffer resultBuffer, DecompressionState state) { var CompressedEnd = state.CompressedChunkStart + 4098; state.CompressedCurrent = state.CompressedChunkStart + 2; var DecompressedEnd = Math.Min(state.DecompressedChunkStart + 4096, state.DecompressedBufferEnd); while (state.DecompressedCurrent < DecompressedEnd && state.CompressedCurrent < CompressedEnd) { CompressTokenSequence(Data, resultBuffer, state, CompressedEnd, DecompressedEnd); } UInt16 CompressedFlag; if (state.DecompressedCurrent < DecompressedEnd) { CompressRawChunk(Data, resultBuffer, state, DecompressedEnd - 1); CompressedFlag = 0; } else { CompressedFlag = 1; } UInt16 size = Convert.ToUInt16(state.CompressedCurrent - state.CompressedChunkStart); var header = new CompressedChunkHeader(0x0000); PackCompressedChunkSize(Data, state, size, header); PackCompressedChunkFlag(Data, state, CompressedFlag, header); PackCompressedChunkSignature(Data, state, header); // SET the CompressedChunkHeader (section 2.4.1.1.5) located at CompressedChunkStart TO Header var bytes = BitConverter.GetBytes(header.AsUInt16()); resultBuffer.SetByte(state.CompressedChunkStart, bytes.First()); resultBuffer.SetByte(state.CompressedChunkStart + 1, bytes.Skip(1).Single()); }
// Section 2.4.1.3.16 private static void PackCompressedChunkFlag(byte[] Data, DecompressionState state, UInt16 CompressedFlag, CompressedChunkHeader header) { if (CompressedFlag != 0 && CompressedFlag != 1) { throw new ArgumentOutOfRangeException("CompressedFlag", "CompressedFlag must be 0 or 1"); } UInt16 temp1 = (UInt16)(header.AsUInt16() & (ushort)0x7FFF); UInt16 temp2 = (UInt16)(CompressedFlag << 15); UInt16 result = (UInt16)(temp1 | temp2); header.SetFrom(result); }
// Section 2.4.1.3.14 private static void PackCompressedChunkSignature(byte[] Data, DecompressionState state, CompressedChunkHeader header) { UInt16 temp = (UInt16)(header.AsUInt16() & (ushort)0x8FFF); UInt16 result = (UInt16)(temp | (ushort)0x3000); header.SetFrom(result); }
// Section 2.4.1.3.13 // page 66 private static void PackCompressedChunkSize(byte[] Data, DecompressionState state, UInt16 size, CompressedChunkHeader header) { if (size > 4098 || size < 3) { throw new ArgumentOutOfRangeException("size", "Size must be between 3 - 4098"); } UInt16 temp1 = (UInt16)(header.AsUInt16() & (ushort)(0xF000)); UInt16 temp2 = (UInt16)(size - 3); UInt16 result = (UInt16)(temp1 | temp2); header.SetFrom(result); }