** DeltaRowCompression.cpp
** Copyright 2005, Michael Pfeiffer, laplace@users.sourceforge.net.
** All rights reserved.
** Distributed under the terms of the MIT License.
*/
#include "DeltaRowCompression.h"
#include <memory.h>
#include <SupportDefs.h>
AbstractDeltaRowCompressor::AbstractDeltaRowCompressor(int rowSize,
uchar initialSeed)
:
fSeedRow(new uchar[rowSize]),
fSize(rowSize),
fInitialSeed(initialSeed)
{
Reset();
}
AbstractDeltaRowCompressor::~AbstractDeltaRowCompressor()
{
delete[] fSeedRow;
fSeedRow = NULL;
}
status_t
AbstractDeltaRowCompressor::InitCheck()
{
if (fSeedRow != NULL)
return B_OK;
else
return B_NO_MEMORY;
}
void
AbstractDeltaRowCompressor::Reset()
{
if (fSeedRow != NULL)
memset(fSeedRow, fInitialSeed, fSize);
}
int
AbstractDeltaRowCompressor::CompressRaw(const uchar* row, bool updateSeedRow,
bool updateDeltaRow)
{
int index = DiffersIndex(row, 0);
if (index == -1) {
return 0;
}
fUpdateDeltaRow = updateDeltaRow;
fDeltaRowIndex = 0;
int seedRowIndex = 0;
do {
int length = DiffersLength(row, index);
do {
int deltaBytes = length;
if (length > 8)
deltaBytes = 8;
int totalOffset = index - seedRowIndex;
bool needsOffsetBytes = totalOffset > 30;
int offset = totalOffset;
if (needsOffsetBytes)
offset = 31;
Put(((deltaBytes - 1) << 5) | offset);
if (needsOffsetBytes) {
totalOffset -= offset;
while (totalOffset >= 255) {
Put(255);
totalOffset -= 255;
}
Put(totalOffset);
}
for (int i = 0; i < deltaBytes; i ++) {
uchar byte = row[index];
if (updateSeedRow) {
ASSERT (index < fSize);
fSeedRow[index] = byte;
}
Put(byte);
index ++;
}
seedRowIndex = index;
length -= deltaBytes;
} while (length > 0);
index = DiffersIndex(row, index);
} while (index != -1);
return fDeltaRowIndex;
}
int
AbstractDeltaRowCompressor::CalculateSize(const uchar* row, bool updateSeedRow)
{
return CompressRaw(row, updateSeedRow, false);
}
void
AbstractDeltaRowCompressor::Compress(const uchar* row)
{
CompressRaw(row, true, true);
}
#ifdef TEST_DELTA_ROW_COMPRESSION
void
test(AbstractDeltaRowCompressor* compressor, uchar* row) {
int size = compressor->CalculateSize(row);
printf("size %d\n", size);
if (size > 0) {
uchar* buffer = new uchar[size];
compressor->Compress(row, buffer, size);
for (int i = 0; i < size; i ++) {
printf("%2.2x ", (int)buffer[i]);
}
printf("\n");
delete buffer;
}
printf("\n");
}
int
main(int argc, char* argv[])
{
int n = 5;
uchar row1[] = {0, 0, 0, 0, 0};
uchar row2[] = {0, 1, 0, 0, 0};
uchar row3[] = {1, 1, 0, 2, 2};
DeltaRowCompressor compressor(n, 0);
test(&compressor, row1);
test(&compressor, row2);
test(&compressor, row3);
}
#endif