1dcdc33b0SIngo Weinhold/*
2dcdc33b0SIngo Weinhold * Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
3dcdc33b0SIngo Weinhold * Distributed under the terms of the MIT License.
4dcdc33b0SIngo Weinhold */
5dcdc33b0SIngo Weinhold
6dcdc33b0SIngo Weinhold
7dcdc33b0SIngo Weinhold#include <CompressionAlgorithm.h>
8dcdc33b0SIngo Weinhold
9dcdc33b0SIngo Weinhold#include <stdlib.h>
10dcdc33b0SIngo Weinhold#include <string.h>
11dcdc33b0SIngo Weinhold
12dcdc33b0SIngo Weinhold#include <Errors.h>
13dcdc33b0SIngo Weinhold
14dcdc33b0SIngo Weinhold
15dcdc33b0SIngo Weinhold// #pragma mark - BCompressionParameters
16dcdc33b0SIngo Weinhold
17dcdc33b0SIngo Weinhold
18dcdc33b0SIngo WeinholdBCompressionParameters::BCompressionParameters()
19dcdc33b0SIngo Weinhold{
20dcdc33b0SIngo Weinhold}
21dcdc33b0SIngo Weinhold
22dcdc33b0SIngo Weinhold
23dcdc33b0SIngo WeinholdBCompressionParameters::~BCompressionParameters()
24dcdc33b0SIngo Weinhold{
25dcdc33b0SIngo Weinhold}
26dcdc33b0SIngo Weinhold
27dcdc33b0SIngo Weinhold
28dcdc33b0SIngo Weinhold// #pragma mark - BDecompressionParameters
29dcdc33b0SIngo Weinhold
30dcdc33b0SIngo Weinhold
31dcdc33b0SIngo WeinholdBDecompressionParameters::BDecompressionParameters()
32dcdc33b0SIngo Weinhold{
33dcdc33b0SIngo Weinhold}
34dcdc33b0SIngo Weinhold
35dcdc33b0SIngo Weinhold
36dcdc33b0SIngo WeinholdBDecompressionParameters::~BDecompressionParameters()
37dcdc33b0SIngo Weinhold{
38dcdc33b0SIngo Weinhold}
39dcdc33b0SIngo Weinhold
40dcdc33b0SIngo Weinhold
41dcdc33b0SIngo Weinhold// #pragma mark - BCompressionAlgorithm
42dcdc33b0SIngo Weinhold
43dcdc33b0SIngo Weinhold
44dcdc33b0SIngo WeinholdBCompressionAlgorithm::BCompressionAlgorithm()
45dcdc33b0SIngo Weinhold{
46dcdc33b0SIngo Weinhold}
47dcdc33b0SIngo Weinhold
48dcdc33b0SIngo Weinhold
49dcdc33b0SIngo WeinholdBCompressionAlgorithm::~BCompressionAlgorithm()
50dcdc33b0SIngo Weinhold{
51dcdc33b0SIngo Weinhold}
52dcdc33b0SIngo Weinhold
53dcdc33b0SIngo Weinhold
54dcdc33b0SIngo Weinholdstatus_t
55dcdc33b0SIngo WeinholdBCompressionAlgorithm::CreateCompressingInputStream(BDataIO* input,
56dcdc33b0SIngo Weinhold	const BCompressionParameters* parameters, BDataIO*& _stream)
57dcdc33b0SIngo Weinhold{
58dcdc33b0SIngo Weinhold	return B_NOT_SUPPORTED;
59dcdc33b0SIngo Weinhold}
60dcdc33b0SIngo Weinhold
61dcdc33b0SIngo Weinhold
62dcdc33b0SIngo Weinholdstatus_t
63dcdc33b0SIngo WeinholdBCompressionAlgorithm::CreateCompressingOutputStream(BDataIO* output,
64dcdc33b0SIngo Weinhold	const BCompressionParameters* parameters, BDataIO*& _stream)
65dcdc33b0SIngo Weinhold{
66dcdc33b0SIngo Weinhold	return B_NOT_SUPPORTED;
67dcdc33b0SIngo Weinhold}
68dcdc33b0SIngo Weinhold
69dcdc33b0SIngo Weinhold
70dcdc33b0SIngo Weinholdstatus_t
71dcdc33b0SIngo WeinholdBCompressionAlgorithm::CreateDecompressingInputStream(BDataIO* input,
72dcdc33b0SIngo Weinhold	const BDecompressionParameters* parameters, BDataIO*& _stream)
73dcdc33b0SIngo Weinhold{
74dcdc33b0SIngo Weinhold	return B_NOT_SUPPORTED;
75dcdc33b0SIngo Weinhold}
76dcdc33b0SIngo Weinhold
77dcdc33b0SIngo Weinhold
78dcdc33b0SIngo Weinholdstatus_t
79dcdc33b0SIngo WeinholdBCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output,
80dcdc33b0SIngo Weinhold	const BDecompressionParameters* parameters, BDataIO*& _stream)
81dcdc33b0SIngo Weinhold{
82dcdc33b0SIngo Weinhold	return B_NOT_SUPPORTED;
83dcdc33b0SIngo Weinhold}
84dcdc33b0SIngo Weinhold
85dcdc33b0SIngo Weinhold
86dcdc33b0SIngo Weinholdstatus_t
87dcdc33b0SIngo WeinholdBCompressionAlgorithm::CompressBuffer(const void* input, size_t inputSize,
88dcdc33b0SIngo Weinhold	void* output, size_t outputSize, size_t& _compressedSize,
89dcdc33b0SIngo Weinhold	const BCompressionParameters* parameters)
90dcdc33b0SIngo Weinhold{
91dcdc33b0SIngo Weinhold	return B_NOT_SUPPORTED;
92dcdc33b0SIngo Weinhold}
93dcdc33b0SIngo Weinhold
94dcdc33b0SIngo Weinhold
95dcdc33b0SIngo Weinholdstatus_t
96dcdc33b0SIngo WeinholdBCompressionAlgorithm::DecompressBuffer(const void* input,
97dcdc33b0SIngo Weinhold	size_t inputSize, void* output, size_t outputSize,
98dcdc33b0SIngo Weinhold	size_t& _uncompressedSize, const BDecompressionParameters* parameters)
99dcdc33b0SIngo Weinhold{
100dcdc33b0SIngo Weinhold	return B_NOT_SUPPORTED;
101dcdc33b0SIngo Weinhold}
102dcdc33b0SIngo Weinhold
103dcdc33b0SIngo Weinhold
104dcdc33b0SIngo Weinhold// #pragma mark - BAbstractStream
105dcdc33b0SIngo Weinhold
106dcdc33b0SIngo Weinhold
107dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractStream::BAbstractStream()
108dcdc33b0SIngo Weinhold	:
109dcdc33b0SIngo Weinhold	BDataIO(),
110dcdc33b0SIngo Weinhold	fBuffer(NULL),
111dcdc33b0SIngo Weinhold	fBufferCapacity(0),
112dcdc33b0SIngo Weinhold	fBufferOffset(0),
113dcdc33b0SIngo Weinhold	fBufferSize(0)
114dcdc33b0SIngo Weinhold{
115dcdc33b0SIngo Weinhold}
116dcdc33b0SIngo Weinhold
117dcdc33b0SIngo Weinhold
118dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractStream::~BAbstractStream()
119dcdc33b0SIngo Weinhold{
120dcdc33b0SIngo Weinhold	free(fBuffer);
121dcdc33b0SIngo Weinhold}
122dcdc33b0SIngo Weinhold
123dcdc33b0SIngo Weinhold
124dcdc33b0SIngo Weinholdstatus_t
125dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractStream::Init(size_t bufferSize)
126dcdc33b0SIngo Weinhold{
127dcdc33b0SIngo Weinhold	fBuffer = (uint8*)malloc(bufferSize);
128dcdc33b0SIngo Weinhold	fBufferCapacity = bufferSize;
129dcdc33b0SIngo Weinhold
130dcdc33b0SIngo Weinhold	return fBuffer != NULL ? B_OK : B_NO_MEMORY;
131dcdc33b0SIngo Weinhold}
132dcdc33b0SIngo Weinhold
133dcdc33b0SIngo Weinhold
134dcdc33b0SIngo Weinhold// #pragma mark - BAbstractInputStream
135dcdc33b0SIngo Weinhold
136dcdc33b0SIngo Weinhold
137dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractInputStream::BAbstractInputStream(
138dcdc33b0SIngo Weinhold		BDataIO* input)
139dcdc33b0SIngo Weinhold	:
140dcdc33b0SIngo Weinhold	BAbstractStream(),
141dcdc33b0SIngo Weinhold	fInput(input),
142dcdc33b0SIngo Weinhold	fEndOfInput(false),
143dcdc33b0SIngo Weinhold	fNoMorePendingData(false)
144dcdc33b0SIngo Weinhold{
145dcdc33b0SIngo Weinhold}
146dcdc33b0SIngo Weinhold
147dcdc33b0SIngo Weinhold
148dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractInputStream::~BAbstractInputStream()
149dcdc33b0SIngo Weinhold{
150dcdc33b0SIngo Weinhold}
151dcdc33b0SIngo Weinhold
152dcdc33b0SIngo Weinhold
153dcdc33b0SIngo Weinholdssize_t
154dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractInputStream::Read(void* buffer, size_t size)
155dcdc33b0SIngo Weinhold{
156dcdc33b0SIngo Weinhold	if (size == 0)
157dcdc33b0SIngo Weinhold		return 0;
158dcdc33b0SIngo Weinhold
159dcdc33b0SIngo Weinhold	size_t bytesRemaining = size;
160dcdc33b0SIngo Weinhold	uint8* output = (uint8*)buffer;
161dcdc33b0SIngo Weinhold
162dcdc33b0SIngo Weinhold	while (bytesRemaining > 0) {
163dcdc33b0SIngo Weinhold		// process the data still in the input buffer
164dcdc33b0SIngo Weinhold		if (fBufferSize > 0) {
165dcdc33b0SIngo Weinhold			size_t bytesConsumed;
166dcdc33b0SIngo Weinhold			size_t bytesProduced;
167dcdc33b0SIngo Weinhold			status_t error = ProcessData(fBuffer + fBufferOffset, fBufferSize,
168dcdc33b0SIngo Weinhold				output, bytesRemaining, bytesConsumed, bytesProduced);
169dcdc33b0SIngo Weinhold			if (error != B_OK)
170dcdc33b0SIngo Weinhold				return error;
171dcdc33b0SIngo Weinhold
172dcdc33b0SIngo Weinhold			fBufferOffset += bytesConsumed;
173dcdc33b0SIngo Weinhold			fBufferSize -= bytesConsumed;
174dcdc33b0SIngo Weinhold			output += bytesProduced;
175dcdc33b0SIngo Weinhold			bytesRemaining -= bytesProduced;
176dcdc33b0SIngo Weinhold			continue;
177dcdc33b0SIngo Weinhold		}
178dcdc33b0SIngo Weinhold
179dcdc33b0SIngo Weinhold		// We couldn't process anything, because we don't have any or not enough
180dcdc33b0SIngo Weinhold		// bytes in the input buffer.
181dcdc33b0SIngo Weinhold
182dcdc33b0SIngo Weinhold		if (fEndOfInput)
183dcdc33b0SIngo Weinhold			break;
184dcdc33b0SIngo Weinhold
185dcdc33b0SIngo Weinhold		// Move any remaining data to the start of the buffer.
186dcdc33b0SIngo Weinhold		if (fBufferSize > 0) {
187dcdc33b0SIngo Weinhold			if (fBufferSize == fBufferCapacity)
188dcdc33b0SIngo Weinhold				return B_ERROR;
189dcdc33b0SIngo Weinhold
190dcdc33b0SIngo Weinhold			if (fBufferOffset > 0)
191dcdc33b0SIngo Weinhold				memmove(fBuffer, fBuffer + fBufferOffset, fBufferSize);
192dcdc33b0SIngo Weinhold		}
193dcdc33b0SIngo Weinhold
194dcdc33b0SIngo Weinhold		fBufferOffset = 0;
195dcdc33b0SIngo Weinhold
196dcdc33b0SIngo Weinhold		// read from the source
197dcdc33b0SIngo Weinhold		ssize_t bytesRead = fInput->Read(fBuffer + fBufferSize,
198dcdc33b0SIngo Weinhold			fBufferCapacity - fBufferSize);
199dcdc33b0SIngo Weinhold		if (bytesRead < 0)
200dcdc33b0SIngo Weinhold			return bytesRead;
201dcdc33b0SIngo Weinhold		if (bytesRead == 0) {
202dcdc33b0SIngo Weinhold			fEndOfInput = true;
203dcdc33b0SIngo Weinhold			break;
204dcdc33b0SIngo Weinhold		}
205dcdc33b0SIngo Weinhold
206dcdc33b0SIngo Weinhold		fBufferSize += bytesRead;
207dcdc33b0SIngo Weinhold	}
208dcdc33b0SIngo Weinhold
209dcdc33b0SIngo Weinhold	// If we've reached the end of the input and still have room in the output
210dcdc33b0SIngo Weinhold	// buffer, we have consumed all input data and want to flush all pending
211dcdc33b0SIngo Weinhold	// data, now.
212dcdc33b0SIngo Weinhold	if (fEndOfInput && bytesRemaining > 0 && !fNoMorePendingData) {
213dcdc33b0SIngo Weinhold		size_t bytesProduced;
214dcdc33b0SIngo Weinhold		status_t error = FlushPendingData(output, bytesRemaining,
215dcdc33b0SIngo Weinhold			bytesProduced);
216dcdc33b0SIngo Weinhold		if (error != B_OK)
217dcdc33b0SIngo Weinhold			return error;
218dcdc33b0SIngo Weinhold
219dcdc33b0SIngo Weinhold		if (bytesProduced < bytesRemaining)
220dcdc33b0SIngo Weinhold			fNoMorePendingData = true;
221dcdc33b0SIngo Weinhold
222dcdc33b0SIngo Weinhold		output += bytesProduced;
223dcdc33b0SIngo Weinhold		bytesRemaining -= bytesProduced;
224dcdc33b0SIngo Weinhold	}
225dcdc33b0SIngo Weinhold
226dcdc33b0SIngo Weinhold	return size - bytesRemaining;
227dcdc33b0SIngo Weinhold}
228dcdc33b0SIngo Weinhold
229dcdc33b0SIngo Weinhold
230dcdc33b0SIngo Weinhold// #pragma mark - BAbstractOutputStream
231dcdc33b0SIngo Weinhold
232dcdc33b0SIngo Weinhold
233dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractOutputStream::BAbstractOutputStream(
234dcdc33b0SIngo Weinhold		BDataIO* output)
235dcdc33b0SIngo Weinhold	:
236dcdc33b0SIngo Weinhold	BAbstractStream(),
237dcdc33b0SIngo Weinhold	fOutput(output)
238dcdc33b0SIngo Weinhold{
239dcdc33b0SIngo Weinhold}
240dcdc33b0SIngo Weinhold
241dcdc33b0SIngo Weinhold
242dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractOutputStream::~BAbstractOutputStream()
243dcdc33b0SIngo Weinhold{
244dcdc33b0SIngo Weinhold}
245dcdc33b0SIngo Weinhold
246dcdc33b0SIngo Weinhold
247dcdc33b0SIngo Weinholdssize_t
248dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractOutputStream::Write(const void* buffer,
249dcdc33b0SIngo Weinhold	size_t size)
250dcdc33b0SIngo Weinhold{
251dcdc33b0SIngo Weinhold	if (size == 0)
252dcdc33b0SIngo Weinhold		return 0;
253dcdc33b0SIngo Weinhold
254dcdc33b0SIngo Weinhold	size_t bytesRemaining = size;
255dcdc33b0SIngo Weinhold	uint8* input = (uint8*)buffer;
256dcdc33b0SIngo Weinhold
257dcdc33b0SIngo Weinhold	while (bytesRemaining > 0) {
258dcdc33b0SIngo Weinhold		// try to process more data
259dcdc33b0SIngo Weinhold		if (fBufferSize < fBufferCapacity) {
260dcdc33b0SIngo Weinhold			size_t bytesConsumed;
261dcdc33b0SIngo Weinhold			size_t bytesProduced;
262dcdc33b0SIngo Weinhold			status_t error = ProcessData(input, bytesRemaining,
263dcdc33b0SIngo Weinhold				fBuffer + fBufferSize, fBufferCapacity - fBufferSize,
264dcdc33b0SIngo Weinhold				bytesConsumed, bytesProduced);
265dcdc33b0SIngo Weinhold			if (error != B_OK)
266dcdc33b0SIngo Weinhold				return error;
267dcdc33b0SIngo Weinhold
268dcdc33b0SIngo Weinhold			input += bytesConsumed;
269dcdc33b0SIngo Weinhold			bytesRemaining -= bytesConsumed;
270dcdc33b0SIngo Weinhold			fBufferSize += bytesProduced;
271dcdc33b0SIngo Weinhold			continue;
272dcdc33b0SIngo Weinhold		}
273dcdc33b0SIngo Weinhold
274dcdc33b0SIngo Weinhold		// We couldn't process anything, because we don't have any or not enough
275dcdc33b0SIngo Weinhold		// room in the output buffer.
276dcdc33b0SIngo Weinhold
277dcdc33b0SIngo Weinhold		if (fBufferSize == 0)
278dcdc33b0SIngo Weinhold			return B_ERROR;
279dcdc33b0SIngo Weinhold
280dcdc33b0SIngo Weinhold		// write to the target
281dcdc33b0SIngo Weinhold		ssize_t bytesWritten = fOutput->Write(fBuffer, fBufferSize);
282dcdc33b0SIngo Weinhold		if (bytesWritten < 0)
283dcdc33b0SIngo Weinhold			return bytesWritten;
284dcdc33b0SIngo Weinhold		if (bytesWritten == 0)
285dcdc33b0SIngo Weinhold			break;
286dcdc33b0SIngo Weinhold
287dcdc33b0SIngo Weinhold		// Move any remaining data to the start of the buffer.
288dcdc33b0SIngo Weinhold		fBufferSize -= bytesWritten;
289dcdc33b0SIngo Weinhold		if (fBufferSize > 0)
290dcdc33b0SIngo Weinhold			memmove(fBuffer, fBuffer + bytesWritten, fBufferSize);
291dcdc33b0SIngo Weinhold	}
292dcdc33b0SIngo Weinhold
293dcdc33b0SIngo Weinhold	return size - bytesRemaining;
294dcdc33b0SIngo Weinhold}
295dcdc33b0SIngo Weinhold
296dcdc33b0SIngo Weinhold
297dcdc33b0SIngo Weinholdstatus_t
298dcdc33b0SIngo WeinholdBCompressionAlgorithm::BAbstractOutputStream::Flush()
299dcdc33b0SIngo Weinhold{
300dcdc33b0SIngo Weinhold	bool noMorePendingData = false;
301dcdc33b0SIngo Weinhold
302dcdc33b0SIngo Weinhold	for (;;) {
303dcdc33b0SIngo Weinhold		// let the derived class flush all pending data
304dcdc33b0SIngo Weinhold		if (fBufferSize < fBufferCapacity && !noMorePendingData) {
305dcdc33b0SIngo Weinhold			size_t bytesProduced;
306dcdc33b0SIngo Weinhold			status_t error = FlushPendingData(fBuffer + fBufferSize,
307dcdc33b0SIngo Weinhold				fBufferCapacity - fBufferSize, bytesProduced);
308dcdc33b0SIngo Weinhold			if (error != B_OK)
309dcdc33b0SIngo Weinhold				return error;
310dcdc33b0SIngo Weinhold
311dcdc33b0SIngo Weinhold			noMorePendingData = bytesProduced < fBufferCapacity - fBufferSize;
312dcdc33b0SIngo Weinhold
313dcdc33b0SIngo Weinhold			fBufferSize += bytesProduced;
314dcdc33b0SIngo Weinhold		}
315dcdc33b0SIngo Weinhold
316dcdc33b0SIngo Weinhold		// write buffered data to output
317dcdc33b0SIngo Weinhold		if (fBufferSize == 0)
318dcdc33b0SIngo Weinhold			break;
319dcdc33b0SIngo Weinhold
320dcdc33b0SIngo Weinhold		status_t error = fOutput->WriteExactly(fBuffer, fBufferSize);
321dcdc33b0SIngo Weinhold		if (error != B_OK)
322dcdc33b0SIngo Weinhold			return error;
323dcdc33b0SIngo Weinhold
324dcdc33b0SIngo Weinhold		fBufferSize = 0;
325dcdc33b0SIngo Weinhold	}
326dcdc33b0SIngo Weinhold
327dcdc33b0SIngo Weinhold	return fOutput->Flush();
328dcdc33b0SIngo Weinhold}
329