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