|
#include <memory.h>
namespace Mm {
template <class FieldType, size_t WindowSize = sizeof(FieldType) * 8>
struct RleCodeBlock {
enum { windowSize = WindowSize };
inline bool Bit(size_t shift) { return ((FieldType)(1 << shift) & descriptor) != 0; }
inline void ClearBit(size_t shift) { descriptor &= ~(FieldType)(1 << shift); }
inline void SetBit(size_t shift) { descriptor |= (FieldType)(1 << shift); }
FieldType descriptor;
FieldType fields[WindowSize - 1];
bool Decode(FieldType*& buf, unsigned long& count)
{
FieldType len = 1;
for (unsigned char i = 0; i < (windowSize - 1); ++ i) {
if (Bit(i)) {
if (fields[i]) for (FieldType j = 0; j < len; ++j) *(buf++) = fields[i];
else buf += len;
count += len; // added len bytes
len = 1; // reset len
} else {
len = fields[i];
if (len == 0) return false;
}
}
return true;
}
bool Encode(FieldType*& buf, unsigned long& count)
{
const unsigned char limit = (windowSize - 2);
bool more = true;
const unsigned long lenMax = (1 << (sizeof(FieldType) * 8)) - 1;
for (unsigned char i = 0; i < (windowSize - 1); ++i) {
if (count == 0) {
ClearBit(i);
fields[i] = 0;
more = false;
break;
}
FieldType* end = buf + 1;
FieldType len = 1;
if (i < limit) {
while ((len < count) && (len < lenMax) && (*end == *buf)) {
++end;
++len;
}
}
switch (len) {
default:
ClearBit(i);
fields[i] = len;
++i;
case 1:
SetBit(i);
fields[i] = *buf;
}
buf += len;
count -= len;
}
return more;
}
size_t Write(FieldType*& buf)
{
const FieldType* start = buf;
*(buf++) = descriptor;
for (size_t i = 0; i < (windowSize - 1); ++i) {
*(buf++) = fields[i];
if (!Bit(i) && !fields[i]) break;
}
if (buf - start > windowSize) throw;
return buf - start;
}
bool DecodeAsDelta(FieldType*& buf, unsigned long& count)
{
FieldType len = 1;
for (unsigned char i = 0; i < (windowSize - 1); ++ i) {
if (Bit(i)) {
if (fields[i]) for (FieldType j = 0; j < len; ++j) *(buf++) ^= fields[i];
else buf += len;
count += len; // added len bytes
len = 1; // reset len
} else {
len = fields[i];
if (len == 0) return false;
}
}
return true;
}
};
typedef unsigned short FieldType;
typedef RleCodeBlock<FieldType> BlockType;
int Compress(void* in, void* out)
{
BlockType block;
FieldType* inc = (FieldType*)in;
FieldType* outc = (FieldType*)out;
unsigned long in_count = 4096 / sizeof(FieldType);
unsigned long out_count = 0;
bool more = false;
do {
more = block.Encode(inc, in_count);
unsigned long c = block.Write(outc);
out_count += c * sizeof(FieldType);
} while (more);
return out_count;
}
int Decompress(void* in, void* out)
{
unsigned long count = 0;
BlockType* block = (BlockType*)in;
FieldType* buf = (FieldType*)out;
while (block->Decode(buf, count) && (count * sizeof(FieldType) < 4096))
++block;
return count;
}
int ApplyCompressedDelta(void* page, void* delta)
{
FieldType* pagec = (FieldType*)page;
unsigned long count = 0;
BlockType* block = (BlockType*)delta;
while (block->DecodeAsDelta(pagec, count) && (count * sizeof(FieldType) < 4096))
++block;
return count;
}
};
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
A compiler warns of bogasity, ignore it at your peril. Unless you've done the compiler's job yourself, don't criticize it.