blob: a41ee8044c6717f2fd35b0655223fe296c7855e1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tika.parser.microsoft.chm;
import java.util.concurrent.CancellationException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.parser.microsoft.chm.ChmCommons.IntelState;
import org.apache.tika.parser.microsoft.chm.ChmCommons.LzxState;
public class ChmLzxState implements Cloneable {
// Trees - PRETREE, MAINTREE, LENGTH, ALIGNED
protected short[] mainTreeLengtsTable;
protected short[] mainTreeTable;
protected short[] lengthTreeTable;
protected short[] lengthTreeLengtsTable;
protected short[] alignedLenTable;
protected short[] alignedTreeTable;
/* Class' members */
private int window; /* the actual decoding window */
private long window_size; /* window size (32Kb through 2Mb) */
private int window_position; /* current offset within the window */
private int main_tree_elements; /* number of main tree elements */
private LzxState hadStarted; /* have we started decoding at all yet? */
private int block_type; /* type of this block */
private int block_length; /* uncompressed length of this block */
private int block_remaining; /* uncompressed bytes still left to decode */
private int frames_read; /* the number of CFDATA blocks processed */
private int intel_file_size; /* magic header value used for transform */
private long intel_current_possition; /* current offset in transform space */
private IntelState intel_state; /* have we seen any translatable data yet? */
private long R0; /* for the LRU offset system */
private long R1; /* for the LRU offset system */
private long R2; /* for the LRU offset system */
public ChmLzxState(int window) throws TikaException {
if (window >= 0) {
int position_slots;
int win = ChmCommons.getWindowSize(window);
setWindowSize(1 << win);
/* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
if (win < 15 || win > 21) {
throw new ChmParsingException("window less than 15 or window greater than 21");
}
/* Calculates required position slots */
if (win == 20) {
position_slots = 42;
} else if (win == 21) {
position_slots = 50;
} else {
position_slots = win << 1;
}
//TODO: position_slots is not used ?
setR0(1);
setR1(1);
setR2(1);
setMainTreeElements(512);
setHadStarted(LzxState.NOT_STARTED_DECODING);
setFramesRead(0);
setBlockRemaining(0);
setBlockType(ChmConstants.LZX_BLOCKTYPE_INVALID);
setIntelCurrentPossition(0);
setIntelState(IntelState.NOT_STARTED);
setWindowPosition(0);
setMainTreeLengtsTable(new short[getMainTreeElements()]);
setLengthTreeLengtsTable(new short[ChmConstants.LZX_NUM_SECONDARY_LENGTHS]);
} else {
throw new CancellationException("window size should be more than zero");
}
}
private static short[] arrayClone(short[] a) {
return a == null ? null : (short[]) a.clone();
}
@Override
public ChmLzxState clone() {
try {
ChmLzxState clone = (ChmLzxState) super.clone();
clone.mainTreeLengtsTable = arrayClone(mainTreeLengtsTable);
clone.mainTreeTable = arrayClone(mainTreeTable);
clone.lengthTreeTable = arrayClone(lengthTreeTable);
clone.lengthTreeLengtsTable = arrayClone(lengthTreeLengtsTable);
clone.alignedLenTable = arrayClone(alignedLenTable);
clone.alignedTreeTable = arrayClone(alignedTreeTable);
return clone;
} catch (CloneNotSupportedException ex) {
return null;
}
}
protected short[] getMainTreeTable() {
return mainTreeTable;
}
protected void setMainTreeTable(short[] mainTreeTable) {
this.mainTreeTable = mainTreeTable;
}
protected short[] getAlignedTreeTable() {
return alignedTreeTable;
}
protected void setAlignedTreeTable(short[] alignedTreeTable) {
this.alignedTreeTable = alignedTreeTable;
}
protected short[] getLengthTreeTable() throws TikaException {
if (lengthTreeTable != null) {
return this.lengthTreeTable;
} else {
throw new ChmParsingException("lengthTreeTable is null");
}
}
protected void setLengthTreeTable(short[] lengthTreeTable) {
this.lengthTreeTable = lengthTreeTable;
}
protected short[] getAlignedLenTable() {
return this.alignedLenTable;
}
protected void setAlignedLenTable(short[] alignedLenTable) {
this.alignedLenTable = alignedLenTable;
}
/**
* It suits for informative outlook
*/
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("actual decoding window:=")
.append(getWindow())
.append(System.getProperty("line.separator"));
sb.append("window size (32Kb through 2Mb):=")
.append(getWindowSize())
.append(System.getProperty("line.separator"));
sb.append("current offset within the window:=")
.append(getWindowPosition())
.append(System.getProperty("line.separator"));
sb.append("number of main tree elements:=")
.append(getMainTreeElements())
.append(System.getProperty("line.separator"));
sb.append("have we started decoding at all yet?:=")
.append(getHadStarted())
.append(System.getProperty("line.separator"));
sb.append("type of this block:=")
.append(getBlockType())
.append(System.getProperty("line.separator"));
sb.append("uncompressed length of this block:=")
.append(getBlockLength())
.append(System.getProperty("line.separator"));
sb.append("uncompressed bytes still left to decode:=")
.append(getBlockRemaining())
.append(System.getProperty("line.separator"));
sb.append("the number of CFDATA blocks processed:=")
.append(getFramesRead())
.append(System.getProperty("line.separator"));
sb.append("magic header value used for transform:=")
.append(getIntelFileSize())
.append(System.getProperty("line.separator"));
sb.append("current offset in transform space:=")
.append(getIntelCurrentPossition())
.append(System.getProperty("line.separator"));
sb.append("have we seen any translatable data yet?:=")
.append(getIntelState())
.append(System.getProperty("line.separator"));
sb.append("R0 for the LRU offset system:=")
.append(getR0())
.append(System.getProperty("line.separator"));
sb.append("R1 for the LRU offset system:=")
.append(getR1())
.append(System.getProperty("line.separator"));
sb.append("R2 for the LRU offset system:=")
.append(getR2())
.append(System.getProperty("line.separator"));
sb.append("main tree length:=")
.append(getMainTreeLengtsTable().length)
.append(System.getProperty("line.separator"));
sb.append("secondary tree length:=")
.append(getLengthTreeLengtsTable().length)
.append(System.getProperty("line.separator"));
return sb.toString();
}
protected int getWindow() {
return window;
}
protected void setWindow(int window) {
this.window = window;
}
protected long getWindowSize() {
return window_size;
}
protected void setWindowSize(long window_size) {
this.window_size = window_size;
}
protected int getWindowPosition() {
return window_position;
}
protected void setWindowPosition(int window_position) {
this.window_position = window_position;
}
protected int getMainTreeElements() {
return main_tree_elements;
}
protected void setMainTreeElements(int main_tree_elements) {
this.main_tree_elements = main_tree_elements;
}
protected LzxState getHadStarted() {
return hadStarted;
}
protected void setHadStarted(LzxState hadStarted) {
this.hadStarted = hadStarted;
}
public int getBlockType() {
return block_type;
}
protected void setBlockType(int block_type) {
this.block_type = block_type;
}
protected int getBlockLength() {
return block_length;
}
protected void setBlockLength(int block_length) {
this.block_length = block_length;
}
protected int getBlockRemaining() {
return block_remaining;
}
protected void setBlockRemaining(int block_remaining) {
this.block_remaining = block_remaining;
}
protected void increaseFramesRead() {
this.frames_read = getFramesRead() + 1;
}
protected int getFramesRead() {
return frames_read;
}
protected void setFramesRead(int frames_read) {
this.frames_read = frames_read;
}
protected int getIntelFileSize() {
return intel_file_size;
}
protected void setIntelFileSize(int intel_file_size) {
this.intel_file_size = intel_file_size;
}
protected long getIntelCurrentPossition() {
return intel_current_possition;
}
protected void setIntelCurrentPossition(long intel_current_possition) {
this.intel_current_possition = intel_current_possition;
}
protected IntelState getIntelState() {
return intel_state;
}
protected void setIntelState(IntelState intel_state) {
this.intel_state = intel_state;
}
protected long getR0() {
return R0;
}
protected void setR0(long r0) {
R0 = r0;
}
protected long getR1() {
return R1;
}
protected void setR1(long r1) {
R1 = r1;
}
protected long getR2() {
return R2;
}
protected void setR2(long r2) {
R2 = r2;
}
public short[] getMainTreeLengtsTable() {
return mainTreeLengtsTable;
}
public void setMainTreeLengtsTable(short[] mainTreeLengtsTable) {
this.mainTreeLengtsTable = mainTreeLengtsTable;
}
public short[] getLengthTreeLengtsTable() {
return lengthTreeLengtsTable;
}
public void setLengthTreeLengtsTable(short[] lengthTreeLengtsTable) {
this.lengthTreeLengtsTable = lengthTreeLengtsTable;
}
}