OpenCores
URL https://opencores.org/ocsvn/lzrw1-compressor-core/lzrw1-compressor-core/trunk

Subversion Repositories lzrw1-compressor-core

[/] [lzrw1-compressor-core/] [trunk/] [LZRW1Decoder.java] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 habicht
/**************************************************************************************************************
2
*
3
*    L Z R W 1   E N C O D E R   C O R E
4
*
5
*  A high throughput loss less data compression core.
6
*
7
* Copyright 2012-2013   Lukas Schrittwieser (LS)
8
*
9
*    This program is free software: you can redistribute it and/or modify
10
*    it under the terms of the GNU General Public License as published by
11
*    the Free Software Foundation, either version 2 of the License, or
12
*    (at your option) any later version.
13
*
14
*    This program is distributed in the hope that it will be useful,
15
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
*    GNU General Public License for more details.
18
*
19
*    You should have received a copy of the GNU General Public License
20
*    along with this program; if not, write to the Free Software
21
*    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22
*    Or see <http://www.gnu.org/licenses/>
23
*
24
***************************************************************************************************************
25
*
26
* Change Log:
27
*
28
* Version 1.0 - 2013/04/05 - LS
29
*   released
30
*
31
***************************************************************************************************************
32
*
33
* This is an example decoder (decompressor) for which can be used to decompress data encoded by the core.
34
*
35
***************************************************************************************************************/
36
 
37
package org.sump.analyzer;
38
import java.io.IOException;
39
 
