Change Apple RLE algorithm for a faster version.

This commit is contained in:
2021-10-17 01:11:43 +01:00
parent 63a3c6475b
commit 722175d2ae
3 changed files with 63 additions and 64 deletions

View File

@@ -23,55 +23,51 @@
#include "library.h" #include "library.h"
#include "apple_rle.h" #include "apple_rle.h"
// readonly Stream _inStream; AARU_EXPORT int32_t AARU_CALL apple_rle_decode_buffer(uint8_t* dst_buffer,
static int32_t count; int32_t dst_size,
static bool nextA; // true if A, false if B const uint8_t* src_buffer,
static uint8_t repeatedByteA, repeatedByteB; int32_t src_size)
static bool repeatMode; // true if we're repeating, false if we're just copying
/// <summary>Initializes a decompressor for the specified stream</summary>
/// <param name="stream">Stream containing the compressed data</param>
AARU_EXPORT void AARU_CALL apple_rle_reset()
{ {
repeatedByteA = repeatedByteB = 0; static int32_t count = 0;
count = 0; static bool nextA = true; // true if A, false if B
nextA = true; static uint8_t repeatedByteA = 0, repeatedByteB = 0;
repeatMode = false; static bool repeatMode = false; // true if we're repeating, false if we're just copying
} int32_t in_pos = 0, out_pos = 0;
/// <summary>Decompresses a byte</summary> while(in_pos <= src_size && out_pos <= dst_size)
/// <returns>Decompressed byte</returns> {
AARU_EXPORT int32_t AARU_CALL apple_rle_produce_byte(const uint8_t* buffer, int32_t length, int32_t* position)
{
if(repeatMode && count > 0) if(repeatMode && count > 0)
{ {
count--; (count)--;
if(nextA) if(nextA)
{ {
nextA = false; nextA = false;
return repeatedByteA; dst_buffer[out_pos++] = repeatedByteA;
continue;
} }
nextA = true; nextA = true;
return repeatedByteB; dst_buffer[out_pos++] = repeatedByteB;
continue;
} }
if(!repeatMode && count > 0) if(!repeatMode && count > 0)
{ {
count--; count--;
return buffer[(*position)++]; dst_buffer[out_pos++] = src_buffer[in_pos++];
continue;
} }
if(*position == length) return -1; if(in_pos == src_size) break;
while(true) while(true)
{ {
uint8_t b1 = buffer[(*position)++]; uint8_t b1 = src_buffer[in_pos++];
uint8_t b2 = buffer[(*position)++]; uint8_t b2 = src_buffer[in_pos++];
int16_t s = (int16_t)((b1 << 8) | b2); int16_t s = (int16_t)((b1 << 8) | b2);
if(s == 0 || s >= DART_CHUNK || s <= -DART_CHUNK) continue; if(s == 0 || s >= DART_CHUNK || s <= -DART_CHUNK) continue;
@@ -79,19 +75,22 @@ AARU_EXPORT int32_t AARU_CALL apple_rle_produce_byte(const uint8_t* buffer, int3
if(s < 0) if(s < 0)
{ {
repeatMode = true; repeatMode = true;
repeatedByteA = buffer[(*position)++]; repeatedByteA = src_buffer[in_pos++];
repeatedByteB = buffer[(*position)++]; repeatedByteB = src_buffer[in_pos++];
count = (-s * 2) - 1; count = (-s * 2) - 1;
nextA = false; nextA = false;
return repeatedByteA; dst_buffer[out_pos++] = repeatedByteA;
break;
} }
if(s <= 0) continue;
repeatMode = false; repeatMode = false;
count = (s * 2) - 1; count = (s * 2) - 1;
return buffer[(*position)++]; dst_buffer[out_pos++] = src_buffer[in_pos++];
break;
} }
}
return out_pos;
} }

View File

@@ -21,7 +21,9 @@
#define DART_CHUNK 20960 #define DART_CHUNK 20960
AARU_EXPORT void AARU_CALL apple_rle_reset(); AARU_EXPORT int32_t AARU_CALL apple_rle_decode_buffer(uint8_t* dst_buffer,
AARU_EXPORT int32_t AARU_CALL apple_rle_produce_byte(const uint8_t* buffer, int32_t length, int32_t* position); int32_t dst_size,
const uint8_t* src_buffer,
int32_t src_size);
#endif // AARU_CHECKSUMS_NATIVE__APPLE_RLE_H_ #endif // AARU_CHECKSUMS_NATIVE__APPLE_RLE_H_

View File

@@ -67,13 +67,11 @@ class apple_rleFixture : public ::testing::Test
TEST_F(apple_rleFixture, apple_rle) TEST_F(apple_rleFixture, apple_rle)
{ {
auto *outBuf = (uint8_t*)malloc(20960); auto *outBuf = (uint8_t*)malloc(32768);
int32_t position = 0;
apple_rle_reset(); auto decoded = apple_rle_decode_buffer(outBuf, 32768, buffer, 1102);
for(int i = 0; i < 20960; i++) EXPECT_EQ(decoded, 20960);
outBuf[i] = (uint8_t)apple_rle_produce_byte(buffer, 1102, &position);
auto crc = crc32_data(outBuf, 20960); auto crc = crc32_data(outBuf, 20960);