You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tika.apache.org by ol...@apache.org on 2011/06/08 23:00:28 UTC

svn commit: r1133554 [4/5] - in /tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/chm: ./ accessor/ assertion/ core/ exception/ lzx/

Modified: tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/chm/lzx/ChmBlockInfo.java
URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/chm/lzx/ChmBlockInfo.java?rev=1133554&r1=1133553&r2=1133554&view=diff
==============================================================================
--- tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/chm/lzx/ChmBlockInfo.java (original)
+++ tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/chm/lzx/ChmBlockInfo.java Wed Jun  8 21:00:27 2011
@@ -29,201 +29,201 @@ import org.apache.tika.parser.chm.except
  * 
  */
 public class ChmBlockInfo {
-	/* class members */
-	private int iniBlock;
-	private int startBlock;
-	private int endBlock;
-	private int startOffset;
-	private int endOffset;
-
-	private static ChmBlockInfo chmBlockInfo = null;
-
-	private ChmBlockInfo() {
-
-	}
-
-	/**
-	 * Returns an information related to the chmBlockInfo
-	 * 
-	 * @param dle
-	 *            - DirectoryListingEntry
-	 * @param bytesPerBlock
-	 *            - int, = chmLzxcResetTable.block_length
-	 * @param clcd
-	 *            - ChmLzxcControlData
-	 * @param chmBlockInfo
-	 *            - ChmBlockInfo
-	 * 
-	 * @return ChmBlockInfo
-	 */
-	protected ChmBlockInfo getChmBlockInfo(DirectoryListingEntry dle,
-			int bytesPerBlock, ChmLzxcControlData clcd,
-			ChmBlockInfo chmBlockInfo) {
-		if (!validateParameters(dle, bytesPerBlock, clcd, chmBlockInfo))
-			throw new ChmParsingException("Please check you parameters");
-
-		chmBlockInfo.setStartBlock(dle.getOffset() / bytesPerBlock);
-		chmBlockInfo.setEndBlock((dle.getOffset() + dle.getLength())
-				/ bytesPerBlock);
-		chmBlockInfo.setStartOffset(dle.getOffset() % bytesPerBlock);
-		chmBlockInfo.setEndOffset((dle.getOffset() + dle.getLength())
-				% bytesPerBlock);
-		// potential problem with casting long to int
-		chmBlockInfo
-				.setIniBlock((chmBlockInfo.startBlock - chmBlockInfo.startBlock)
-						% (int) clcd.getResetInterval());
-		return chmBlockInfo;
-	}
-
-	public static ChmBlockInfo getChmBlockInfoInstance(
-			DirectoryListingEntry dle, int bytesPerBlock,
-			ChmLzxcControlData clcd) {
-		setChmBlockInfo(new ChmBlockInfo());
-		getChmBlockInfo().setStartBlock(dle.getOffset() / bytesPerBlock);
-		getChmBlockInfo().setEndBlock(
-				(dle.getOffset() + dle.getLength()) / bytesPerBlock);
-		getChmBlockInfo().setStartOffset(dle.getOffset() % bytesPerBlock);
-		getChmBlockInfo().setEndOffset(
-				(dle.getOffset() + dle.getLength()) % bytesPerBlock);
-		// potential problem with casting long to int
-		getChmBlockInfo().setIniBlock(
-				(getChmBlockInfo().startBlock - getChmBlockInfo().startBlock)
-						% (int) clcd.getResetInterval());
-		return getChmBlockInfo();
-	}
-
-	/**
-	 * Returns textual representation of ChmBlockInfo
-	 */
-	public String toString() {
-		StringBuilder sb = new StringBuilder();
-		sb.append("iniBlock:=" + getIniBlock() + ", ");
-		sb.append("startBlock:=" + getStartBlock() + ", ");
-		sb.append("endBlock:=" + getEndBlock() + ", ");
-		sb.append("startOffset:=" + getStartOffset() + ", ");
-		sb.append("endOffset:=" + getEndOffset()
-				+ System.getProperty("line.separator"));
-		return sb.toString();
-	}
-
-	private boolean validateParameters(DirectoryListingEntry dle,
-			int bytesPerBlock, ChmLzxcControlData clcd,
-			ChmBlockInfo chmBlockInfo) {
-		int goodParameter = 0;
-		if (dle != null)
-			++goodParameter;
-		if (bytesPerBlock > 0)
-			++goodParameter;
-		if (clcd != null)
-			++goodParameter;
-		if (chmBlockInfo != null)
-			++goodParameter;
-		return (goodParameter == 4);
-	}
-
-	public static void main(String[] args) {
-	}
-
-	/**
-	 * Returns an initial block index
-	 * 
-	 * @return int
-	 */
-	public int getIniBlock() {
-		return iniBlock;
-	}
-
-	/**
-	 * Sets the initial block index
-	 * 
-	 * @param iniBlock
-	 *            - int
-	 */
-	private void setIniBlock(int iniBlock) {
-		this.iniBlock = iniBlock;
-	}
-
-	/**
-	 * Returns the start block index
-	 * 
-	 * @return int
-	 */
-	public int getStartBlock() {
-		return startBlock;
-	}
-
-	/**
-	 * Sets the start block index
-	 * 
-	 * @param startBlock
-	 *            - int
-	 */
-	private void setStartBlock(int startBlock) {
-		this.startBlock = startBlock;
-	}
-
-	/**
-	 * Returns the end block index
-	 * 
-	 * @return - int
-	 */
-	public int getEndBlock() {
-		return endBlock;
-	}
-
-	/**
-	 * Sets the end block index
-	 * 
-	 * @param endBlock
-	 *            - int
-	 */
-	private void setEndBlock(int endBlock) {
-		this.endBlock = endBlock;
-	}
-
-	/**
-	 * Returns the start offset index
-	 * 
-	 * @return - int
-	 */
-	public int getStartOffset() {
-		return startOffset;
-	}
-
-	/**
-	 * Sets the start offset index
-	 * 
-	 * @param startOffset
-	 *            - int
-	 */
-	private void setStartOffset(int startOffset) {
-		this.startOffset = startOffset;
-	}
-
-	/**
-	 * Returns the end offset index
-	 * 
-	 * @return - int
-	 */
-	public int getEndOffset() {
-		return endOffset;
-	}
-
-	/**
-	 * Sets the end offset index
-	 * 
-	 * @param endOffset
-	 *            - int
-	 */
-	private void setEndOffset(int endOffset) {
-		this.endOffset = endOffset;
-	}
-
-	public static void setChmBlockInfo(ChmBlockInfo chmBlockInfo) {
-		ChmBlockInfo.chmBlockInfo = chmBlockInfo;
-	}
-
-	public static ChmBlockInfo getChmBlockInfo() {
-		return chmBlockInfo;
-	}
+    /* class members */
+    private int iniBlock;
+    private int startBlock;
+    private int endBlock;
+    private int startOffset;
+    private int endOffset;
+
+    private static ChmBlockInfo chmBlockInfo = null;
+
+    private ChmBlockInfo() {
+
+    }
+
+    /**
+     * Returns an information related to the chmBlockInfo
+     * 
+     * @param dle
+     *            - DirectoryListingEntry
+     * @param bytesPerBlock
+     *            - int, = chmLzxcResetTable.block_length
+     * @param clcd
+     *            - ChmLzxcControlData
+     * @param chmBlockInfo
+     *            - ChmBlockInfo
+     * 
+     * @return ChmBlockInfo
+     */
+    protected ChmBlockInfo getChmBlockInfo(DirectoryListingEntry dle,
+            int bytesPerBlock, ChmLzxcControlData clcd,
+            ChmBlockInfo chmBlockInfo) {
+        if (!validateParameters(dle, bytesPerBlock, clcd, chmBlockInfo))
+            throw new ChmParsingException("Please check you parameters");
+
+        chmBlockInfo.setStartBlock(dle.getOffset() / bytesPerBlock);
+        chmBlockInfo.setEndBlock((dle.getOffset() + dle.getLength())
+                / bytesPerBlock);
+        chmBlockInfo.setStartOffset(dle.getOffset() % bytesPerBlock);
+        chmBlockInfo.setEndOffset((dle.getOffset() + dle.getLength())
+                % bytesPerBlock);
+        // potential problem with casting long to int
+        chmBlockInfo
+                .setIniBlock((chmBlockInfo.startBlock - chmBlockInfo.startBlock)
+                        % (int) clcd.getResetInterval());
+        return chmBlockInfo;
+    }
+
+    public static ChmBlockInfo getChmBlockInfoInstance(
+            DirectoryListingEntry dle, int bytesPerBlock,
+            ChmLzxcControlData clcd) {
+        setChmBlockInfo(new ChmBlockInfo());
+        getChmBlockInfo().setStartBlock(dle.getOffset() / bytesPerBlock);
+        getChmBlockInfo().setEndBlock(
+                (dle.getOffset() + dle.getLength()) / bytesPerBlock);
+        getChmBlockInfo().setStartOffset(dle.getOffset() % bytesPerBlock);
+        getChmBlockInfo().setEndOffset(
+                (dle.getOffset() + dle.getLength()) % bytesPerBlock);
+        // potential problem with casting long to int
+        getChmBlockInfo().setIniBlock(
+                (getChmBlockInfo().startBlock - getChmBlockInfo().startBlock)
+                        % (int) clcd.getResetInterval());
+        return getChmBlockInfo();
+    }
+
+    /**
+     * Returns textual representation of ChmBlockInfo
+     */
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("iniBlock:=" + getIniBlock() + ", ");
+        sb.append("startBlock:=" + getStartBlock() + ", ");
+        sb.append("endBlock:=" + getEndBlock() + ", ");
+        sb.append("startOffset:=" + getStartOffset() + ", ");
+        sb.append("endOffset:=" + getEndOffset()
+                + System.getProperty("line.separator"));
+        return sb.toString();
+    }
+
+    private boolean validateParameters(DirectoryListingEntry dle,
+            int bytesPerBlock, ChmLzxcControlData clcd,
+            ChmBlockInfo chmBlockInfo) {
+        int goodParameter = 0;
+        if (dle != null)
+            ++goodParameter;
+        if (bytesPerBlock > 0)
+            ++goodParameter;
+        if (clcd != null)
+            ++goodParameter;
+        if (chmBlockInfo != null)
+            ++goodParameter;
+        return (goodParameter == 4);
+    }
+
+    public static void main(String[] args) {
+    }
+
+    /**
+     * Returns an initial block index
+     * 
+     * @return int
+     */
+    public int getIniBlock() {
+        return iniBlock;
+    }
+
+    /**
+     * Sets the initial block index
+     * 
+     * @param iniBlock
+     *            - int
+     */
+    private void setIniBlock(int iniBlock) {
+        this.iniBlock = iniBlock;
+    }
+
+    /**
+     * Returns the start block index
+     * 
+     * @return int
+     */
+    public int getStartBlock() {
+        return startBlock;
+    }
+
+    /**
+     * Sets the start block index
+     * 
+     * @param startBlock
+     *            - int
+     */
+    private void setStartBlock(int startBlock) {
+        this.startBlock = startBlock;
+    }
+
+    /**
+     * Returns the end block index
+     * 
+     * @return - int
+     */
+    public int getEndBlock() {
+        return endBlock;
+    }
+
+    /**
+     * Sets the end block index
+     * 
+     * @param endBlock
+     *            - int
+     */
+    private void setEndBlock(int endBlock) {
+        this.endBlock = endBlock;
+    }
+
+    /**
+     * Returns the start offset index
+     * 
+     * @return - int
+     */
+    public int getStartOffset() {
+        return startOffset;
+    }
+
+    /**
+     * Sets the start offset index
+     * 
+     * @param startOffset
+     *            - int
+     */
+    private void setStartOffset(int startOffset) {
+        this.startOffset = startOffset;
+    }
+
+    /**
+     * Returns the end offset index
+     * 
+     * @return - int
+     */
+    public int getEndOffset() {
+        return endOffset;
+    }
+
+    /**
+     * Sets the end offset index
+     * 
+     * @param endOffset
+     *            - int
+     */
+    private void setEndOffset(int endOffset) {
+        this.endOffset = endOffset;
+    }
+
+    public static void setChmBlockInfo(ChmBlockInfo chmBlockInfo) {
+        ChmBlockInfo.chmBlockInfo = chmBlockInfo;
+    }
+
+    public static ChmBlockInfo getChmBlockInfo() {
+        return chmBlockInfo;
+    }
 }

