aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/deflate.h2
-rw-r--r--src/lzma.cpp248
-rw-r--r--src/lzma.h56
-rw-r--r--src/tests/lzma.cpp53
4 files changed, 358 insertions, 1 deletions
diff --git a/src/deflate.h b/src/deflate.h
index cab9b51..8ce283b 100644
--- a/src/deflate.h
+++ b/src/deflate.h
@@ -34,7 +34,7 @@ namespace Bu
34 AutoGzip = 0x04|0x03 34 AutoGzip = 0x04|0x03
35 }; 35 };
36 36
37 Deflate( Bu::Stream &rNext, int nCompression=9, Format eFmt=AutoRaw ); 37 Deflate( Bu::Stream &rNext, int nCompression=-1, Format eFmt=AutoRaw );
38 virtual ~Deflate(); 38 virtual ~Deflate();
39 39
40 virtual void start(); 40 virtual void start();
diff --git a/src/lzma.cpp b/src/lzma.cpp
new file mode 100644
index 0000000..6ed0806
--- /dev/null
+++ b/src/lzma.cpp
@@ -0,0 +1,248 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/lzma.h"
9#include "bu/trace.h"
10
11#include <lzma.h>
12
13#define pState ((lzma_stream *)prState)
14
15using namespace Bu;
16
17Bu::Lzma::Lzma( Bu::Stream &rNext, int nCompression, Format eFmt ) :
18 Bu::Filter( rNext ),
19 prState( NULL ),
20 nCompression( nCompression ),
21 sTotalOut( 0 ),
22 eFmt( eFmt ),
23 bEos( false )
24{
25 TRACE( nCompression );
26 start();
27}
28
29Bu::Lzma::~Lzma()
30{
31 TRACE();
32 stop();
33}
34
35void Bu::Lzma::start()
36{
37 TRACE();
38 nBufSize = 64*1024;
39 pBuf = new char[nBufSize];
40}
41
42Bu::size Bu::Lzma::stop()
43{
44 TRACE();
45 if( pState )
46 {
47 if( bReading )
48 {
49 lzma_end( pState );
50 delete[] pBuf;
51 pBuf = NULL;
52 delete pState;
53 prState = NULL;
54 return 0;
55 }
56 else
57 {
58 for(;;)
59 {
60 pState->next_in = NULL;
61 pState->avail_in = 0;
62 pState->avail_out = nBufSize;
63 pState->next_out = (uint8_t *)pBuf;
64 int res = lzma_code( pState, LZMA_FINISH );
65 if( pState->avail_out < nBufSize )
66 {
67 sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out );
68 }
69 if( res == LZMA_STREAM_END )
70 break;
71 }
72 lzma_end( pState );
73 delete[] pBuf;
74 pBuf = NULL;
75 delete pState;
76 prState = NULL;
77 return sTotalOut;
78 }
79 }
80 return 0;
81}
82
83void Bu::Lzma::lzmaError( int code )
84{
85 TRACE( code );
86 switch( code )
87 {
88 case LZMA_OK:
89 case LZMA_STREAM_END:
90 case LZMA_NO_CHECK:
91 case LZMA_UNSUPPORTED_CHECK:
92 break;
93
94 case LZMA_MEM_ERROR:
95 throw ExceptionBase("Lzma: Memory allocation error.");
96
97 case LZMA_MEMLIMIT_ERROR:
98 throw ExceptionBase("Lzma: Memory usage limit was reached.");
99
100 case LZMA_FORMAT_ERROR:
101 throw ExceptionBase("Lzma: File format not recognized.");
102
103 case LZMA_OPTIONS_ERROR:
104 throw ExceptionBase("Lzma: Invalid or unsupported options.");
105
106 case LZMA_DATA_ERROR:
107 throw ExceptionBase("Lzma: Data is corrupt.");
108
109 case LZMA_BUF_ERROR:
110 throw ExceptionBase("Lzma: No progress is possible.");
111
112 case LZMA_PROG_ERROR:
113 throw ExceptionBase("Lzma: Programming error.");
114
115 default:
116 throw ExceptionBase("Lzma: Unknown error encountered." );
117 }
118}
119
120Bu::size Bu::Lzma::read( void *pData, Bu::size nBytes )
121{
122 TRACE( pData, nBytes );
123 if( !pState )
124 {
125 prState = new ::lzma_stream;
126 lzma_stream zEmpty = LZMA_STREAM_INIT;
127 Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) );
128
129 bReading = true;
130 lzmaError( lzma_auto_decoder( pState, UINT64_MAX, 0 ) );
131 pState->next_in = (uint8_t *)pBuf;
132 pState->avail_in = 0;
133 }
134 if( bReading == false )
135 throw ExceptionBase("This lzma filter is in writing mode, you can't read.");
136
137 int nRead = 0;
138 int nReadTotal = pState->total_out;
139 pState->next_out = (uint8_t *)pData;
140 pState->avail_out = nBytes;
141 for(;;)
142 {
143 int ret = lzma_code( pState, LZMA_RUN );
144 printf("inflate returned %d; avail in=%d, out=%d\n", ret,
145 pState->avail_in, pState->avail_out );
146
147 nReadTotal += nRead-pState->avail_out;
148
149 if( ret == LZMA_STREAM_END )
150 {
151 bEos = true;
152 if( pState->avail_in > 0 )
153 {
154 if( rNext.isSeekable() )
155 {
156 rNext.seek( -pState->avail_in );
157 }
158 }
159 return nBytes-pState->avail_out;
160 }
161// if( ret != LZMA_BUF_ERROR )
162 lzmaError( ret );
163
164 if( pState->avail_out )
165 {
166 if( pState->avail_in == 0 )
167 {
168 nRead = rNext.read( pBuf, nBufSize );
169 if( nRead == 0 && rNext.isEos() )
170 {
171 throw Bu::ExceptionBase("Premature end of underlying "
172 "stream found reading deflate stream.");
173 }
174 pState->next_in = (uint8_t *)pBuf;
175 pState->avail_in = nRead;
176 }
177 }
178 else
179 {
180 return nBytes-pState->avail_out;
181 }
182 }
183 return 0;
184}
185
186Bu::size Bu::Lzma::write( const void *pData, Bu::size nBytes )
187{
188 TRACE( pData, nBytes );
189 if( !pState )
190 {
191 prState = new ::lzma_stream;
192 lzma_stream zEmpty = LZMA_STREAM_INIT;
193 Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) );
194
195 bReading = false;
196 if( eFmt == Xz )
197 lzmaError(
198 lzma_easy_encoder( pState, nCompression, LZMA_CHECK_CRC64 )
199 );
200 else if( eFmt == LzmaAlone )
201 {
202 lzma_options_lzma opt;
203 lzma_lzma_preset( &opt, nCompression );
204 lzmaError( lzma_alone_encoder( pState, &opt ) );
205 }
206 else
207 throw Bu::ExceptionBase("Invalid format for lzma.");
208 }
209 if( bReading == true )
210 throw ExceptionBase("This lzma filter is in reading mode, you can't write.");
211
212 pState->next_in = (uint8_t *)pData;
213 pState->avail_in = nBytes;
214 for(;;)
215 {
216 pState->avail_out = nBufSize;
217 pState->next_out = (uint8_t *)pBuf;
218
219 lzmaError( lzma_code( pState, LZMA_RUN ) );
220
221 if( pState->avail_out < nBufSize )
222 {
223 sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out );
224 }
225 if( pState->avail_in == 0 )
226 break;
227 }
228
229 return nBytes;
230}
231
232bool Bu::Lzma::isOpen()
233{
234 TRACE();
235 return (pState != NULL);
236}
237
238bool Bu::Lzma::isEos()
239{
240 TRACE();
241 return bEos;
242}
243
244Bu::size Bu::Lzma::getCompressedSize()
245{
246 return sTotalOut;
247}
248
diff --git a/src/lzma.h b/src/lzma.h
new file mode 100644
index 0000000..21da6e8
--- /dev/null
+++ b/src/lzma.h
@@ -0,0 +1,56 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_LZMA_H
9#define BU_LZMA_H
10
11#include <stdint.h>
12
13#include "bu/filter.h"
14
15namespace Bu
16{
17 /**
18 *
19 *@ingroup Streams
20 */
21 class Lzma : public Bu::Filter
22 {
23 public:
24 enum Format
25 {
26 Xz = 0x01,
27 LzmaAlone = 0x02,
28 };
29
30 Lzma( Bu::Stream &rNext, int nCompression=6, Format eFmt=Xz );
31 virtual ~Lzma();
32
33 virtual void start();
34 virtual Bu::size stop();
35 virtual Bu::size read( void *pBuf, Bu::size nBytes );
36 virtual Bu::size write( const void *pBuf, Bu::size nBytes );
37
38 virtual bool isOpen();
39 virtual bool isEos();
40
41 Bu::size getCompressedSize();
42
43 private:
44 void lzmaError( int code );
45 void *prState;
46 bool bReading;
47 int nCompression;
48 char *pBuf;
49 uint32_t nBufSize;
50 Bu::size sTotalOut;
51 Format eFmt;
52 bool bEos;
53 };
54}
55
56#endif
diff --git a/src/tests/lzma.cpp b/src/tests/lzma.cpp
new file mode 100644
index 0000000..752357a
--- /dev/null
+++ b/src/tests/lzma.cpp
@@ -0,0 +1,53 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/lzma.h"
9#include "bu/file.h"
10
11int main( int argc, char *argv[] )
12{
13 if( argc < 3 )
14 {
15 printf("usage: %s <in> <out>\n", argv[0] );
16 return -1;
17 }
18
19 char buf[1024];
20 size_t nRead;
21
22 /*
23 Bu::File fin( argv[1], Bu::File::Read );
24 fin.seek( 4 );
25 Bu::Deflate def( fin );
26
27 Bu::File f( argv[2], Bu::File::WriteNew );
28
29 for(;;)
30 {
31 nRead = def.read( buf, 1024 );
32 if( nRead > 0 )
33 f.write( buf, nRead );
34 if( def.isEos() )
35 break;
36 }
37 */
38
39 Bu::File fin( argv[1], Bu::File::Read );
40
41 Bu::File f( argv[2], Bu::File::WriteNew );
42 Bu::Lzma def( f, 9 );
43
44 for(;;)
45 {
46 nRead = fin.read( buf, 1024 );
47 if( nRead > 0 )
48 def.write( buf, nRead );
49 if( fin.isEos() )
50 break;
51 }
52}
53