internal bool getValue(LinkedListNode <byte> code, out int value) { value = data; if (code == null) { return(node0 == null && node1 == null && data >= 0); } if (code.Value > 1) { throw new Exception(String.Format("the list should be a list of bytes < 2. got:{0:g}", code.Value)); } byte c = code.Value; bool retVal; HuffTreeNode n = c == 0 ? node0 : node1; retVal = n != null && n.getValue(code.Previous, out value); return(retVal); }
public override byte[] Decompress(byte[] buffer, int offset) { BinaryReader br = new BinaryReader(new MemoryStream(buffer, offset, buffer.Length - offset)); byte firstByte = br.ReadByte(); int dataSize = firstByte & 0x0F; if (dataSize != 8 && dataSize != 4) { throw new Exception(string.Format("Unhandled Huffman dataSize {0:x}", dataSize)); } int decomp_size = 0; for (int i = 0; i < 3; i++) { decomp_size |= br.ReadByte() << (i * 8); } byte treeSize = br.ReadByte(); HuffTreeNode.maxInpos = 4 + (treeSize + 1) * 2; HuffTreeNode rootNode = new HuffTreeNode(); rootNode.parseData(br); br.BaseStream.Position = 4 + (treeSize + 1) * 2; uint[] indata = new uint[(br.BaseStream.Length - br.BaseStream.Position) / 4]; for (int i = 0; i < indata.Length; i++) { indata[i] = br.ReadUInt32(); } long curr_size = 0; decomp_size *= dataSize == 8 ? 1 : 2; byte[] outdata = new byte[decomp_size]; int idx = -1; string codestr = ""; LinkedList <byte> code = new LinkedList <byte>(); int value; while (curr_size < decomp_size) { try { string newstr = uint_to_bits(indata[++idx]); codestr += newstr; } catch (IndexOutOfRangeException e) { throw new IndexOutOfRangeException("not enough data.", e); } while (codestr.Length > 0) { code.AddFirst(byte.Parse(codestr[0] + "")); codestr = codestr.Remove(0, 1); if (rootNode.getValue(code.Last, out value)) { try { outdata[curr_size++] = (byte)value; } catch (IndexOutOfRangeException ex) { if (code.First.Value != 0) { throw ex; } } code.Clear(); } } } br.Close(); byte[] realout; if (dataSize == 4) { realout = new byte[decomp_size / 2]; for (int i = 0; i < decomp_size / 2; i++) { if ((outdata[i * 2] & 0xF0) > 0 || (outdata[i * 2 + 1] & 0xF0) > 0) { throw new Exception("first 4 bits of data should be 0 if dataSize = 4"); } realout[i] = (byte)((outdata[i * 2] << 4) | outdata[i * 2 + 1]); } } else { realout = outdata; } return(realout); }