Modified: tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/chm/lzx/ChmLzxBlock.java
URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/chm/lzx/ChmLzxBlock.java?rev=1133554&r1=1133553&r2=1133554&view=diff
==============================================================================
--- tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/chm/lzx/ChmLzxBlock.java (original)
+++ tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/chm/lzx/ChmLzxBlock.java Wed Jun  8 21:00:27 2011
@@ -17,7 +17,6 @@
 package org.apache.tika.parser.chm.lzx;
 
 import java.math.BigInteger;
-import java.util.Arrays;
 
 import org.apache.tika.parser.chm.core.ChmCommons;
 import org.apache.tika.parser.chm.core.ChmCommons.IntelState;
@@ -36,871 +35,875 @@ import org.apache.tika.parser.chm.except
  * 
  */
 public class ChmLzxBlock {
-	private int block_number;
-	private long block_length;
-	private ChmLzxState state;
-	private byte[] content = null;
-	private ChmSection chmSection = null;
-	private int contentLength = 0;
-
-	// trying to find solution for bad blocks ...
-	private int previousBlockType = -1;
-
-	public ChmLzxBlock(int blockNumber, byte[] dataSegment, long blockLength,
-			ChmLzxBlock prevBlock) {
-		try {
-			if (validateConstructorParams(blockNumber, dataSegment, blockLength)) {
-				setBlockNumber(blockNumber);
-
-				if (prevBlock != null
-						&& prevBlock.getState().getBlockLength() > prevBlock
-								.getState().getBlockRemaining())
-					setChmSection(new ChmSection(prevBlock.getContent()));
-				else
-					setChmSection(new ChmSection(dataSegment));
-
-				setBlockLength(blockLength);
-
-				// ============================================
-				// we need to take care of previous context
-				// ============================================
-				checkLzxBlock(prevBlock);
-				setContent((int) blockLength);
-				if (prevBlock == null
-						|| getContent().length < (int) getBlockLength()) {
-					setContent((int) getBlockLength());
-				}
-
-				if (prevBlock != null && prevBlock.getState() != null)
-					previousBlockType = prevBlock.getState().getBlockType();
-
-				try {
-					extractContent();
-				} catch (ChmParsingException e) {
-					// System.err.println(e.getMessage());
-				}
-			} else
-				System.err.println("Check your chm lzx block parameters");
-		} catch (ChmParsingException e) {
-			// TODO: handle exception
-		}
-	}
-
-	protected int getContentLength() {
-		return contentLength;
-	}
-
-	protected void setContentLength(int contentLength) {
-		this.contentLength = contentLength;
-	}
-
-	private ChmSection getChmSection() {
-		return chmSection;
-	}
-
-	private void setChmSection(ChmSection chmSection) {
-		this.chmSection = chmSection;
-	}
-
-	private void assertStateNotNull() {
-		if (getState() == null)
-			throw new ChmParsingException("state is null");
-	}
-
-	private void extractContent() {
-		assertStateNotNull();
-		if (getChmSection().getData() != null) {
-			while (getContentLength() < getBlockLength()) {// && tempStopLoop
-				if (getState() != null && getState().getBlockRemaining() == 0) {
-					if (getState().getHadStarted() == LzxState.NOT_STARTED_DECODING) {
-						getState().setHadStarted(LzxState.STARTED_DECODING);
-						if (getChmSection().getSyncBits(1) == 1) {
-							int intelSizeTemp = (getChmSection()
-									.getSyncBits(16) << 16)
-									+ getChmSection().getSyncBits(16);
-							if (intelSizeTemp >= 0)
-								getState().setIntelFileSize(intelSizeTemp);
-							else
-								getState().setIntelFileSize(0);
-						}
-					}
-					getState().setBlockType(getChmSection().getSyncBits(3));
-					getState().setBlockLength(
-							(getChmSection().getSyncBits(16) << 8)
-									+ getChmSection().getSyncBits(8));
-					getState().setBlockRemaining(getState().getBlockLength());
-
-					// ----------------------------------------
-					// Trying to handle 3 - 7 block types
-					// ----------------------------------------
-					if (getState().getBlockType() > 3) {
-						if (previousBlockType >= 0 && previousBlockType < 3)
-							getState().setBlockType(previousBlockType);
-					}
-
-					switch (getState().getBlockType()) {
-					case ChmCommons.ALIGNED_OFFSET:
-						createAlignedTreeTable();
-					case ChmCommons.VERBATIM:
-						/* Creates mainTreeTable */
-						createMainTreeTable();
-						createLengthTreeTable();
-						if (getState().getMainTreeLengtsTable()[0xe8] != 0)
-							getState().setIntelState(IntelState.STARTED);
-						break;
-					case ChmCommons.UNCOMPRESSED:
-						getState().setIntelState(IntelState.STARTED);
-						if (getChmSection().getTotal() > 16)
-							getChmSection().setSwath(
-									getChmSection().getSwath() - 1);
-						getState().setR0(
-								(new BigInteger(getChmSection()
-										.reverseByteOrder(
-												getChmSection().unmarshalBytes(
-														4))).longValue()));
-						getState().setR1(
-								(new BigInteger(getChmSection()
-										.reverseByteOrder(
-												getChmSection().unmarshalBytes(
-														4))).longValue()));
-						getState().setR2(
-								(new BigInteger(getChmSection()
-										.reverseByteOrder(
-												getChmSection().unmarshalBytes(
-														4))).longValue()));
-						break;
-					default:
-						break;
-					}
-				}
-
-				int tempLen;
-
-				if (getContentLength() + getState().getBlockRemaining() > getBlockLength()) {
-					getState().setBlockRemaining(
-							getContentLength() + getState().getBlockRemaining()
-									- (int) getBlockLength());
-					tempLen = (int) getBlockLength();
-				} else {
-					tempLen = getContentLength()
-							+ getState().getBlockRemaining();
-					getState().setBlockRemaining(0);
-				}
-
-				switch (getState().getBlockType()) {
-				case ChmCommons.ALIGNED_OFFSET:
-					// if(prevblock.lzxState.length>prevblock.lzxState.remaining)
-					decompressAlignedBlock(tempLen, getChmSection().getData());// prevcontext
-					break;
-				case ChmCommons.VERBATIM:
-					decompressVerbatimBlock(tempLen, getChmSection().getData());
-					break;
-				case ChmCommons.UNCOMPRESSED:
-					decompressUncompressedBlock(tempLen, getChmSection()
-							.getData());
-					break;
-				}
-				getState().increaseFramesRead();
-				if ((getState().getFramesRead() < 32768)
-						&& getState().getIntelFileSize() != 0)
-					intelE8Decoding();
-			}
-		}
-	}
-
-	protected void intelE8Decoding() {
-		if (getBlockLength() <= ChmConstants.LZX_PRETREE_TABLEBITS
-				|| (getState().getIntelState() == IntelState.NOT_STARTED)) {
-			getState().setBlockRemaining(
-					getState().getBlockRemaining() - (int) getBlockLength());
-		} else {
-			long curpos = getState().getBlockRemaining();
-			getState().setBlockRemaining(
-					getState().getBlockRemaining() - (int) getBlockLength());
-			int i = 0;
-			while (i < getBlockLength() - 10) {
-				if (content[i] != 0xe8) {
-					i++;
-					continue;
-				}
-				byte[] b = new byte[4];
-				b[0] = getContent()[i + 3];
-				b[1] = getContent()[i + 2];
-				b[2] = getContent()[i + 1];
-				b[3] = getContent()[i + 0];
-				long absoff = (new BigInteger(b)).longValue();
-				if ((absoff >= -curpos)
-						&& (absoff < getState().getIntelFileSize())) {
-					long reloff = (absoff >= 0) ? absoff - curpos : absoff
-							+ getState().getIntelFileSize();
-					getContent()[i + 0] = (byte) reloff;
-					getContent()[i + 1] = (byte) (reloff >>> 8);
-					getContent()[i + 2] = (byte) (reloff >>> 16);
-					getContent()[i + 3] = (byte) (reloff >>> 24);
-				}
-				i += 4;
-				curpos += 5;
-			}
-		}
-	}
-
-	private short[] createPreLenTable() {
-		short[] tmp = new short[ChmConstants.LZX_PRETREE_MAXSYMBOLS];
-		for (int i = 0; i < ChmConstants.LZX_PRETREE_MAXSYMBOLS; i++) {
-			tmp[i] = (short) getChmSection().getSyncBits(
-					ChmConstants.LZX_PRETREE_NUM_ELEMENTS_BITS);
-		}
-		return tmp;
-	}
-
-	private void createLengthTreeTable() {
-		short[] prelentable = createPreLenTable();
-
-		if (prelentable == null) {
-			throw new ChmParsingException("pretreetable is null");
-		}
-
-		short[] pretreetable = createTreeTable2(prelentable,
-				(1 << ChmConstants.LZX_PRETREE_TABLEBITS)
-						+ (ChmConstants.LZX_PRETREE_MAXSYMBOLS << 1),
-				ChmConstants.LZX_PRETREE_TABLEBITS,
-				ChmConstants.LZX_PRETREE_MAXSYMBOLS);
-
-		if (pretreetable == null) {
-			throw new ChmParsingException("pretreetable is null");
-		}
-
-		createLengthTreeLenTable(0, ChmConstants.LZX_NUM_SECONDARY_LENGTHS,
-				pretreetable, prelentable);
-
-		getState().setLengthTreeTable(
-				createTreeTable2(getState().getLengthTreeLengtsTable(),
-						(1 << ChmConstants.LZX_MAINTREE_TABLEBITS)
-								+ (ChmConstants.LZX_LENGTH_MAXSYMBOLS << 1),
-						ChmConstants.LZX_MAINTREE_TABLEBITS,
-						ChmConstants.LZX_NUM_SECONDARY_LENGTHS));
-	}
-
-	public void decompressUncompressedBlock(int len, byte[] prevcontent) {
-		if (getContentLength() + getState().getBlockRemaining() <= getBlockLength()) {
-			for (int i = getContentLength(); i < (getContentLength() + getState()
-					.getBlockRemaining()); i++)
-				content[i] = getChmSection().getByte();
-
-			setContentLength(getContentLength()
-					+ getState().getBlockRemaining());
-			getState().setBlockRemaining(0);
-		} else {
-			for (int i = getContentLength(); i < getBlockLength(); i++)
-				content[i] = getChmSection().getByte();
-			getState().setBlockRemaining(
-					(int) getBlockLength() - getContentLength());// = blockLen -
-																	// contentlen;
-			setContentLength((int) getBlockLength());
-		}
-	}
-
-	public void decompressAlignedBlock(int len, byte[] prevcontent) {
-
-		if ((getChmSection() == null) || (getState() == null)
-				|| (getState().getMainTreeTable() == null))
-			throw new ChmParsingException("chm section is null");
-
-		short s;
-		int x, i, border;
-		int matchlen = 0, matchfooter = 0, extra, rundest, runsrc;
-		int matchoffset = 0;
-		for (i = getContentLength(); i < len; i++) {
-			/* new code */
-			border = getChmSection().getDesyncBits(
-					ChmConstants.LZX_MAINTREE_TABLEBITS, 0);
-			if (border >= getState().mainTreeTable.length)
-				break;
-			/* end new code */
-			s = getState().mainTreeTable[getChmSection().getDesyncBits(
-					ChmConstants.LZX_MAINTREE_TABLEBITS, 0)];
-			if (s >= getState().getMainTreeElements()) {
-				x = ChmConstants.LZX_MAINTREE_TABLEBITS;
-				do {
-					x++;
-					s <<= 1;
-					s += getChmSection().checkBit(x);
-				} while ((s = getState().mainTreeTable[s]) >= getState()
-						.getMainTreeElements());
-			}
-			getChmSection().getSyncBits(getState().mainTreeTable[s]);
-			if (s < ChmConstants.LZX_NUM_CHARS) {
-				content[i] = (byte) s;
-			} else {
-				s -= ChmConstants.LZX_NUM_CHARS;
-				matchlen = s & ChmConstants.LZX_NUM_PRIMARY_LENGTHS;
-				if (matchlen == ChmConstants.LZX_NUM_PRIMARY_LENGTHS) {
-					matchfooter = getState().lengthTreeTable[getChmSection()
-							.getDesyncBits(ChmConstants.LZX_MAINTREE_TABLEBITS,
-									0)];
-					if (matchfooter >= ChmConstants.LZX_MAINTREE_TABLEBITS) {
-						x = ChmConstants.LZX_MAINTREE_TABLEBITS;
-						do {
-							x++;
-							matchfooter <<= 1;
-							matchfooter += getChmSection().checkBit(x);
-						} while ((matchfooter = getState().lengthTreeTable[matchfooter]) >= ChmConstants.LZX_NUM_SECONDARY_LENGTHS);
-					}
-					getChmSection().getSyncBits(
-							getState().lengthTreeLengtsTable[matchfooter]);
-					matchlen += matchfooter;
-				}
-				matchlen += ChmConstants.LZX_MIN_MATCH;
-				matchoffset = s >>> 3;
-				if (matchoffset > 2) {
-					extra = ChmConstants.EXTRA_BITS[matchoffset];
-					matchoffset = (ChmConstants.POSITION_BASE[matchoffset] - 2);
-					if (extra > 3) {
-						extra -= 3;
-						long l = getChmSection().getSyncBits(extra);
-						matchoffset += (l << 3);
-						int g = getChmSection().getDesyncBits(
-								ChmConstants.LZX_NUM_PRIMARY_LENGTHS, 0);
-						int t = getState().getAlignedTreeTable()[g];
-						if (t >= getState().getMainTreeElements()) {
-							x = ChmConstants.LZX_MAINTREE_TABLEBITS;
-							do {
-								x++;
-								t <<= 1;
-								t += getChmSection().checkBit(x);
-							} while ((t = getState().getAlignedTreeTable()[t]) >= getState()
-									.getMainTreeElements());
-						}
-						getChmSection().getSyncBits(
-								getState().getAlignedTreeTable()[t]);
-						matchoffset += t;
-					} else if (extra == 3) {
-						int g = (int) getChmSection().getDesyncBits(
-								ChmConstants.LZX_NUM_PRIMARY_LENGTHS, 0);
-						int t = getState().getAlignedTreeTable()[g];
-						if (t >= getState().getMainTreeElements()) {
-							x = ChmConstants.LZX_MAINTREE_TABLEBITS;
-							do {
-								x++;
-								t <<= 1;
-								t += getChmSection().checkBit(x);
-							} while ((t = getState().getAlignedTreeTable()[t]) >= getState()
-									.getMainTreeElements());
-						}
-						getChmSection().getSyncBits(
-								getState().getAlignedTreeTable()[t]);
-						matchoffset += t;
-					} else if (extra > 0) {
-						long l = getChmSection().getSyncBits(extra);
-						matchoffset += l;
-					} else
-						matchoffset = 1;
-					getState().setR2(getState().getR1());
-					getState().setR1(getState().getR0());
-					getState().setR0(matchoffset);
-				} else if (matchoffset == 0) {
-					matchoffset = (int) getState().getR0();
-				} else if (matchoffset == 1) {
-					matchoffset = (int) getState().getR1();
-					getState().setR1(getState().getR0());
-					getState().setR0(matchoffset);
-				} else /** match_offset == 2 */
-				{
-					matchoffset = (int) getState().getR2();
-					getState().setR2(getState().getR0());
-					getState().setR0(matchoffset);
-				}
-				rundest = i;
-				runsrc = rundest - matchoffset;
-				i += (matchlen - 1);
-				if (i > len)
-					break;
-
-				if (runsrc < 0) {
-					if (matchlen + runsrc <= 0) {
-						runsrc = prevcontent.length + runsrc;
-						while (matchlen-- > 0)
-							content[rundest++] = prevcontent[runsrc++];
-					} else {
-						runsrc = prevcontent.length + runsrc;
-						while (runsrc < prevcontent.length)
-							content[rundest++] = prevcontent[runsrc++];
-						matchlen = matchlen + runsrc - prevcontent.length;
-						runsrc = 0;
-						while (matchlen-- > 0)
-							content[rundest++] = content[runsrc++];
-					}
-
-				} else {
-					/* copies any wrappes around source data */
-					while ((runsrc < 0) && (matchlen-- > 0)) {
-						content[rundest++] = content[(int) (runsrc + getBlockLength())];
-						runsrc++;
-					}
-					/* copies match data - no worries about destination wraps */
-					while (matchlen-- > 0)
-						content[rundest++] = content[runsrc++];
-				}
-			}
-		}
-		setContentLength(len);
-	}
-
-	private void assertShortArrayNotNull(short[] array) {
-		if (array == null)
-			throw new ChmParsingException("short[] is null");
-	}
-
-	private void decompressVerbatimBlock(int len, byte[] prevcontent) {
-		short s;
-		int x, i;
-		int matchlen = 0, matchfooter = 0, extra, rundest, runsrc;
-		int matchoffset = 0;
-		for (i = getContentLength(); i < len; i++) {
-			int f = (int) getChmSection().getDesyncBits(
-					ChmConstants.LZX_MAINTREE_TABLEBITS, 0);
-			assertShortArrayNotNull(getState().getMainTreeTable());
-			s = getState().getMainTreeTable()[f];
-			if (s >= ChmConstants.LZX_MAIN_MAXSYMBOLS) {
-				x = ChmConstants.LZX_MAINTREE_TABLEBITS;
-				do {
-					x++;
-					s <<= 1;
-					s += getChmSection().checkBit(x);
-				} while ((s = getState().getMainTreeTable()[s]) >= ChmConstants.LZX_MAIN_MAXSYMBOLS);
-			}
-			getChmSection().getSyncBits(getState().getMainTreeLengtsTable()[s]);
-			if (s < ChmConstants.LZX_NUM_CHARS) {
-				content[i] = (byte) s;
-			} else {
-				s -= ChmConstants.LZX_NUM_CHARS;
-				matchlen = s & ChmConstants.LZX_NUM_PRIMARY_LENGTHS;
-				if (matchlen == ChmConstants.LZX_NUM_PRIMARY_LENGTHS) {
-					matchfooter = getState().getLengthTreeTable()[(int) getChmSection()
-							.getDesyncBits(ChmConstants.LZX_LENGTH_TABLEBITS, 0)];
-					if (matchfooter >= ChmConstants.LZX_NUM_SECONDARY_LENGTHS) {
-						x = ChmConstants.LZX_LENGTH_TABLEBITS;
-						do {
-							x++;
-							matchfooter <<= 1;
-							matchfooter += getChmSection().checkBit(x);
-						} while ((matchfooter = getState().getLengthTreeTable()[matchfooter]) >= ChmConstants.LZX_NUM_SECONDARY_LENGTHS);
-					}
-					getChmSection().getSyncBits(
-							getState().getLengthTreeLengtsTable()[matchfooter]);
-					matchlen += matchfooter;
-				}
-				matchlen += ChmConstants.LZX_MIN_MATCH;
-				// shorter than 2
-				matchoffset = s >>> 3;
-				if (matchoffset > 2) {
-					if (matchoffset != 3) { // should get other bits to retrieve
-											// offset
-						extra = ChmConstants.EXTRA_BITS[matchoffset];
-						long l = getChmSection().getSyncBits(extra);
-						matchoffset = (int) (ChmConstants.POSITION_BASE[matchoffset] - 2 + l);
-					} else {
-						matchoffset = 1;
-					}
-					getState().setR2(getState().getR1());
-					getState().setR1(getState().getR0());
-					getState().setR0(matchoffset);
-				} else if (matchoffset == 0) {
-					matchoffset = (int) getState().getR0();
-				} else if (matchoffset == 1) {
-					matchoffset = (int) getState().getR1();
-					getState().setR1(getState().getR0());
-					getState().setR0(matchoffset);
-				} else /* match_offset == 2 */
-				{
-					matchoffset = (int) getState().getR2();
-					getState().setR2(getState().getR0());
-					getState().setR0(matchoffset);
-				}
-				rundest = i;
-				runsrc = rundest - matchoffset;
-				i += (matchlen - 1);
-				if (i > len)
-					break;
-				if (runsrc < 0) {
-					if (matchlen + runsrc <= 0) {
-						runsrc = prevcontent.length + runsrc;
-						while ((matchlen-- > 0) && (prevcontent != null)
-								&& ((runsrc + 1) > 0))
-							if ((rundest < content.length)
-									&& (runsrc < content.length))
-								content[rundest++] = prevcontent[runsrc++];
-					} else {
-						runsrc = prevcontent.length + runsrc;
-						while (runsrc < prevcontent.length)
-							if ((rundest < content.length)
-									&& (runsrc < content.length))
-								content[rundest++] = prevcontent[runsrc++];
-						matchlen = matchlen + runsrc - prevcontent.length;
-						runsrc = 0;
-						while (matchlen-- > 0)
-							content[rundest++] = content[runsrc++];
-					}
-
-				} else {
-					/* copies any wrapped source data */
-					while ((runsrc < 0) && (matchlen-- > 0)) {
-						content[rundest++] = content[(int) (runsrc + getBlockLength())];
-						runsrc++;
-					}
-					/* copies match data - no worries about destination wraps */
-					while (matchlen-- > 0) {
-						if ((rundest < content.length)
-								&& (runsrc < content.length))
-							content[rundest++] = content[runsrc++];
-					}
-				}
-			}
-		}
-		setContentLength(len);
-	}
-
-	private void createLengthTreeLenTable(int offset, int tablelen,
-			short[] pretreetable, short[] prelentable) {
-		if (prelentable == null || getChmSection() == null
-				|| pretreetable == null || prelentable == null)
-			throw new ChmParsingException("is null");
-
-		int i = offset; // represents offset
-		int z, y, x;// local counters
-		while (i < tablelen) {
-			z = pretreetable[(int) getChmSection().getDesyncBits(
-					ChmConstants.LZX_PRETREE_TABLEBITS, 0)];
-			if (z >= ChmConstants.LZX_PRETREE_NUM_ELEMENTS) {// 1 bug, should be
-																// 20
-				x = ChmConstants.LZX_PRETREE_TABLEBITS;
-				do {
-					x++;
-					z <<= 1;
-					z += getChmSection().checkBit(x);
-				} while ((z = pretreetable[z]) >= ChmConstants.LZX_PRETREE_NUM_ELEMENTS);
-			}
-			getChmSection().getSyncBits(prelentable[z]);
-			if (z < 17) {
-				z = getState().getLengthTreeLengtsTable()[i] - z;
-				if (z < 0)
-					z = z + 17;
-				getState().getLengthTreeLengtsTable()[i] = (short) z;
-				i++;
-			} else if (z == 17) {
-				y = (int) getChmSection().getSyncBits(4);
-				y += 4;
-				for (int j = 0; j < y; j++)
-					if (i < getState().getLengthTreeLengtsTable().length)
-						getState().getLengthTreeLengtsTable()[i++] = 0;
-			} else if (z == 18) {
-				y = (int) getChmSection().getSyncBits(5);
-				y += 20;
-				for (int j = 0; j < y; j++)
-					if (i < getState().getLengthTreeLengtsTable().length)
-						getState().getLengthTreeLengtsTable()[i++] = 0;
-			} else if (z == 19) {
-				y = getChmSection().getSyncBits(1);
-				y += 4;
-				z = pretreetable[(int) getChmSection().getDesyncBits(
-						ChmConstants.LZX_PRETREE_TABLEBITS, 0)];
-				if (z >= ChmConstants.LZX_PRETREE_NUM_ELEMENTS) {// 20
-					x = ChmConstants.LZX_PRETREE_TABLEBITS;// 6
-					do {
-						x++;
-						z <<= 1;
-						z += getChmSection().checkBit(x);
-					} while ((z = pretreetable[z]) >= ChmConstants.LZX_MAINTREE_TABLEBITS);
-				}
-				getChmSection().getSyncBits(prelentable[z]);
-				z = getState().getLengthTreeLengtsTable()[i] - z;
-				if (z < 0)
-					z = z + 17;
-				for (int j = 0; j < y; j++)
-					getState().getLengthTreeLengtsTable()[i++] = (short) z;
-			}
-		}
-	}
-
-	private void createMainTreeTable() {
-		short[] prelentable = createPreLenTable();
-		short[] pretreetable = createTreeTable2(prelentable,
-				(1 << ChmConstants.LZX_PRETREE_TABLEBITS)
-						+ (ChmConstants.LZX_PRETREE_MAXSYMBOLS << 1),
-				ChmConstants.LZX_PRETREE_TABLEBITS,
-				ChmConstants.LZX_PRETREE_MAXSYMBOLS);
-		createMainTreeLenTable(0, ChmConstants.LZX_NUM_CHARS, pretreetable,
-				prelentable);
-		prelentable = createPreLenTable();
-		pretreetable = createTreeTable2(prelentable,
-				(1 << ChmConstants.LZX_PRETREE_TABLEBITS)
-						+ (ChmConstants.LZX_PRETREE_MAXSYMBOLS << 1),
-				ChmConstants.LZX_PRETREE_TABLEBITS,
-				ChmConstants.LZX_PRETREE_MAXSYMBOLS);
-		createMainTreeLenTable(ChmConstants.LZX_NUM_CHARS,
-				getState().mainTreeLengtsTable.length, pretreetable,
-				prelentable);
-
-		getState().setMainTreeTable(
-				createTreeTable2(getState().mainTreeLengtsTable,
-						(1 << ChmConstants.LZX_MAINTREE_TABLEBITS)
-								+ (ChmConstants.LZX_MAINTREE_MAXSYMBOLS << 1),
-						ChmConstants.LZX_MAINTREE_TABLEBITS, getState()
-								.getMainTreeElements()));
-
-	}
-
-	private void createMainTreeLenTable(int offset, int tablelen,
-			short[] pretreetable, short[] prelentable) {
-		if (pretreetable == null)
-			throw new ChmParsingException("pretreetable is null");
-		int i = offset;
-		int z, y, x;
-		while (i < tablelen) {
-			int f = getChmSection().getDesyncBits(
-					ChmConstants.LZX_PRETREE_TABLEBITS, 0);
-			z = pretreetable[f];
-			if (z >= ChmConstants.LZX_PRETREE_MAXSYMBOLS) {
-				x = ChmConstants.LZX_PRETREE_TABLEBITS;
-				do {
-					x++;
-					z <<= 1;
-					z += getChmSection().checkBit(x);
-				} while ((z = pretreetable[z]) >= ChmConstants.LZX_PRETREE_MAXSYMBOLS);
-			}
-			getChmSection().getSyncBits(prelentable[z]);
-			if (z < 17) {
-				z = getState().getMainTreeLengtsTable()[i] - z;
-				if (z < 0)
-					z = z + 17;
-				getState().mainTreeLengtsTable[i] = (short) z;
-				i++;
-			} else if (z == 17) {
-				y = getChmSection().getSyncBits(4);
-				y += 4;
-				for (int j = 0; j < y; j++) {
-					assertInRange(getState().getMainTreeLengtsTable(), i);
-					getState().mainTreeLengtsTable[i++] = 0;
-				}
-			} else if (z == 18) {
-				y = getChmSection().getSyncBits(5);
-				y += 20;
-				for (int j = 0; j < y; j++) {
-					assertInRange(getState().getMainTreeLengtsTable(), i);
-					getState().mainTreeLengtsTable[i++] = 0;
-				}
-			} else if (z == 19) {
-				y = getChmSection().getSyncBits(1);
-				y += 4;
-				z = pretreetable[getChmSection().getDesyncBits(
-						ChmConstants.LZX_PRETREE_TABLEBITS, 0)];
-				if (z >= ChmConstants.LZX_PRETREE_MAXSYMBOLS) {
-					x = ChmConstants.LZX_PRETREE_TABLEBITS;
-					do {
-						x++;
-						z <<= 1;
-						z += getChmSection().checkBit(x);
-					} while ((z = pretreetable[z]) >= ChmConstants.LZX_PRETREE_MAXSYMBOLS);
-				}
-				getChmSection().getSyncBits(prelentable[z]);
-				z = getState().mainTreeLengtsTable[i] - z;
-				if (z < 0)
-					z = z + 17;
-				for (int j = 0; j < y; j++)
-					if (i < getState().getMainTreeLengtsTable().length)
-						getState().mainTreeLengtsTable[i++] = (short) z;
-			}
-		}
-	}
-
-	private void assertInRange(short[] array, int index) {
-		if (index >= array.length)
-			throw new ChmParsingException(index + " is bigger than "
-					+ array.length);
-	}
-
-	private short[] createAlignedLenTable() {
-		int tablelen = ChmConstants.LZX_BLOCKTYPE_UNCOMPRESSED;
-		int bits = ChmConstants.LZX_BLOCKTYPE_UNCOMPRESSED;
-		short[] tmp = new short[tablelen];
-		for (int i = 0; i < tablelen; i++) {
-			tmp[i] = (short) getChmSection().getSyncBits(bits);
-		}
-		return tmp;
-	}
-
-	private void createAlignedTreeTable() {
-		getState().setAlignedLenTable(createAlignedLenTable());
-		getState().setAlignedLenTable(
-				createTreeTable2(getState().getAlignedLenTable(),
-						(1 << ChmConstants.LZX_NUM_PRIMARY_LENGTHS)
-								+ (ChmConstants.LZX_ALIGNED_MAXSYMBOLS << 1),
-						ChmConstants.LZX_NUM_PRIMARY_LENGTHS,
-						ChmConstants.LZX_ALIGNED_MAXSYMBOLS));
-	}
-
-	private short[] createTreeTable2(short[] lentable, int tablelen, int bits,
-			int maxsymbol) {
-		short[] tmp = new short[tablelen];
-		short sym;
-		int leaf;
-		int bit_num = 1;
-		long fill;
-		int pos = 0;
-		/* the current position in the decode table */
-		long table_mask = (1 << bits);
-		long bit_mask = (table_mask >> 1);
-		long next_symbol = bit_mask;
-
-		/* fills entries for short codes for a direct mapping */
-		while (bit_num <= bits) {
-			for (sym = 0; sym < maxsymbol; sym++) {
-				if (lentable.length > sym && lentable[sym] == bit_num) {
-					leaf = pos;// pos=0
-
-					if ((pos += bit_mask) > table_mask)
-						return null;
-
-					fill = bit_mask;
-					while (fill-- > 0)
-						tmp[leaf++] = sym;
-				}
-			}
-			bit_mask >>= 1;
-			bit_num++;
-		}
-
-		/* if there are any codes longer than nbits */
-		if (pos != table_mask) {
-			/* clears the remainder of the table */
-			for (leaf = pos; leaf < table_mask; leaf++)
-				tmp[leaf] = 0;
-
-			/* gives ourselves room for codes to grow by up to 16 more bits */
-			pos <<= 16;
-			table_mask <<= 16;
-			bit_mask = 1 << 15;
-
-			while (bit_num <= 16) {
-				for (sym = 0; sym < maxsymbol; sym++) {
-					if ((lentable.length > sym) && (lentable[sym] == bit_num)) {
-						leaf = pos >> 16;
-						for (fill = 0; fill < bit_num - bits; fill++) {
-							/*
-							 * if this path hasn't been taken yet, 'allocate'
-							 * two entries
-							 */
-							if (tmp[leaf] == 0) {
-								if (((next_symbol << 1) + 1) < tmp.length) {
-									tmp[(int) (next_symbol << 1)] = 0;
-									tmp[(int) (next_symbol << 1) + 1] = 0;
-									tmp[leaf] = (short) next_symbol++;
-								}
-
-							}
-							/*
-							 * follows the path and select either left or right
-							 * for next bit
-							 */
-							leaf = tmp[leaf] << 1;
-							if (((pos >> (15 - fill)) & 1) != 0)
-								leaf++;
-						}
-						tmp[leaf] = sym;
-
-						if ((pos += bit_mask) > table_mask)
-							return null;
-						/* table overflow */
-					} else {
-						// return null;
-					}
-				}
-				bit_mask >>= 1;
-				bit_num++;
-			}
-		}
-
-		/* is it full table? */
-		if (pos == table_mask)
-			return tmp;
-
-		return tmp;
-	}
-
-	public byte[] getContent() {
-		return content;
-	}
-
-	public byte[] getContent(int startOffset, int endOffset) {
-		int length = endOffset - startOffset;
-		return (getContent() != null) ? Arrays.copyOfRange(getContent(),
-				startOffset, (startOffset + length)) : new byte[1];
-	}
-
-	public byte[] getContent(int start) {
-		return (getContent() != null) ? Arrays.copyOfRange(getContent(), start,
-				(getContent().length + start)) : new byte[1];
-	}
-
-	private void setContent(int contentLength) {
-		this.content = new byte[contentLength];
-	}
-
-	private void checkLzxBlock(ChmLzxBlock chmPrevLzxBlock) {
-		if (chmPrevLzxBlock == null && getBlockLength() < Integer.MAX_VALUE)
-			setState(new ChmLzxState((int) getBlockLength()));
-		else
-			setState(chmPrevLzxBlock.getState());
-	}
-
-	private boolean validateConstructorParams(int blockNumber,
-			byte[] dataSegment, long blockLength) {
-		int goodParameter = 0;
-		if (blockNumber >= 0)
-			++goodParameter;
-		else
-			throw new ChmParsingException("block number should be possitive");
-		if (dataSegment != null && dataSegment.length > 0)
-			++goodParameter;
-		else
-			throw new ChmParsingException("data segment should not be null");
-		if (blockLength > 0)
-			++goodParameter;
-		else
-			throw new ChmParsingException(
-					"block length should be more than zero");
-		return (goodParameter == 3);
-	}
-
-	public int getBlockNumber() {
-		return block_number;
-	}
-
-	private void setBlockNumber(int block_number) {
-		this.block_number = block_number;
-	}
-
-	private long getBlockLength() {
-		return block_length;
-	}
-
-	private void setBlockLength(long block_length) {
-		this.block_length = block_length;
-	}
-
-	public ChmLzxState getState() {
-		return state;
-	}
-
-	private void setState(ChmLzxState state) {
-		this.state = state;
-	}
-
-	/**
-	 * @param args
-	 */
-	public static void main(String[] args) {
-		// TODO Auto-generated method stub
+    private int block_number;
+    private long block_length;
+    private ChmLzxState state;
+    private byte[] content = null;
+    private ChmSection chmSection = null;
+    private int contentLength = 0;
+
+    // trying to find solution for bad blocks ...
+    private int previousBlockType = -1;
+
+    public ChmLzxBlock(int blockNumber, byte[] dataSegment, long blockLength,
+            ChmLzxBlock prevBlock) {
+        try {
+            if (validateConstructorParams(blockNumber, dataSegment, blockLength)) {
+                setBlockNumber(blockNumber);
+
+                if (prevBlock != null
+                        && prevBlock.getState().getBlockLength() > prevBlock
+                                .getState().getBlockRemaining())
+                    setChmSection(new ChmSection(prevBlock.getContent()));
+                else
+                    setChmSection(new ChmSection(dataSegment));
+
+                setBlockLength(blockLength);
+
+                // ============================================
+                // we need to take care of previous context
+                // ============================================
+                checkLzxBlock(prevBlock);
+                setContent((int) blockLength);
+                if (prevBlock == null
+                        || getContent().length < (int) getBlockLength()) {
+                    setContent((int) getBlockLength());
+                }
+
+                if (prevBlock != null && prevBlock.getState() != null)
+                    previousBlockType = prevBlock.getState().getBlockType();
+
+                try {
+                    extractContent();
+                } catch (ChmParsingException e) {
+                    // System.err.println(e.getMessage());
+                }
+            } else
+                System.err.println("Check your chm lzx block parameters");
+        } catch (ChmParsingException e) {
+            // TODO: handle exception
+        }
+    }
+
+    protected int getContentLength() {
+        return contentLength;
+    }
+
+    protected void setContentLength(int contentLength) {
+        this.contentLength = contentLength;
+    }
+
+    private ChmSection getChmSection() {
+        return chmSection;
+    }
+
+    private void setChmSection(ChmSection chmSection) {
+        this.chmSection = chmSection;
+    }
+
+    private void assertStateNotNull() {
+        if (getState() == null)
+            throw new ChmParsingException("state is null");
+    }
+
+    private void extractContent() {
+        assertStateNotNull();
+        if (getChmSection().getData() != null) {
+            while (getContentLength() < getBlockLength()) {// && tempStopLoop
+                if (getState() != null && getState().getBlockRemaining() == 0) {
+                    if (getState().getHadStarted() == LzxState.NOT_STARTED_DECODING) {
+                        getState().setHadStarted(LzxState.STARTED_DECODING);
+                        if (getChmSection().getSyncBits(1) == 1) {
+                            int intelSizeTemp = (getChmSection()
+                                    .getSyncBits(16) << 16)
+                                    + getChmSection().getSyncBits(16);
+                            if (intelSizeTemp >= 0)
+                                getState().setIntelFileSize(intelSizeTemp);
+                            else
+                                getState().setIntelFileSize(0);
+                        }
+                    }
+                    getState().setBlockType(getChmSection().getSyncBits(3));
+                    getState().setBlockLength(
+                            (getChmSection().getSyncBits(16) << 8)
+                                    + getChmSection().getSyncBits(8));
+                    getState().setBlockRemaining(getState().getBlockLength());
+
+                    // ----------------------------------------
+                    // Trying to handle 3 - 7 block types
+                    // ----------------------------------------
+                    if (getState().getBlockType() > 3) {
+                        if (previousBlockType >= 0 && previousBlockType < 3)
+                            getState().setBlockType(previousBlockType);
+                    }
+
+                    switch (getState().getBlockType()) {
+                    case ChmCommons.ALIGNED_OFFSET:
+                        createAlignedTreeTable();
+                    case ChmCommons.VERBATIM:
+                        /* Creates mainTreeTable */
+                        createMainTreeTable();
+                        createLengthTreeTable();
+                        if (getState().getMainTreeLengtsTable()[0xe8] != 0)
+                            getState().setIntelState(IntelState.STARTED);
+                        break;
+                    case ChmCommons.UNCOMPRESSED:
+                        getState().setIntelState(IntelState.STARTED);
+                        if (getChmSection().getTotal() > 16)
+                            getChmSection().setSwath(
+                                    getChmSection().getSwath() - 1);
+                        getState().setR0(
+                                (new BigInteger(getChmSection()
+                                        .reverseByteOrder(
+                                                getChmSection().unmarshalBytes(
+                                                        4))).longValue()));
+                        getState().setR1(
+                                (new BigInteger(getChmSection()
+                                        .reverseByteOrder(
+                                                getChmSection().unmarshalBytes(
+                                                        4))).longValue()));
+                        getState().setR2(
+                                (new BigInteger(getChmSection()
+                                        .reverseByteOrder(
+                                                getChmSection().unmarshalBytes(
+                                                        4))).longValue()));
+                        break;
+                    default:
+                        break;
+                    }
+                }
+
+                int tempLen;
+
+                if (getContentLength() + getState().getBlockRemaining() > getBlockLength()) {
+                    getState().setBlockRemaining(
+                            getContentLength() + getState().getBlockRemaining()
+                                    - (int) getBlockLength());
+                    tempLen = (int) getBlockLength();
+                } else {
+                    tempLen = getContentLength()
+                            + getState().getBlockRemaining();
+                    getState().setBlockRemaining(0);
+                }
+
+                switch (getState().getBlockType()) {
+                case ChmCommons.ALIGNED_OFFSET:
+                    // if(prevblock.lzxState.length>prevblock.lzxState.remaining)
+                    decompressAlignedBlock(tempLen, getChmSection().getData());// prevcontext
+                    break;
+                case ChmCommons.VERBATIM:
+                    decompressVerbatimBlock(tempLen, getChmSection().getData());
+                    break;
+                case ChmCommons.UNCOMPRESSED:
+                    decompressUncompressedBlock(tempLen, getChmSection()
+                            .getData());
+                    break;
+                }
+                getState().increaseFramesRead();
+                if ((getState().getFramesRead() < 32768)
+                        && getState().getIntelFileSize() != 0)
+                    intelE8Decoding();
+            }
+        }
+    }
+
+    protected void intelE8Decoding() {
+        if (getBlockLength() <= ChmConstants.LZX_PRETREE_TABLEBITS
+                || (getState().getIntelState() == IntelState.NOT_STARTED)) {
+            getState().setBlockRemaining(
+                    getState().getBlockRemaining() - (int) getBlockLength());
+        } else {
+            long curpos = getState().getBlockRemaining();
+            getState().setBlockRemaining(
+                    getState().getBlockRemaining() - (int) getBlockLength());
+            int i = 0;
+            while (i < getBlockLength() - 10) {
+                if (content[i] != 0xe8) {
+                    i++;
+                    continue;
+                }
+                byte[] b = new byte[4];
+                b[0] = getContent()[i + 3];
+                b[1] = getContent()[i + 2];
+                b[2] = getContent()[i + 1];
+                b[3] = getContent()[i + 0];
+                long absoff = (new BigInteger(b)).longValue();
+                if ((absoff >= -curpos)
+                        && (absoff < getState().getIntelFileSize())) {
+                    long reloff = (absoff >= 0) ? absoff - curpos : absoff
+                            + getState().getIntelFileSize();
+                    getContent()[i + 0] = (byte) reloff;
+                    getContent()[i + 1] = (byte) (reloff >>> 8);
+                    getContent()[i + 2] = (byte) (reloff >>> 16);
+                    getContent()[i + 3] = (byte) (reloff >>> 24);
+                }
+                i += 4;
+                curpos += 5;
+            }
+        }
+    }
+
+    private short[] createPreLenTable() {
+        short[] tmp = new short[ChmConstants.LZX_PRETREE_MAXSYMBOLS];
+        for (int i = 0; i < ChmConstants.LZX_PRETREE_MAXSYMBOLS; i++) {
+            tmp[i] = (short) getChmSection().getSyncBits(
+                    ChmConstants.LZX_PRETREE_NUM_ELEMENTS_BITS);
+        }
+        return tmp;
+    }
+
+    private void createLengthTreeTable() {
+        short[] prelentable = createPreLenTable();
+
+        if (prelentable == null) {
+            throw new ChmParsingException("pretreetable is null");
+        }
+
+        short[] pretreetable = createTreeTable2(prelentable,
+                (1 << ChmConstants.LZX_PRETREE_TABLEBITS)
+                        + (ChmConstants.LZX_PRETREE_MAXSYMBOLS << 1),
+                ChmConstants.LZX_PRETREE_TABLEBITS,
+                ChmConstants.LZX_PRETREE_MAXSYMBOLS);
+
+        if (pretreetable == null) {
+            throw new ChmParsingException("pretreetable is null");
+        }
+
+        createLengthTreeLenTable(0, ChmConstants.LZX_NUM_SECONDARY_LENGTHS,
+                pretreetable, prelentable);
+
+        getState().setLengthTreeTable(
+                createTreeTable2(getState().getLengthTreeLengtsTable(),
+                        (1 << ChmConstants.LZX_MAINTREE_TABLEBITS)
+                                + (ChmConstants.LZX_LENGTH_MAXSYMBOLS << 1),
+                        ChmConstants.LZX_MAINTREE_TABLEBITS,
+                        ChmConstants.LZX_NUM_SECONDARY_LENGTHS));
+    }
+
+    public void decompressUncompressedBlock(int len, byte[] prevcontent) {
+        if (getContentLength() + getState().getBlockRemaining() <= getBlockLength()) {
+            for (int i = getContentLength(); i < (getContentLength() + getState()
+                    .getBlockRemaining()); i++)
+                content[i] = getChmSection().getByte();
+
+            setContentLength(getContentLength()
+                    + getState().getBlockRemaining());
+            getState().setBlockRemaining(0);
+        } else {
+            for (int i = getContentLength(); i < getBlockLength(); i++)
+                content[i] = getChmSection().getByte();
+            getState().setBlockRemaining(
+                    (int) getBlockLength() - getContentLength());// = blockLen -
+                                                                 // contentlen;
+            setContentLength((int) getBlockLength());
+        }
+    }
+
+    public void decompressAlignedBlock(int len, byte[] prevcontent) {
+
+        if ((getChmSection() == null) || (getState() == null)
+                || (getState().getMainTreeTable() == null))
+            throw new ChmParsingException("chm section is null");
+
+        short s;
+        int x, i, border;
+        int matchlen = 0, matchfooter = 0, extra, rundest, runsrc;
+        int matchoffset = 0;
+        for (i = getContentLength(); i < len; i++) {
+            /* new code */
+            border = getChmSection().getDesyncBits(
+                    ChmConstants.LZX_MAINTREE_TABLEBITS, 0);
+            if (border >= getState().mainTreeTable.length)
+                break;
+            /* end new code */
+            s = getState().mainTreeTable[getChmSection().getDesyncBits(
+                    ChmConstants.LZX_MAINTREE_TABLEBITS, 0)];
+            if (s >= getState().getMainTreeElements()) {
+                x = ChmConstants.LZX_MAINTREE_TABLEBITS;
+                do {
+                    x++;
+                    s <<= 1;
+                    s += getChmSection().checkBit(x);
+                } while ((s = getState().mainTreeTable[s]) >= getState()
+                        .getMainTreeElements());
+            }
+            getChmSection().getSyncBits(getState().mainTreeTable[s]);
+            if (s < ChmConstants.LZX_NUM_CHARS) {
+                content[i] = (byte) s;
+            } else {
+                s -= ChmConstants.LZX_NUM_CHARS;
+                matchlen = s & ChmConstants.LZX_NUM_PRIMARY_LENGTHS;
+                if (matchlen == ChmConstants.LZX_NUM_PRIMARY_LENGTHS) {
+                    matchfooter = getState().lengthTreeTable[getChmSection()
+                            .getDesyncBits(ChmConstants.LZX_MAINTREE_TABLEBITS,
+                                    0)];
+                    if (matchfooter >= ChmConstants.LZX_MAINTREE_TABLEBITS) {
+                        x = ChmConstants.LZX_MAINTREE_TABLEBITS;
+                        do {
+                            x++;
+                            matchfooter <<= 1;
+                            matchfooter += getChmSection().checkBit(x);
+                        } while ((matchfooter = getState().lengthTreeTable[matchfooter]) >= ChmConstants.LZX_NUM_SECONDARY_LENGTHS);
+                    }
+                    getChmSection().getSyncBits(
+                            getState().lengthTreeLengtsTable[matchfooter]);
+                    matchlen += matchfooter;
+                }
+                matchlen += ChmConstants.LZX_MIN_MATCH;
+                matchoffset = s >>> 3;
+                if (matchoffset > 2) {
+                    extra = ChmConstants.EXTRA_BITS[matchoffset];
+                    matchoffset = (ChmConstants.POSITION_BASE[matchoffset] - 2);
+                    if (extra > 3) {
+                        extra -= 3;
+                        long l = getChmSection().getSyncBits(extra);
+                        matchoffset += (l << 3);
+                        int g = getChmSection().getDesyncBits(
+                                ChmConstants.LZX_NUM_PRIMARY_LENGTHS, 0);
+                        int t = getState().getAlignedTreeTable()[g];
+                        if (t >= getState().getMainTreeElements()) {
+                            x = ChmConstants.LZX_MAINTREE_TABLEBITS;
+                            do {
+                                x++;
+                                t <<= 1;
+                                t += getChmSection().checkBit(x);
+                            } while ((t = getState().getAlignedTreeTable()[t]) >= getState()
+                                    .getMainTreeElements());
+                        }
+                        getChmSection().getSyncBits(
+                                getState().getAlignedTreeTable()[t]);
+                        matchoffset += t;
+                    } else if (extra == 3) {
+                        int g = (int) getChmSection().getDesyncBits(
+                                ChmConstants.LZX_NUM_PRIMARY_LENGTHS, 0);
+                        int t = getState().getAlignedTreeTable()[g];
+                        if (t >= getState().getMainTreeElements()) {
+                            x = ChmConstants.LZX_MAINTREE_TABLEBITS;
+                            do {
+                                x++;
+                                t <<= 1;
+                                t += getChmSection().checkBit(x);
+                            } while ((t = getState().getAlignedTreeTable()[t]) >= getState()
+                                    .getMainTreeElements());
+                        }
+                        getChmSection().getSyncBits(
+                                getState().getAlignedTreeTable()[t]);
+                        matchoffset += t;
+                    } else if (extra > 0) {
+                        long l = getChmSection().getSyncBits(extra);
+                        matchoffset += l;
+                    } else
+                        matchoffset = 1;
+                    getState().setR2(getState().getR1());
+                    getState().setR1(getState().getR0());
+                    getState().setR0(matchoffset);
+                } else if (matchoffset == 0) {
+                    matchoffset = (int) getState().getR0();
+                } else if (matchoffset == 1) {
+                    matchoffset = (int) getState().getR1();
+                    getState().setR1(getState().getR0());
+                    getState().setR0(matchoffset);
+                } else /** match_offset == 2 */
+                {
+                    matchoffset = (int) getState().getR2();
+                    getState().setR2(getState().getR0());
+                    getState().setR0(matchoffset);
+                }
+                rundest = i;
+                runsrc = rundest - matchoffset;
+                i += (matchlen - 1);
+                if (i > len)
+                    break;
+
+                if (runsrc < 0) {
+                    if (matchlen + runsrc <= 0) {
+                        runsrc = prevcontent.length + runsrc;
+                        while (matchlen-- > 0)
+                            content[rundest++] = prevcontent[runsrc++];
+                    } else {
+                        runsrc = prevcontent.length + runsrc;
+                        while (runsrc < prevcontent.length)
+                            content[rundest++] = prevcontent[runsrc++];
+                        matchlen = matchlen + runsrc - prevcontent.length;
+                        runsrc = 0;
+                        while (matchlen-- > 0)
+                            content[rundest++] = content[runsrc++];
+                    }
+
+                } else {
+                    /* copies any wrappes around source data */
+                    while ((runsrc < 0) && (matchlen-- > 0)) {
+                        content[rundest++] = content[(int) (runsrc + getBlockLength())];
+                        runsrc++;
+                    }
+                    /* copies match data - no worries about destination wraps */
+                    while (matchlen-- > 0)
+                        content[rundest++] = content[runsrc++];
+                }
+            }
+        }
+        setContentLength(len);
+    }
+
+    private void assertShortArrayNotNull(short[] array) {
+        if (array == null)
+            throw new ChmParsingException("short[] is null");
+    }
+
+    private void decompressVerbatimBlock(int len, byte[] prevcontent) {
+        short s;
+        int x, i;
+        int matchlen = 0, matchfooter = 0, extra, rundest, runsrc;
+        int matchoffset = 0;
+        for (i = getContentLength(); i < len; i++) {
+            int f = (int) getChmSection().getDesyncBits(
+                    ChmConstants.LZX_MAINTREE_TABLEBITS, 0);
+            assertShortArrayNotNull(getState().getMainTreeTable());
+            s = getState().getMainTreeTable()[f];
+            if (s >= ChmConstants.LZX_MAIN_MAXSYMBOLS) {
+                x = ChmConstants.LZX_MAINTREE_TABLEBITS;
+                do {
+                    x++;
+                    s <<= 1;
+                    s += getChmSection().checkBit(x);
+                } while ((s = getState().getMainTreeTable()[s]) >= ChmConstants.LZX_MAIN_MAXSYMBOLS);
+            }
+            getChmSection().getSyncBits(getState().getMainTreeLengtsTable()[s]);
+            if (s < ChmConstants.LZX_NUM_CHARS) {
+                content[i] = (byte) s;
+            } else {
+                s -= ChmConstants.LZX_NUM_CHARS;
+                matchlen = s & ChmConstants.LZX_NUM_PRIMARY_LENGTHS;
+                if (matchlen == ChmConstants.LZX_NUM_PRIMARY_LENGTHS) {
+                    matchfooter = getState().getLengthTreeTable()[(int) getChmSection()
+                            .getDesyncBits(ChmConstants.LZX_LENGTH_TABLEBITS, 0)];
+                    if (matchfooter >= ChmConstants.LZX_NUM_SECONDARY_LENGTHS) {
+                        x = ChmConstants.LZX_LENGTH_TABLEBITS;
+                        do {
+                            x++;
+                            matchfooter <<= 1;
+                            matchfooter += getChmSection().checkBit(x);
+                        } while ((matchfooter = getState().getLengthTreeTable()[matchfooter]) >= ChmConstants.LZX_NUM_SECONDARY_LENGTHS);
+                    }
+                    getChmSection().getSyncBits(
+                            getState().getLengthTreeLengtsTable()[matchfooter]);
+                    matchlen += matchfooter;
+                }
+                matchlen += ChmConstants.LZX_MIN_MATCH;
+                // shorter than 2
+                matchoffset = s >>> 3;
+                if (matchoffset > 2) {
+                    if (matchoffset != 3) { // should get other bits to retrieve
+                                            // offset
+                        extra = ChmConstants.EXTRA_BITS[matchoffset];
+                        long l = getChmSection().getSyncBits(extra);
+                        matchoffset = (int) (ChmConstants.POSITION_BASE[matchoffset] - 2 + l);
+                    } else {
+                        matchoffset = 1;
+                    }
+                    getState().setR2(getState().getR1());
+                    getState().setR1(getState().getR0());
+                    getState().setR0(matchoffset);
+                } else if (matchoffset == 0) {
+                    matchoffset = (int) getState().getR0();
+                } else if (matchoffset == 1) {
+                    matchoffset = (int) getState().getR1();
+                    getState().setR1(getState().getR0());
+                    getState().setR0(matchoffset);
+                } else /* match_offset == 2 */
+                {
+                    matchoffset = (int) getState().getR2();
+                    getState().setR2(getState().getR0());
+                    getState().setR0(matchoffset);
+                }
+                rundest = i;
+                runsrc = rundest - matchoffset;
+                i += (matchlen - 1);
+                if (i > len)
+                    break;
+                if (runsrc < 0) {
+                    if (matchlen + runsrc <= 0) {
+                        runsrc = prevcontent.length + runsrc;
+                        while ((matchlen-- > 0) && (prevcontent != null)
+                                && ((runsrc + 1) > 0))
+                            if ((rundest < content.length)
+                                    && (runsrc < content.length))
+                                content[rundest++] = prevcontent[runsrc++];
+                    } else {
+                        runsrc = prevcontent.length + runsrc;
+                        while (runsrc < prevcontent.length)
+                            if ((rundest < content.length)
+                                    && (runsrc < content.length))
+                                content[rundest++] = prevcontent[runsrc++];
+                        matchlen = matchlen + runsrc - prevcontent.length;
+                        runsrc = 0;
+                        while (matchlen-- > 0)
+                            content[rundest++] = content[runsrc++];
+                    }
+
+                } else {
+                    /* copies any wrapped source data */
+                    while ((runsrc < 0) && (matchlen-- > 0)) {
+                        content[rundest++] = content[(int) (runsrc + getBlockLength())];
+                        runsrc++;
+                    }
+                    /* copies match data - no worries about destination wraps */
+                    while (matchlen-- > 0) {
+                        if ((rundest < content.length)
+                                && (runsrc < content.length))
+                            content[rundest++] = content[runsrc++];
+                    }
+                }
+            }
+        }
+        setContentLength(len);
+    }
+
+    private void createLengthTreeLenTable(int offset, int tablelen,
+            short[] pretreetable, short[] prelentable) {
+        if (prelentable == null || getChmSection() == null
+                || pretreetable == null || prelentable == null)
+            throw new ChmParsingException("is null");
+
+        int i = offset; // represents offset
+        int z, y, x;// local counters
+        while (i < tablelen) {
+            z = pretreetable[(int) getChmSection().getDesyncBits(
+                    ChmConstants.LZX_PRETREE_TABLEBITS, 0)];
+            if (z >= ChmConstants.LZX_PRETREE_NUM_ELEMENTS) {// 1 bug, should be
+                                                             // 20
+                x = ChmConstants.LZX_PRETREE_TABLEBITS;
+                do {
+                    x++;
+                    z <<= 1;
+                    z += getChmSection().checkBit(x);
+                } while ((z = pretreetable[z]) >= ChmConstants.LZX_PRETREE_NUM_ELEMENTS);
+            }
+            getChmSection().getSyncBits(prelentable[z]);
+            if (z < 17) {
+                z = getState().getLengthTreeLengtsTable()[i] - z;
+                if (z < 0)
+                    z = z + 17;
+                getState().getLengthTreeLengtsTable()[i] = (short) z;
+                i++;
+            } else if (z == 17) {
+                y = (int) getChmSection().getSyncBits(4);
+                y += 4;
+                for (int j = 0; j < y; j++)
+                    if (i < getState().getLengthTreeLengtsTable().length)
+                        getState().getLengthTreeLengtsTable()[i++] = 0;
+            } else if (z == 18) {
+                y = (int) getChmSection().getSyncBits(5);
+                y += 20;
+                for (int j = 0; j < y; j++)
+                    if (i < getState().getLengthTreeLengtsTable().length)
+                        getState().getLengthTreeLengtsTable()[i++] = 0;
+            } else if (z == 19) {
+                y = getChmSection().getSyncBits(1);
+                y += 4;
+                z = pretreetable[(int) getChmSection().getDesyncBits(
+                        ChmConstants.LZX_PRETREE_TABLEBITS, 0)];
+                if (z >= ChmConstants.LZX_PRETREE_NUM_ELEMENTS) {// 20
+                    x = ChmConstants.LZX_PRETREE_TABLEBITS;// 6
+                    do {
+                        x++;
+                        z <<= 1;
+                        z += getChmSection().checkBit(x);
+                    } while ((z = pretreetable[z]) >= ChmConstants.LZX_MAINTREE_TABLEBITS);
+                }
+                getChmSection().getSyncBits(prelentable[z]);
+                z = getState().getLengthTreeLengtsTable()[i] - z;
+                if (z < 0)
+                    z = z + 17;
+                for (int j = 0; j < y; j++)
+                    getState().getLengthTreeLengtsTable()[i++] = (short) z;
+            }
+        }
+    }
+
+    private void createMainTreeTable() {
+        short[] prelentable = createPreLenTable();
+        short[] pretreetable = createTreeTable2(prelentable,
+                (1 << ChmConstants.LZX_PRETREE_TABLEBITS)
+                        + (ChmConstants.LZX_PRETREE_MAXSYMBOLS << 1),
+                ChmConstants.LZX_PRETREE_TABLEBITS,
+                ChmConstants.LZX_PRETREE_MAXSYMBOLS);
+        createMainTreeLenTable(0, ChmConstants.LZX_NUM_CHARS, pretreetable,
+                prelentable);
+        prelentable = createPreLenTable();
+        pretreetable = createTreeTable2(prelentable,
+                (1 << ChmConstants.LZX_PRETREE_TABLEBITS)
+                        + (ChmConstants.LZX_PRETREE_MAXSYMBOLS << 1),
+                ChmConstants.LZX_PRETREE_TABLEBITS,
+                ChmConstants.LZX_PRETREE_MAXSYMBOLS);
+        createMainTreeLenTable(ChmConstants.LZX_NUM_CHARS,
+                getState().mainTreeLengtsTable.length, pretreetable,
+                prelentable);
+
+        getState().setMainTreeTable(
+                createTreeTable2(getState().mainTreeLengtsTable,
+                        (1 << ChmConstants.LZX_MAINTREE_TABLEBITS)
+                                + (ChmConstants.LZX_MAINTREE_MAXSYMBOLS << 1),
+                        ChmConstants.LZX_MAINTREE_TABLEBITS, getState()
+                                .getMainTreeElements()));
+
+    }
+
+    private void createMainTreeLenTable(int offset, int tablelen,
+            short[] pretreetable, short[] prelentable) {
+        if (pretreetable == null)
+            throw new ChmParsingException("pretreetable is null");
+        int i = offset;
+        int z, y, x;
+        while (i < tablelen) {
+            int f = getChmSection().getDesyncBits(
+                    ChmConstants.LZX_PRETREE_TABLEBITS, 0);
+            z = pretreetable[f];
+            if (z >= ChmConstants.LZX_PRETREE_MAXSYMBOLS) {
+                x = ChmConstants.LZX_PRETREE_TABLEBITS;
+                do {
+                    x++;
+                    z <<= 1;
+                    z += getChmSection().checkBit(x);
+                } while ((z = pretreetable[z]) >= ChmConstants.LZX_PRETREE_MAXSYMBOLS);
+            }
+            getChmSection().getSyncBits(prelentable[z]);
+            if (z < 17) {
+                z = getState().getMainTreeLengtsTable()[i] - z;
+                if (z < 0)
+                    z = z + 17;
+                getState().mainTreeLengtsTable[i] = (short) z;
+                i++;
+            } else if (z == 17) {
+                y = getChmSection().getSyncBits(4);
+                y += 4;
+                for (int j = 0; j < y; j++) {
+                    assertInRange(getState().getMainTreeLengtsTable(), i);
+                    getState().mainTreeLengtsTable[i++] = 0;
+                }
+            } else if (z == 18) {
+                y = getChmSection().getSyncBits(5);
+                y += 20;
+                for (int j = 0; j < y; j++) {
+                    assertInRange(getState().getMainTreeLengtsTable(), i);
+                    getState().mainTreeLengtsTable[i++] = 0;
+                }
+            } else if (z == 19) {
+                y = getChmSection().getSyncBits(1);
+                y += 4;
+                z = pretreetable[getChmSection().getDesyncBits(
+                        ChmConstants.LZX_PRETREE_TABLEBITS, 0)];
+                if (z >= ChmConstants.LZX_PRETREE_MAXSYMBOLS) {
+                    x = ChmConstants.LZX_PRETREE_TABLEBITS;
+                    do {
+                        x++;
+                        z <<= 1;
+                        z += getChmSection().checkBit(x);
+                    } while ((z = pretreetable[z]) >= ChmConstants.LZX_PRETREE_MAXSYMBOLS);
+                }
+                getChmSection().getSyncBits(prelentable[z]);
+                z = getState().mainTreeLengtsTable[i] - z;
+                if (z < 0)
+                    z = z + 17;
+                for (int j = 0; j < y; j++)
+                    if (i < getState().getMainTreeLengtsTable().length)
+                        getState().mainTreeLengtsTable[i++] = (short) z;
+            }
+        }
+    }
+
+    private void assertInRange(short[] array, int index) {
+        if (index >= array.length)
+            throw new ChmParsingException(index + " is bigger than "
+                    + array.length);
+    }
+
+    private short[] createAlignedLenTable() {
+        int tablelen = ChmConstants.LZX_BLOCKTYPE_UNCOMPRESSED;
+        int bits = ChmConstants.LZX_BLOCKTYPE_UNCOMPRESSED;
+        short[] tmp = new short[tablelen];
+        for (int i = 0; i < tablelen; i++) {
+            tmp[i] = (short) getChmSection().getSyncBits(bits);
+        }
+        return tmp;
+    }
+
+    private void createAlignedTreeTable() {
+        getState().setAlignedLenTable(createAlignedLenTable());
+        getState().setAlignedLenTable(
+                createTreeTable2(getState().getAlignedLenTable(),
+                        (1 << ChmConstants.LZX_NUM_PRIMARY_LENGTHS)
+                                + (ChmConstants.LZX_ALIGNED_MAXSYMBOLS << 1),
+                        ChmConstants.LZX_NUM_PRIMARY_LENGTHS,
+                        ChmConstants.LZX_ALIGNED_MAXSYMBOLS));
+    }
+
+    private short[] createTreeTable2(short[] lentable, int tablelen, int bits,
+            int maxsymbol) {
+        short[] tmp = new short[tablelen];
+        short sym;
+        int leaf;
+        int bit_num = 1;
+        long fill;
+        int pos = 0;
+        /* the current position in the decode table */
+        long table_mask = (1 << bits);
+        long bit_mask = (table_mask >> 1);
+        long next_symbol = bit_mask;
+
+        /* fills entries for short codes for a direct mapping */
+        while (bit_num <= bits) {
+            for (sym = 0; sym < maxsymbol; sym++) {
+                if (lentable.length > sym && lentable[sym] == bit_num) {
+                    leaf = pos;// pos=0
+
+                    if ((pos += bit_mask) > table_mask)
+                        return null;
+
+                    fill = bit_mask;
+                    while (fill-- > 0)
+                        tmp[leaf++] = sym;
+                }
+            }
+            bit_mask >>= 1;
+            bit_num++;
+        }
+
+        /* if there are any codes longer than nbits */
+        if (pos != table_mask) {
+            /* clears the remainder of the table */
+            for (leaf = pos; leaf < table_mask; leaf++)
+                tmp[leaf] = 0;
+
+            /* gives ourselves room for codes to grow by up to 16 more bits */
+            pos <<= 16;
+            table_mask <<= 16;
+            bit_mask = 1 << 15;
+
+            while (bit_num <= 16) {
+                for (sym = 0; sym < maxsymbol; sym++) {
+                    if ((lentable.length > sym) && (lentable[sym] == bit_num)) {
+                        leaf = pos >> 16;
+                        for (fill = 0; fill < bit_num - bits; fill++) {
+                            /*
+                             * if this path hasn't been taken yet, 'allocate'
+                             * two entries
+                             */
+                            if (tmp[leaf] == 0) {
+                                if (((next_symbol << 1) + 1) < tmp.length) {
+                                    tmp[(int) (next_symbol << 1)] = 0;
+                                    tmp[(int) (next_symbol << 1) + 1] = 0;
+                                    tmp[leaf] = (short) next_symbol++;
+                                }
+
+                            }
+                            /*
+                             * follows the path and select either left or right
+                             * for next bit
+                             */
+                            leaf = tmp[leaf] << 1;
+                            if (((pos >> (15 - fill)) & 1) != 0)
+                                leaf++;
+                        }
+                        tmp[leaf] = sym;
+
+                        if ((pos += bit_mask) > table_mask)
+                            return null;
+                        /* table overflow */
+                    } else {
+                        // return null;
+                    }
+                }
+                bit_mask >>= 1;
+                bit_num++;
+            }
+        }
+
+        /* is it full table? */
+        if (pos == table_mask)
+            return tmp;
+
+        return tmp;
+    }
+
+    public byte[] getContent() {
+        return content;
+    }
+
+    public byte[] getContent(int startOffset, int endOffset) {
+        int length = endOffset - startOffset;
+        // return (getContent() != null) ? Arrays.copyOfRange(getContent(),
+        // startOffset, (startOffset + length)) : new byte[1];
+        return (getContent() != null) ? ChmCommons.copyOfRange(getContent(),
+                startOffset, (startOffset + length)) : new byte[1];
+    }
+
+    public byte[] getContent(int start) {
+        // return (getContent() != null) ? Arrays.copyOfRange(getContent(),
+        // start, (getContent().length + start)) : new byte[1];
+        return (getContent() != null) ? ChmCommons.copyOfRange(getContent(),
+                start, (getContent().length + start)) : new byte[1];
+    }
+
+    private void setContent(int contentLength) {
+        this.content = new byte[contentLength];
+    }
+
+    private void checkLzxBlock(ChmLzxBlock chmPrevLzxBlock) {
+        if (chmPrevLzxBlock == null && getBlockLength() < Integer.MAX_VALUE)
+            setState(new ChmLzxState((int) getBlockLength()));
+        else
+            setState(chmPrevLzxBlock.getState());
+    }
+
+    private boolean validateConstructorParams(int blockNumber,
+            byte[] dataSegment, long blockLength) {
+        int goodParameter = 0;
+        if (blockNumber >= 0)
+            ++goodParameter;
+        else
+            throw new ChmParsingException("block number should be possitive");
+        if (dataSegment != null && dataSegment.length > 0)
+            ++goodParameter;
+        else
+            throw new ChmParsingException("data segment should not be null");
+        if (blockLength > 0)
+            ++goodParameter;
+        else
+            throw new ChmParsingException(
+                    "block length should be more than zero");
+        return (goodParameter == 3);
+    }
+
+    public int getBlockNumber() {
+        return block_number;
+    }
+
+    private void setBlockNumber(int block_number) {
+        this.block_number = block_number;
+    }
+
+    private long getBlockLength() {
+        return block_length;
+    }
+
+    private void setBlockLength(long block_length) {
+        this.block_length = block_length;
+    }
+
+    public ChmLzxState getState() {
+        return state;
+    }
+
+    private void setState(ChmLzxState state) {
+        this.state = state;
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        // TODO Auto-generated method stub
 
-	}
+    }
 }