1/*
2** DeltaRowCompression.h
3** Copyright 2005, Michael Pfeiffer, laplace@users.sourceforge.net.
4** All rights reserved.
5** Distributed under the terms of the MIT License.
6*/
7#ifndef _DELTA_ROW_COMPRESSION_H
8#define _DELTA_ROW_COMPRESSION_H
9
10
11#include <Debug.h>
12
13
14class AbstractDeltaRowCompressor {
15public:
16						AbstractDeltaRowCompressor(int rowSize,
17							uchar initialSeed);
18	virtual				~AbstractDeltaRowCompressor();
19
20	// InitCheck returns B_OK on successful construction of this object or
21	// B_NO_MEMORY if the buffer for the seed row could not be allocated.
22			status_t	InitCheck();
23
24	// Clears the seed row to the initial seed specified in the constructor
25			void		Reset();
26
27	// Returns the size of the delta row.
28	// The size is 0 if the row is equal to the seed row (previous row).
29	// The seed row is updated only if updateSeedRow is true.
30			int			CalculateSize(const uchar* row,
31							bool updateSeedRow = false);
32
33	// Compresses the row using the delta row compression algorithm.
34	// The seed row is updated.
35			void		Compress(const uchar* row);
36
37protected:
38	// append byte to delta row
39	virtual	void		AppendByteToDeltaRow(uchar byte) = 0;
40
41	// returns the current size of the delta row
42	inline	int			CurrentDeltaRowSize()
43						{
44							return fDeltaRowIndex;
45						}
46
47private:
48	// Returns the index where seed row and row differ
49	// or -1 if both arrays are equal.
50	inline	int			DiffersIndex(const uchar* row, int index)
51						{
52							while (index < fSize) {
53								if (fSeedRow[index] != row[index])
54									return index;
55								index ++;
56							}
57							return -1;
58						}
59
60	// Returns the number of bytes that row differs from seed row
61	// starting at the specified index.
62	inline	int			DiffersLength(const uchar* row, int index)
63						{
64							int startIndex = index;
65							while (index < fSize) {
66								if (fSeedRow[index] == row[index])
67									break;
68								index ++;
69							}
70							return index - startIndex;
71						}
72
73	// Compresses row with delta row compression algorithm.
74	// The seed row is updated only if updateSeedRow is true.
75	// If updateDeltaRow is true the method AppendByteToDeltaRow is called.
76			int 		CompressRaw(const uchar* row, bool updateSeedRow,
77							bool updateDeltaRow);
78
79	// write byte to delta row and calculate size of delta row
80			void		Put(uchar byte)
81						{
82							if (fUpdateDeltaRow)
83								AppendByteToDeltaRow(byte);
84							fDeltaRowIndex ++;
85						}
86
87			uchar*		fSeedRow; // the seed row
88			int			fSize; // the size of the seed row in bytes
89			uchar		fInitialSeed;
90							// the value to initialize the seed row with
91
92			int			fDeltaRowIndex;
93							// the index of the next byte to be written into
94							// the delta row
95			bool		fUpdateDeltaRow; // write delta row
96};
97
98
99class DeltaRowCompressor : public AbstractDeltaRowCompressor
100{
101public:
102						DeltaRowCompressor(int rowSize, uchar initialSeed)
103						:
104						AbstractDeltaRowCompressor(rowSize, initialSeed)
105						{}
106
107	// The delta row to be written to.
108			void		SetDeltaRow(uchar* deltaRow)
109						{
110							fDeltaRow = deltaRow;
111						}
112
113protected:
114	virtual	void		AppendByteToDeltaRow(uchar byte)
115						{
116							fDeltaRow[CurrentDeltaRowSize()] = byte;
117						}
118
119private:
120			uchar*		fDeltaRow; // the delta row
121};
122
123#endif
124