diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index c0acd7cbf..0c7d4fda2 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -85,5 +85,5 @@ FetchContent_MakeAvailable(Corrosion) corrosion_import_crate(MANIFEST_PATH ../rust/Cargo.toml) # Build and link our app's native lib -add_library(${PROJECT_NAME} SHARED archive.c border.c gifutils.c natsort/strnatcmp.c) +add_library(${PROJECT_NAME} SHARED archive.c border.c gifutils.c hash.c natsort/strnatcmp.c) target_link_libraries(${PROJECT_NAME} ehviewer_rust archive_static log jnigraphics) diff --git a/app/src/main/cpp/hash.c b/app/src/main/cpp/hash.c new file mode 100644 index 000000000..1a199b934 --- /dev/null +++ b/app/src/main/cpp/hash.c @@ -0,0 +1,39 @@ +#include + +#include +#include + +#include "ehviewer.h" + +#define BUFFER_SIZE 8192 + +typedef uint8_t byte; + +const char hex_digits[] = "0123456789abcdef"; + +JNIEXPORT jstring JNICALL +Java_com_hippo_ehviewer_jni_HashKt_sha1(JNIEnv *env, jclass clazz, jint fd) { + EH_UNUSED(clazz); + struct sha1_ctx ctx; + sha1_init(&ctx); + + size_t bytes_read; + byte buffer[BUFFER_SIZE]; + while ((bytes_read = read(fd, buffer, BUFFER_SIZE)) > 0) { + sha1_update(&ctx, bytes_read, buffer); + } + + byte digest[SHA1_DIGEST_SIZE]; + sha1_digest(&ctx, SHA1_DIGEST_SIZE, digest); + + byte byte; + char hex_digest[2 * SHA1_DIGEST_SIZE + 1]; + for (int i = 0; i < SHA1_DIGEST_SIZE; i++) { + byte = digest[i]; + hex_digest[2 * i] = hex_digits[byte >> 4 & 0xF]; + hex_digest[2 * i + 1] = hex_digits[byte & 0xF]; + } + hex_digest[2 * SHA1_DIGEST_SIZE] = '\0'; + + return (*env)->NewStringUTF(env, hex_digest); +} diff --git a/app/src/main/kotlin/com/hippo/ehviewer/jni/Hash.kt b/app/src/main/kotlin/com/hippo/ehviewer/jni/Hash.kt new file mode 100644 index 000000000..d0ddcece1 --- /dev/null +++ b/app/src/main/kotlin/com/hippo/ehviewer/jni/Hash.kt @@ -0,0 +1,3 @@ +package com.hippo.ehviewer.jni + +external fun sha1(fd: Int): String diff --git a/app/src/main/kotlin/com/hippo/unifile/UniFileExtensions.kt b/app/src/main/kotlin/com/hippo/unifile/UniFileExtensions.kt index d0fe372d0..5c136051b 100644 --- a/app/src/main/kotlin/com/hippo/unifile/UniFileExtensions.kt +++ b/app/src/main/kotlin/com/hippo/unifile/UniFileExtensions.kt @@ -5,15 +5,11 @@ import android.os.Environment import android.os.ParcelFileDescriptor.AutoCloseInputStream import android.os.ParcelFileDescriptor.AutoCloseOutputStream import android.provider.DocumentsContract -import eu.kanade.tachiyomi.util.system.logcat +import com.hippo.ehviewer.jni.sha1 import java.io.File import java.io.FileInputStream import java.io.FileOutputStream -import okio.HashingSink import okio.Path -import okio.blackholeSink -import okio.buffer -import okio.source /** * Use Native IO/NIO directly if possible, unless you need process file content on JVM! @@ -29,17 +25,7 @@ fun UniFile.openOutputStream(): FileOutputStream { return AutoCloseOutputStream(openFileDescriptor("w")) } -fun UniFile.sha1() = runCatching { - openInputStream().source().buffer().use { source -> - HashingSink.sha1(blackholeSink()).use { - source.readAll(it) - it.hash.hex() - } - } -}.getOrElse { - logcat(it) - null -} +fun UniFile.sha1() = openFileDescriptor("r").use { sha1(it.fd) } fun File.asUniFile() = UniFile.fromFile(this)