diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8ac5f51..51fab87 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -71,6 +71,6 @@ if("${CMAKE_BUILD_TYPE}" MATCHES "Release")
endif()
endif()
-add_library("Aaru.Compression.Native" SHARED library.c)
+add_library("Aaru.Compression.Native" SHARED library.c apple_rle.c apple_rle.h)
-#add_subdirectory(tests)
+add_subdirectory(tests)
diff --git a/apple_rle.c b/apple_rle.c
new file mode 100644
index 0000000..779b178
--- /dev/null
+++ b/apple_rle.c
@@ -0,0 +1,97 @@
+/*
+ * This file is part of the Aaru Data Preservation Suite.
+ * Copyright (c) 2019-2021 Natalia Portillo.
+ * Copyright © 2018-2019 David Ryskalczyk
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include
+#include
+
+#include "library.h"
+#include "apple_rle.h"
+
+// readonly Stream _inStream;
+static int32_t count;
+static bool nextA; // true if A, false if B
+static uint8_t repeatedByteA, repeatedByteB;
+static bool repeatMode; // true if we're repeating, false if we're just copying
+
+/// Initializes a decompressor for the specified stream
+/// Stream containing the compressed data
+AARU_EXPORT void AARU_CALL apple_rle_reset()
+{
+ repeatedByteA = repeatedByteB = 0;
+ count = 0;
+ nextA = true;
+ repeatMode = false;
+}
+
+/// Decompresses a byte
+/// Decompressed byte
+AARU_EXPORT int32_t AARU_CALL apple_rle_produce_byte(const uint8_t* buffer, int32_t length, int32_t* position)
+{
+ if(repeatMode && count > 0)
+ {
+ count--;
+
+ if(nextA)
+ {
+ nextA = false;
+
+ return repeatedByteA;
+ }
+
+ nextA = true;
+
+ return repeatedByteB;
+ }
+
+ if(!repeatMode && count > 0)
+ {
+ count--;
+
+ return buffer[(*position)++];
+ }
+
+ if(*position == length) return -1;
+
+ while(true)
+ {
+ uint8_t b1 = buffer[(*position)++];
+ uint8_t b2 = buffer[(*position)++];
+ int16_t s = (int16_t)((b1 << 8) | b2);
+
+ if(s == 0 || s >= DART_CHUNK || s <= -DART_CHUNK) continue;
+
+ if(s < 0)
+ {
+ repeatMode = true;
+ repeatedByteA = buffer[(*position)++];
+ repeatedByteB = buffer[(*position)++];
+ count = (-s * 2) - 1;
+ nextA = false;
+
+ return repeatedByteA;
+ }
+
+ if(s <= 0) continue;
+
+ repeatMode = false;
+ count = (s * 2) - 1;
+
+ return buffer[(*position)++];
+ }
+}
\ No newline at end of file
diff --git a/apple_rle.h b/apple_rle.h
new file mode 100644
index 0000000..eb34403
--- /dev/null
+++ b/apple_rle.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the Aaru Data Preservation Suite.
+ * Copyright (c) 2019-2021 Natalia Portillo.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#ifndef AARU_CHECKSUMS_NATIVE__APPLE_RLE_H_
+#define AARU_CHECKSUMS_NATIVE__APPLE_RLE_H_
+
+#define DART_CHUNK 20960
+
+AARU_EXPORT void AARU_CALL apple_rle_reset();
+AARU_EXPORT int32_t AARU_CALL apple_rle_produce_byte(const uint8_t* buffer, int32_t length, int32_t* position);
+
+#endif // AARU_CHECKSUMS_NATIVE__APPLE_RLE_H_
diff --git a/library.c b/library.c
index 88c44ad..ab0a059 100644
--- a/library.c
+++ b/library.c
@@ -1,7 +1,23 @@
-#include "library.h"
+/*
+ * This file is part of the Aaru Data Preservation Suite.
+ * Copyright (c) 2019-2021 Natalia Portillo.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
#include
-void hello(void) {
- printf("Hello, World!\n");
-}
+#include "library.h"
+
+void hello(void) { printf("Hello, World!\n"); }
diff --git a/library.h b/library.h
index da98fba..f747260 100644
--- a/library.h
+++ b/library.h
@@ -1,5 +1,57 @@
+/*
+ * This file is part of the Aaru Data Preservation Suite.
+ * Copyright (c) 2019-2021 Natalia Portillo.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
#ifndef AARU_COMPRESSION_NATIVE_LIBRARY_H
#define AARU_COMPRESSION_NATIVE_LIBRARY_H
+#ifdef __cplusplus
+#define EXTERNC extern "C"
+#else
+#define EXTERNC
+#endif
-#endif//AARU_COMPRESSION_NATIVE_LIBRARY_H
+#if defined(_WIN32)
+#define AARU_CALL __stdcall
+#define AARU_EXPORT EXTERNC __declspec(dllexport)
+#define AARU_LOCAL
+#ifndef PATH_MAX
+#define PATH_MAX _MAX_PATH
+#endif
+#else
+#define AARU_CALL
+#if defined(__APPLE__)
+#define AARU_EXPORT EXTERNC __attribute__((visibility("default")))
+#define AARU_LOCAL __attribute__((visibility("hidden")))
+#else
+#if __GNUC__ >= 4
+#define AARU_EXPORT EXTERNC __attribute__((visibility("default")))
+#define AARU_LOCAL __attribute__((visibility("hidden")))
+#else
+#define AARU_EXPORT EXTERNC
+#define AARU_LOCAL
+#endif
+#endif
+#endif
+
+#ifdef _MSC_VER
+#define FORCE_INLINE static inline
+#else
+#define FORCE_INLINE static inline __attribute__((always_inline))
+#endif
+
+#endif // AARU_COMPRESSION_NATIVE_LIBRARY_H
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 8932429..324d45d 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -9,7 +9,10 @@ project(tests)
add_subdirectory(lib)
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/apple_rle.bin
+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
+
# 'Google_Tests_run' is the target name
# 'test1.cpp tests2.cpp' are source files with tests
-add_executable(tests_run "")
+add_executable(tests_run apple_rle.cpp crc32.c crc32.h)
target_link_libraries(tests_run gtest gtest_main "Aaru.Compression.Native")
diff --git a/tests/apple_rle.cpp b/tests/apple_rle.cpp
new file mode 100644
index 0000000..4216e1f
--- /dev/null
+++ b/tests/apple_rle.cpp
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the Aaru Data Preservation Suite.
+ * Copyright (c) 2019-2021 Natalia Portillo.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include
+#include
+#include
+
+#include "../library.h"
+#include "../apple_rle.h"
+#include "crc32.h"
+#include "gtest/gtest.h"
+
+#define EXPECTED_CRC32 0x3525ef06
+
+static const uint8_t* buffer;
+
+class apple_rleFixture : public ::testing::Test
+{
+ public:
+ apple_rleFixture()
+ {
+ // initialization;
+ // can also be done in SetUp()
+ }
+
+ protected:
+ void SetUp()
+ {
+ char path[PATH_MAX];
+ char filename[PATH_MAX];
+
+ getcwd(path, PATH_MAX);
+ snprintf(filename, PATH_MAX, "%s/data/apple_rle.bin", path);
+
+ FILE* file = fopen(filename, "rb");
+ buffer = (const uint8_t*)malloc(1102);
+ fread((void*)buffer, 1, 1102, file);
+ fclose(file);
+ }
+
+ void TearDown() {
+ free((void*)buffer);
+ }
+
+ ~apple_rleFixture()
+ {
+ // resources cleanup, no exceptions allowed
+ }
+
+ // shared user data
+};
+
+TEST_F(apple_rleFixture, apple_rle)
+{
+ auto *outBuf = (uint8_t*)malloc(20960);
+int32_t position = 0;
+
+ apple_rle_reset();
+
+ for(int i = 0; i < 20960; i++)
+ outBuf[i] = (uint8_t)apple_rle_produce_byte(buffer, 1102, &position);
+
+ auto crc = crc32_data(outBuf, 20960);
+
+ free(outBuf);
+
+ EXPECT_EQ(crc, EXPECTED_CRC32);
+}
diff --git a/tests/crc32.c b/tests/crc32.c
new file mode 100644
index 0000000..4eac7fc
--- /dev/null
+++ b/tests/crc32.c
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the Aaru Data Preservation Suite.
+ * Copyright (c) 2019-2021 Natalia Portillo.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include
+
+#define CRC32_ISO_POLY 0xEDB88320
+#define CRC32_ISO_SEED 0xFFFFFFFF
+
+uint32_t crc32_data(const uint8_t *data, uint32_t len)
+{
+ uint32_t localHashInt = CRC32_ISO_SEED;
+ uint32_t localTable[256];
+ int i, j;
+
+ for(i = 0; i < 256; i++)
+ {
+ uint32_t entry = (uint32_t)i;
+
+ for(j = 0; j < 8; j++)
+ if((entry & 1) == 1)
+ entry = (entry >> 1) ^ CRC32_ISO_POLY;
+ else
+ entry >>= 1;
+
+ localTable[i] = entry;
+ }
+
+ for(i = 0; i < len; i++)
+ localHashInt = (localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)];
+
+ localHashInt ^= CRC32_ISO_SEED;
+
+ return localHashInt;
+}
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/tests/crc32.h b/tests/crc32.h
new file mode 100644
index 0000000..3c70824
--- /dev/null
+++ b/tests/crc32.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the Aaru Data Preservation Suite.
+ * Copyright (c) 2019-2021 Natalia Portillo.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#ifndef AARU_CHECKSUMS_NATIVE_TESTS_CRC32_H_
+#define AARU_CHECKSUMS_NATIVE_TESTS_CRC32_H_
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ uint32_t crc32_data(const uint8_t* data, uint32_t len);
+#ifdef __cplusplus
+}
+#endif
+#endif // AARU_CHECKSUMS_NATIVE_TESTS_CRC32_H_
diff --git a/tests/data/apple_rle.bin b/tests/data/apple_rle.bin
new file mode 100644
index 0000000..8789ec5
Binary files /dev/null and b/tests/data/apple_rle.bin differ