aboutsummaryrefslogtreecommitdiff
path: root/java/dec/State.java
blob: 9ac6ca186e3b958b9dd378c7fd144ace729843ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/* Copyright 2015 Google Inc. All Rights Reserved.

   Distributed under MIT license.
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/

package org.brotli.dec;

import static org.brotli.dec.RunningState.BLOCK_START;
import static org.brotli.dec.RunningState.UNINITIALIZED;

import java.io.InputStream;

final class State {
  RunningState runningState = UNINITIALIZED;
  RunningState nextRunningState;
  final BitReader br = new BitReader();
  byte[] ringBuffer;
  final int[] blockTypeTrees = new int[3 * Huffman.HUFFMAN_MAX_TABLE_SIZE];
  final int[] blockLenTrees = new int[3 * Huffman.HUFFMAN_MAX_TABLE_SIZE];

  // Current meta-block header information.
  int metaBlockLength;
  boolean inputEnd;
  boolean isUncompressed;
  boolean isMetadata;

  final HuffmanTreeGroup hGroup0 = new HuffmanTreeGroup();
  final HuffmanTreeGroup hGroup1 = new HuffmanTreeGroup();
  final HuffmanTreeGroup hGroup2 = new HuffmanTreeGroup();
  final int[] blockLength = new int[3];
  final int[] numBlockTypes = new int[3];
  final int[] blockTypeRb = new int[6];
  final int[] distRb = {16, 15, 11, 4};
  int pos = 0;
  int maxDistance = 0;
  int distRbIdx = 0;
  boolean trivialLiteralContext = false;
  int literalTreeIndex = 0;
  int literalTree;
  int j;
  int insertLength;
  byte[] contextModes;
  byte[] contextMap;
  int contextMapSlice;
  int distContextMapSlice;
  int contextLookupOffset1;
  int contextLookupOffset2;
  int treeCommandOffset;
  int distanceCode;
  byte[] distContextMap;
  int numDirectDistanceCodes;
  int distancePostfixMask;
  int distancePostfixBits;
  int distance;
  int copyLength;
  int copyDst;
  int maxBackwardDistance;
  int maxRingBufferSize;
  int ringBufferSize = 0;
  long expectedTotalSize = 0;
  byte[] customDictionary = new byte[0];
  int bytesToIgnore = 0;

  int outputOffset;
  int outputLength;
  int outputUsed;
  int bytesWritten;
  int bytesToWrite;
  byte[] output;

  // TODO: Update to current spec.
  private static int decodeWindowBits(BitReader br) {
    if (BitReader.readBits(br, 1) == 0) {
      return 16;
    }
    int n = BitReader.readBits(br, 3);
    if (n != 0) {
      return 17 + n;
    }
    n = BitReader.readBits(br, 3);
    if (n != 0) {
      return 8 + n;
    }
    return 17;
  }

  /**
   * Associate input with decoder state.
   *
   * @param state uninitialized state without associated input
   * @param input compressed data source
   */
  static void setInput(State state, InputStream input) {
    if (state.runningState != UNINITIALIZED) {
      throw new IllegalStateException("State is MUST be uninitialized");
    }
    BitReader.init(state.br, input);
    int windowBits = decodeWindowBits(state.br);
    if (windowBits == 9) { /* Reserved case for future expansion. */
      throw new BrotliRuntimeException("Invalid 'windowBits' code");
    }
    state.maxRingBufferSize = 1 << windowBits;
    state.maxBackwardDistance = state.maxRingBufferSize - 16;
    state.runningState = BLOCK_START;
  }
}