mirror of https://github.com/bsnes-emu/bsnes.git
51 lines
1.1 KiB
C++
51 lines
1.1 KiB
C++
#pragma once
|
|
|
|
namespace nall { namespace Encode {
|
|
|
|
template<typename T> inline auto RLE(const void* data_, uint size, uint minimum = 0) -> vector<uint8_t> {
|
|
if(!minimum) minimum = max(1, 4 / sizeof(T));
|
|
vector<uint8_t> result;
|
|
|
|
auto data = (const T*)data_;
|
|
uint base = 0;
|
|
uint skip = 0;
|
|
|
|
for(uint byte : range(sizeof(uint))) result.append(size * sizeof(T) >> byte * 8);
|
|
|
|
auto read = [&](uint offset) -> T {
|
|
if(offset >= size) return {};
|
|
return data[offset];
|
|
};
|
|
|
|
auto write = [&](T value) -> void {
|
|
for(uint byte : range(sizeof(T))) result.append(value >> byte * 8);
|
|
};
|
|
|
|
auto flush = [&]() -> void {
|
|
result.append(skip - 1);
|
|
do { write(read(base++)); } while(--skip);
|
|
};
|
|
|
|
while(base + skip < size) {
|
|
uint same = 1;
|
|
for(uint offset = base + skip + 1; offset < size; offset++) {
|
|
if(read(offset) != read(base + skip)) break;
|
|
if(++same == 127 + minimum) break;
|
|
}
|
|
|
|
if(same < minimum) {
|
|
if(++skip == 128) flush();
|
|
} else {
|
|
if(skip) flush();
|
|
result.append(128 | same - minimum);
|
|
write(read(base));
|
|
base += same;
|
|
}
|
|
}
|
|
if(skip) flush();
|
|
|
|
return result;
|
|
}
|
|
|
|
}}
|