40
class LZRW1Decoder
41
{
42
        final static boolean DEBUG = false;             // set this to true for detailed debug output to the console
43
 
44
        final static int HISTORY_LEN = 4096;    // buffer length in bytes 
45
        final static int LOOK_AHEAD_LEN = 16;   // look ahead buffer length in bytes
46
        final static int HASH_BIT_LEN = 11;     // number of bits for the index in the hash table
47
 
48
        /* configer the number of items (offset-length-tuples or literals) per frame */
49
        public final int ITEMS_PER_FRAME = 8;
50
 
51
        public LZRW1Decoder ()
52
        {
53
                // allocate the history buffer
54
                buffer = new int[HISTORY_LEN];
55
                validBufferLen = 0;
56
                histWrInd = 0;
57
                flags = 0;
58
                frameItemCnt = 0;
59
                offset = -1;
60
                copyCnt = 0;
61
                readIndex = 0;
62
                endOfData = false;
63
                if (DEBUG)
64
                        System.out.println("LZRW1Decoder constructed");
65
        }
66
 
67
        /**
68
        * Loads a block of compressed data into the module. Decoding will start at a given offset.
69
        * @param cd             The data to be decompressed
70
        * @param o              Index of the first byte of encoded data in cd
71
        */
72
        void loadCompressedData (byte [] cd, int o)
73
        {
74
                compressed = cd;
75
                // reset all internal states for a new stream
76
                validBufferLen = 0;
77
                histWrInd = 0;
78
                flags = 0;
79
                frameItemCnt = 0;
80
                offset = -1;
81
                copyCnt = 0;
82
                readIndex = o;
83
                endOfData = false;
84
                if (DEBUG)
85
                        System.out.println("compressed data loaded");
86
        }
87
 
88
        /**
89
        * Decompresses one byte of data stored in source block and returns it. If no source data is available an
90
        * exception will be created. If the end-of-data symbol is encountered -1 will be returned. If the compressed
91
        * data ends without an end-of-data symbol an exception will be created as well. Any data after an end-of-data
92
        * symbol will be ignored and can not be decoded. However the method may still be called, it will keep returning
93
        * -1 to indicated the end of the decoded data.
94
        * @return       The next byte in the stream of decoded data. -1 if end-of-data was reached
95
        * @throws IOException if an error is found in the encoded data
96
        */
97
        int decodeNextByte () throws IOException
98
        {
99
                int ch = 0;              // decoded char (to be returned)
100
 
101
                // make sure that we have data
102
                if (compressed == null)
103
                        throw new IOException("no compressed data loaded");
104
 
105
                if (endOfData)
106
                        return -1;
107
 
108
                // check wether we can copy data from the stream history (due to a offset/length pair found earlier)
109
                if (copyCnt > 0)
110
                {
111
                        ch = readFromHistory();
112
                        copyCnt--;
113
                        // the byte is decoded, it becomes part of the stream history
114
                        insertIntoHistBuf(ch);
115
                        return ch;
116
                }
117
 
118
                // get next byte from compressed data stream
119
                if (readIndex >= compressed.length)
120
                        throw new IOException("encountered end of compressed data without end-of-data symbol (data corrupt)");
121
                ch = compressed[readIndex++];
122
 
123
                // load a new header if necessary
124
                if (frameItemCnt==0)
125
                {
126
                        flags = ch&0xff;
127
                        if (DEBUG)
128
                                System.out.printf("   found header: %02x\n",flags);
129
                        frameItemCnt = 8;
130
                        // load the next byte
131
                        if (readIndex >= compressed.length)
132
                                throw new IOException("encountered end of compressed data without end-of-data symbol (data corrupt)");
133
                        ch = compressed[readIndex++];
134
                }
135
 
136
                // check whether we have a pair or not
137
                if ((flags&0x01) == 1)
138
                {
139
                        // this is a length-offset pair, load the second byte
140
                        if (readIndex >= compressed.length)
141
                                throw new IOException("encountered end of compressed data without end-of-data symbol (data corrupt)");
142
                        int lowByte = compressed[readIndex++];
143
                        int highByte = ch;
144
                        // decode the pair into offset and length
145
                        copyCnt = (highByte>>4) & 0x0f;
146
                        offset = ((highByte<<8)&0x0f00) + (lowByte&0xff);
147
                        // check for the end-of-data symbol
148
                        if ((offset==0) && (copyCnt==0))
149
                        {
150
                                if (DEBUG)
151
                                        System.out.println("   found end of data symbol");
152
                                endOfData = true;
153
                                // check that there is no data left in the encoded input
154
                                /*if (readIndex < compressed.length)
155
                                        throw new IOException("compressed data after end-of-data symbol (data corrupt) "+readIndex+"  "+compressed.length);*/
156
                                return -1;
157
                        }
158
                        copyCnt++;      // Note: the encoder saves the number of byte to be copied minus 1 to save some space (2 means copy 3 bytes, and so on)
159
                        if (DEBUG)
160
                                System.out.println("len:"+copyCnt+" off:"+offset);
161
                        // load the first copy byte from the history buffer
162
                        ch = readFromHistory();
163
                        copyCnt--;      // one byte copied
164
                        // this byte is decoded, it becomes part of the stream history
165
                        insertIntoHistBuf(ch);
166
                }
167
                else
168
                {
169
                        // convert the signed char (-128..127) to an unsigned value
170
                        //if (ch < 0)
171
                        //      ch += 256;
172
                        ch &= 0xff;
173
 
174
                        // this is a literal
175
                        if (DEBUG)
176
                                System.out.printf("lit: '%c'=%02x\n",ch,ch);
177
                        // save this byte in the history buffer
178
                        insertIntoHistBuf(ch);
179
                }
180
 
181
                // shift header for next byte
182
                frameItemCnt--;
183
                flags >>= 1;
184
                return ch;
185
        }
186
 
187
        /**
188
        * read one byte from the history buffer from the position defined by offset.
189
        */
190
        private int readFromHistory() throws IOException
191
        {
192
                if (offset >= validBufferLen)
193
                        throw new IOException("offset is pointing to a location before the beginning of the data (data corrupt)");
194
                // calculate index (move back offset bytes) from last one (-1 because histWrInd point to next free location)    
195
                int ind = histWrInd-offset-1;
196
                if (ind < 0)     // wrap around (ring buffer)
197
                        ind += HISTORY_LEN;
198
                if (ind < 0)
199
                        // index is still negative, this is an error in the encoded data
200
                        throw new IOException("Offset wraps more than once in history buffer (data corrupt)");
201
                // load the byte from the histroy buffer        
202
                return buffer[ind];
203
        }
204
 
205
        private void insertIntoHistBuf (int ch)
206
        {
207
                buffer[histWrInd++] = ch;
208
                if (histWrInd >= buffer.length)
209
                        histWrInd = 0;
210
                // count the number of valid bytes in the histroy buffer
211
                if (validBufferLen < HISTORY_LEN)
212
                        validBufferLen++;
213
        }
214
 
215
        int [] buffer;
216
        int validBufferLen;
217
        int histWrInd;
218
        int flags;
219
        int frameItemCnt;
220
        int offset;
221
        int copyCnt;
222
        byte [] compressed;     // holds the compressed data
223
        int readIndex;
224
        boolean endOfData;
225
}
226
 
227
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.