1 // Copyright 2007 Google Inc.
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 #include "bbb_compress.h"
18 #include "rl_compress.h"
19 #include "stream_compressor.h"
25 // Trivial implementations of StreamCompressor and StreamDecompressor
26 // They serve as an example, and can be useful as a replacement of a real
27 // (de)compressor in testing, debugging and development.
28 class TrivialCompressor
: public StreamCompressor
{
30 class Options
: public StreamCompressor::OptionsBase
{
32 bool Set(const std::string
& options
) { return 0 == options
.length(); }
33 std::string
Get() const { return std::string(); }
34 int64
SizeInBytes() const { return 1; }
35 StreamCompressor
* GetCompressor() { return new TrivialCompressor
; }
38 TrivialCompressor() {}
39 virtual ~TrivialCompressor() {}
41 virtual void WriteBegin() {}
42 virtual void WriteEndPrivate() {}
43 virtual void Write(const char* bytes
, size_t n
) { Emit(bytes
, n
); }
45 TrivialCompressor(const TrivialCompressor
&);
46 TrivialCompressor
& operator=(const TrivialCompressor
&);
49 class TrivialDecompressor
: public StreamDecompressor
{
51 static StreamDecompressor
* Create(const std::string
&) {
52 return new TrivialDecompressor
;
54 TrivialDecompressor() {}
55 virtual ~TrivialDecompressor() {}
56 virtual void ReadBegin() {}
57 virtual void ReadEnd() {}
58 virtual void Read(char* bytes
, size_t n
) { GetCompressed(bytes
, n
); }
59 virtual int64
SizeInBytes() const { return 1; }
61 TrivialDecompressor(const TrivialDecompressor
&);
62 TrivialDecompressor
& operator=(const TrivialDecompressor
&);
66 /////////////////////// StreamCompressor ///////////////////////
68 const int StreamCompressor::kBufferSize
= 1 << 16;
70 // Select the compression algorithm based on the first character
71 // of the options_string and let the algorithm specific options
72 // processor handle the rest of options_string.
73 bool StreamCompressor::Options::Set(const std::string
& options_string
) {
74 if (options_string
.length() < 1) return false;
75 char compression_algorithm
= options_string
[0];
77 switch (compression_algorithm
) {
78 case 't': // TrivialCompressor (see above)
79 options
= new TrivialCompressor::Options
;
81 case 'b': // BbbCompressor (see bbb_compressor.h)
82 options
= new BbbCompressor::Options
;
85 options
= new ByteCompressor::Options
;
88 options
= new RunLengthCompressor::Options
;
93 std::string
algorithm_specific_options_string(options_string
, 1);
94 bool success
= options
->Set(algorithm_specific_options_string
);
96 compression_algorithm_
= compression_algorithm
;
97 if (algorithm_specific_options_
) delete algorithm_specific_options_
;
98 algorithm_specific_options_
= options
;
105 StreamCompressor
* StreamCompressor::Options::GetCompressor() {
106 return algorithm_specific_options_
->GetCompressor();
109 StreamCompressor
* StreamCompressor::Connect(OutStream
* output
,
111 StreamCompressor
* compressor
= options
.GetCompressor();
113 // '\n' is used as the terminator of the compression format string.
114 std::string compression_format
= options
.Get() + '\n';
115 output
->Write(compression_format
.data(), compression_format
.length());
116 compressor
->output_
.Connect(output
);
117 compressor
->ConnectPrivate(&compressor
->output_
);
122 OutStream
* StreamCompressor::Disconnect() {
124 OutStream
* oldoutput
= output_
.Disconnect();
129 /////////////////////// StreamDecompressor ///////////////////////
131 StreamDecompressor
* StreamDecompressor::Connect(InStreamBuffer
* input
) {
132 // The compression format is identified by the input prefix ending
133 // with the first '\n'.
135 char ch
= input
->ReadByte();
137 if (format
.length() > 1000) return NULL
; // guard against infinite loop
139 ch
= input
->ReadByte();
141 if (0 == format
.length()) return NULL
;
142 char compression_type
= format
[0];
143 std::string
options(format
, 1);
144 StreamDecompressor
* decompressor
;
145 switch (compression_type
) {
147 decompressor
= TrivialDecompressor::Create(options
);
150 decompressor
= BbbDecompressor::Create(options
);
153 decompressor
= ByteDecompressor::Create(options
);
156 decompressor
= RunLengthDecompressor::Create(options
);
162 decompressor
->format_
= format
;
163 decompressor
->input_
.Connect(input
);
164 decompressor
->ConnectPrivate(decompressor
->input_
.GetServant());
169 InStreamBuffer
* StreamDecompressor::Disconnect() {
171 InStreamBuffer
* oldinput
= input_
.Disconnect();
176 } // namespace dcsbwt