react-native-sherpa-onnx 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -0
- package/README.md +90 -21
- package/SherpaOnnx.podspec +3 -0
- package/THIRD_PARTY_LICENSES/README.md +62 -0
- package/THIRD_PARTY_LICENSES/ffmpeg.txt +502 -0
- package/THIRD_PARTY_LICENSES/libarchive.txt +65 -0
- package/THIRD_PARTY_LICENSES/nvidia_omla.txt +181 -0
- package/THIRD_PARTY_LICENSES/onnxruntime.txt +21 -0
- package/THIRD_PARTY_LICENSES/opus.txt +44 -0
- package/THIRD_PARTY_LICENSES/sherpa-onnx.txt +201 -0
- package/THIRD_PARTY_LICENSES/shine.txt +482 -0
- package/THIRD_PARTY_LICENSES/zstd.txt +30 -0
- package/android/build.gradle +7 -3
- package/android/prebuilt-download.gradle +345 -153
- package/android/prebuilt-versions.gradle +2 -2
- package/android/src/main/assets/model_licenses/asr-models-license-status.csv +409 -0
- package/android/src/main/assets/model_licenses/qnn-asr-models-license-status.csv +695 -0
- package/android/src/main/assets/model_licenses/tts-models-license-status.csv +596 -0
- package/android/src/main/cpp/CMakeLists.txt +28 -10
- package/android/src/main/cpp/jni/archive/sherpa-onnx-archive-helper.cpp +306 -6
- package/android/src/main/cpp/jni/archive/sherpa-onnx-archive-helper.h +33 -4
- package/android/src/main/cpp/jni/archive/sherpa-onnx-archive-jni.cpp +266 -7
- package/android/src/main/cpp/jni/audio/sherpa-onnx-audio-convert-jni.cpp +268 -2
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-tts.cpp +6 -2
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-tts.cpp +4 -2
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxArchiveHelper.kt +137 -7
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxAssetHelper.kt +51 -6
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxModule.kt +159 -0
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxOnlineSttHelper.kt +4 -1
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxTtsHelper.kt +112 -97
- package/ios/Resources/model_licenses/asr-models-license-status.csv +409 -0
- package/ios/Resources/model_licenses/qnn-asr-models-license-status.csv +695 -0
- package/ios/Resources/model_licenses/tts-models-license-status.csv +596 -0
- package/ios/SherpaOnnx+OnlineSTT.mm +2 -0
- package/ios/SherpaOnnx+PcmLiveStream.mm +2 -29
- package/ios/SherpaOnnx+TTS.mm +178 -20
- package/ios/SherpaOnnx.mm +108 -1
- package/ios/SherpaOnnxAudioConvert.h +10 -0
- package/ios/SherpaOnnxAudioConvert.mm +257 -1
- package/ios/archive/sherpa-onnx-archive-helper.h +10 -0
- package/ios/archive/sherpa-onnx-archive-helper.mm +56 -5
- package/ios/model_detect/sherpa-onnx-model-detect-tts.mm +13 -2
- package/ios/model_detect/sherpa-onnx-validate-tts.mm +4 -2
- package/ios/online_stt/sherpa-onnx-online-stt-wrapper.h +1 -0
- package/ios/online_stt/sherpa-onnx-online-stt-wrapper.mm +4 -0
- package/ios/tts/sherpa-onnx-tts-wrapper.h +37 -0
- package/ios/tts/sherpa-onnx-tts-wrapper.mm +149 -3
- package/lib/module/NativeSherpaOnnx.js.map +1 -1
- package/lib/module/audio/index.js +8 -0
- package/lib/module/audio/index.js.map +1 -1
- package/lib/module/download/ModelDownloadManager.js +10 -929
- package/lib/module/download/ModelDownloadManager.js.map +1 -1
- package/lib/module/download/activeModelOperations.js +26 -0
- package/lib/module/download/activeModelOperations.js.map +1 -0
- package/lib/module/download/background-downloader.d.js +2 -0
- package/lib/module/download/background-downloader.d.js.map +1 -0
- package/lib/module/download/bulkPurge.js +72 -0
- package/lib/module/download/bulkPurge.js.map +1 -0
- package/lib/module/download/checksumPrompt.js +19 -0
- package/lib/module/download/checksumPrompt.js.map +1 -0
- package/lib/module/download/constants.js +7 -0
- package/lib/module/download/constants.js.map +1 -0
- package/lib/module/download/downloadEvents.js +35 -0
- package/lib/module/download/downloadEvents.js.map +1 -0
- package/lib/module/download/downloadTask.js +385 -0
- package/lib/module/download/downloadTask.js.map +1 -0
- package/lib/module/download/ensureModel.js +89 -0
- package/lib/module/download/ensureModel.js.map +1 -0
- package/lib/module/download/index.js +4 -3
- package/lib/module/download/index.js.map +1 -1
- package/lib/module/download/localModels.js +151 -0
- package/lib/module/download/localModels.js.map +1 -0
- package/lib/module/download/modelExtraction.js +174 -0
- package/lib/module/download/modelExtraction.js.map +1 -0
- package/lib/module/download/paths.js +98 -0
- package/lib/module/download/paths.js.map +1 -0
- package/lib/module/download/postDownloadProcessing.js +206 -0
- package/lib/module/download/postDownloadProcessing.js.map +1 -0
- package/lib/module/download/protectedModelKeys.js +31 -0
- package/lib/module/download/protectedModelKeys.js.map +1 -0
- package/lib/module/download/registry.js +267 -0
- package/lib/module/download/registry.js.map +1 -0
- package/lib/module/download/retry.js +59 -0
- package/lib/module/download/retry.js.map +1 -0
- package/lib/module/download/types.js +17 -0
- package/lib/module/download/types.js.map +1 -0
- package/lib/module/download/validation.js +101 -5
- package/lib/module/download/validation.js.map +1 -1
- package/lib/module/{download → extraction}/extractTarBz2.js +3 -1
- package/lib/module/extraction/extractTarBz2.js.map +1 -0
- package/lib/module/extraction/extractTarZst.js +54 -0
- package/lib/module/extraction/extractTarZst.js.map +1 -0
- package/lib/module/extraction/index.js +190 -0
- package/lib/module/extraction/index.js.map +1 -0
- package/lib/module/extraction/types.js +2 -0
- package/lib/module/extraction/types.js.map +1 -0
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/licenses.js +63 -0
- package/lib/module/licenses.js.map +1 -0
- package/lib/module/stt/index.js +16 -2
- package/lib/module/stt/index.js.map +1 -1
- package/lib/module/stt/streaming.js +2 -0
- package/lib/module/stt/streaming.js.map +1 -1
- package/lib/module/stt/streamingTypes.js.map +1 -1
- package/lib/module/stt/types.js.map +1 -1
- package/lib/module/tts/index.js +20 -2
- package/lib/module/tts/index.js.map +1 -1
- package/lib/module/tts/streaming.js +4 -0
- package/lib/module/tts/streaming.js.map +1 -1
- package/lib/module/tts/types.js.map +1 -1
- package/lib/module/utils.js +16 -1
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/src/NativeSherpaOnnx.d.ts +72 -5
- package/lib/typescript/src/NativeSherpaOnnx.d.ts.map +1 -1
- package/lib/typescript/src/audio/index.d.ts +10 -0
- package/lib/typescript/src/audio/index.d.ts.map +1 -1
- package/lib/typescript/src/download/ModelDownloadManager.d.ts +10 -108
- package/lib/typescript/src/download/ModelDownloadManager.d.ts.map +1 -1
- package/lib/typescript/src/download/activeModelOperations.d.ts +6 -0
- package/lib/typescript/src/download/activeModelOperations.d.ts.map +1 -0
- package/lib/typescript/src/download/bulkPurge.d.ts +14 -0
- package/lib/typescript/src/download/bulkPurge.d.ts.map +1 -0
- package/lib/typescript/src/download/checksumPrompt.d.ts +3 -0
- package/lib/typescript/src/download/checksumPrompt.d.ts.map +1 -0
- package/lib/typescript/src/download/constants.d.ts +5 -0
- package/lib/typescript/src/download/constants.d.ts.map +1 -0
- package/lib/typescript/src/download/downloadEvents.d.ts +6 -0
- package/lib/typescript/src/download/downloadEvents.d.ts.map +1 -0
- package/lib/typescript/src/download/downloadTask.d.ts +20 -0
- package/lib/typescript/src/download/downloadTask.d.ts.map +1 -0
- package/lib/typescript/src/download/ensureModel.d.ts +26 -0
- package/lib/typescript/src/download/ensureModel.d.ts.map +1 -0
- package/lib/typescript/src/download/index.d.ts +7 -5
- package/lib/typescript/src/download/index.d.ts.map +1 -1
- package/lib/typescript/src/download/localModels.d.ts +15 -0
- package/lib/typescript/src/download/localModels.d.ts.map +1 -0
- package/lib/typescript/src/download/modelExtraction.d.ts +36 -0
- package/lib/typescript/src/download/modelExtraction.d.ts.map +1 -0
- package/lib/typescript/src/download/paths.d.ts +28 -0
- package/lib/typescript/src/download/paths.d.ts.map +1 -0
- package/lib/typescript/src/download/postDownloadProcessing.d.ts +19 -0
- package/lib/typescript/src/download/postDownloadProcessing.d.ts.map +1 -0
- package/lib/typescript/src/download/protectedModelKeys.d.ts +6 -0
- package/lib/typescript/src/download/protectedModelKeys.d.ts.map +1 -0
- package/lib/typescript/src/download/registry.d.ts +14 -0
- package/lib/typescript/src/download/registry.d.ts.map +1 -0
- package/lib/typescript/src/download/retry.d.ts +15 -0
- package/lib/typescript/src/download/retry.d.ts.map +1 -0
- package/lib/typescript/src/download/types.d.ts +96 -0
- package/lib/typescript/src/download/types.d.ts.map +1 -0
- package/lib/typescript/src/download/validation.d.ts +19 -0
- package/lib/typescript/src/download/validation.d.ts.map +1 -1
- package/lib/typescript/src/extraction/extractTarBz2.d.ts.map +1 -0
- package/lib/typescript/src/extraction/extractTarZst.d.ts +14 -0
- package/lib/typescript/src/extraction/extractTarZst.d.ts.map +1 -0
- package/lib/typescript/src/extraction/index.d.ts +50 -0
- package/lib/typescript/src/extraction/index.d.ts.map +1 -0
- package/lib/typescript/src/extraction/types.d.ts +60 -0
- package/lib/typescript/src/extraction/types.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/licenses.d.ts +10 -0
- package/lib/typescript/src/licenses.d.ts.map +1 -0
- package/lib/typescript/src/stt/index.d.ts +4 -1
- package/lib/typescript/src/stt/index.d.ts.map +1 -1
- package/lib/typescript/src/stt/streaming.d.ts.map +1 -1
- package/lib/typescript/src/stt/streamingTypes.d.ts +5 -0
- package/lib/typescript/src/stt/streamingTypes.d.ts.map +1 -1
- package/lib/typescript/src/stt/types.d.ts +3 -1
- package/lib/typescript/src/stt/types.d.ts.map +1 -1
- package/lib/typescript/src/tts/index.d.ts +3 -1
- package/lib/typescript/src/tts/index.d.ts.map +1 -1
- package/lib/typescript/src/tts/streaming.d.ts.map +1 -1
- package/lib/typescript/src/tts/types.d.ts +6 -5
- package/lib/typescript/src/tts/types.d.ts.map +1 -1
- package/lib/typescript/src/utils.d.ts +5 -0
- package/lib/typescript/src/utils.d.ts.map +1 -1
- package/package.json +11 -1
- package/scripts/{check-model-csvs.sh → ci/check-model-csvs.sh} +9 -2
- package/scripts/ci/collect_all_sherpa_model_streams.sh +101 -0
- package/scripts/ci/collect_one_sherpa_release_stream.sh +189 -0
- package/scripts/ci/sherpa_asr_model_release_streams.json +21 -0
- package/scripts/ci/sherpa_tts_model_release_streams.json +13 -0
- package/scripts/ci/update_model_license_csv.sh +765 -0
- package/scripts/setup-ios-framework.sh +14 -11
- package/scripts/update_commercial_use.js +73 -0
- package/src/NativeSherpaOnnx.ts +92 -5
- package/src/audio/index.ts +20 -0
- package/src/download/ModelDownloadManager.ts +55 -1343
- package/src/download/activeModelOperations.ts +38 -0
- package/src/download/background-downloader.d.ts +43 -0
- package/src/download/bulkPurge.ts +102 -0
- package/src/download/checksumPrompt.ts +25 -0
- package/src/download/constants.ts +5 -0
- package/src/download/downloadEvents.ts +55 -0
- package/src/download/downloadTask.ts +497 -0
- package/src/download/ensureModel.ts +124 -0
- package/src/download/index.ts +19 -2
- package/src/download/localModels.ts +234 -0
- package/src/download/modelExtraction.ts +244 -0
- package/src/download/paths.ts +134 -0
- package/src/download/postDownloadProcessing.ts +292 -0
- package/src/download/protectedModelKeys.ts +30 -0
- package/src/download/registry.ts +404 -0
- package/src/download/retry.ts +76 -0
- package/src/download/types.ts +120 -0
- package/src/download/validation.ts +114 -8
- package/src/{download → extraction}/extractTarBz2.ts +3 -1
- package/src/extraction/extractTarZst.ts +79 -0
- package/src/extraction/index.ts +269 -0
- package/src/extraction/types.ts +63 -0
- package/src/index.tsx +2 -0
- package/src/licenses.ts +100 -0
- package/src/stt/index.ts +20 -2
- package/src/stt/streaming.ts +3 -0
- package/src/stt/streamingTypes.ts +5 -0
- package/src/stt/types.ts +3 -1
- package/src/tts/index.ts +30 -2
- package/src/tts/streaming.ts +10 -0
- package/src/tts/types.ts +6 -5
- package/src/utils.ts +22 -1
- package/third_party/libarchive_prebuilt/ANDROID_RELEASE_TAG +1 -1
- package/third_party/libarchive_prebuilt/IOS_RELEASE_TAG +1 -1
- package/third_party/sherpa-onnx-prebuilt/ANDROID_RELEASE_TAG +1 -1
- package/third_party/sherpa-onnx-prebuilt/IOS_RELEASE_TAG +1 -1
- package/android/src/main/cpp/jni/tts/sherpa-onnx-tts-zipvoice-jni.cpp +0 -301
- package/android/src/main/java/com/sherpaonnx/ZipvoiceTtsWrapper.kt +0 -187
- package/lib/module/download/extractTarBz2.js.map +0 -1
- package/lib/typescript/src/download/extractTarBz2.d.ts.map +0 -1
- package/scripts/check-qnn-support.sh +0 -78
- /package/lib/typescript/src/{download → extraction}/extractTarBz2.d.ts +0 -0
|
@@ -29,7 +29,7 @@ get_filename_component(PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../.." ABSOL
|
|
|
29
29
|
set(USE_FFMPEG ON)
|
|
30
30
|
if(SHERPA_ONNX_DISABLE_FFMPEG)
|
|
31
31
|
set(USE_FFMPEG OFF)
|
|
32
|
-
message(STATUS "FFmpeg disabled (SHERPA_ONNX_DISABLE_FFMPEG=ON). convertAudioToWav16k/convertAudioToFormat will return an error at runtime.")
|
|
32
|
+
message(STATUS "FFmpeg disabled (SHERPA_ONNX_DISABLE_FFMPEG=ON). convertAudioToWav16k/convertAudioToFormat and decode (non-WAV) will return an error at runtime.")
|
|
33
33
|
endif()
|
|
34
34
|
|
|
35
35
|
if(USE_FFMPEG)
|
|
@@ -39,25 +39,32 @@ set(FFMPEG_PREBUILT_BASE "${PROJECT_ROOT}/../third_party/ffmpeg_prebuilt/android
|
|
|
39
39
|
set(FFMPEG_PREBUILT_LIB "${FFMPEG_PREBUILT_BASE}/${ANDROID_ABI}/lib")
|
|
40
40
|
set(FFMPEG_JNILIBS "${PROJECT_ROOT}/src/main/jniLibs/${ANDROID_ABI}")
|
|
41
41
|
set(FFMPEG_INCLUDE_CPP "${PROJECT_ROOT}/src/main/cpp/include/ffmpeg")
|
|
42
|
-
|
|
42
|
+
# Require a real header — an empty third_party/.../include/ dir must not win over Gradle-populated cpp/include/ffmpeg.
|
|
43
|
+
if(EXISTS "${FFMPEG_PREBUILT_BASE}/include/libavcodec/avcodec.h")
|
|
43
44
|
set(FFMPEG_INCLUDE_DIR "${FFMPEG_PREBUILT_BASE}/include")
|
|
44
45
|
message(STATUS "FFmpeg headers: prebuilts ${FFMPEG_INCLUDE_DIR}")
|
|
45
|
-
elseif(EXISTS "${FFMPEG_INCLUDE_CPP}")
|
|
46
|
+
elseif(EXISTS "${FFMPEG_INCLUDE_CPP}/libavcodec/avcodec.h")
|
|
46
47
|
set(FFMPEG_INCLUDE_DIR "${FFMPEG_INCLUDE_CPP}")
|
|
47
|
-
message(STATUS "FFmpeg headers:
|
|
48
|
+
message(STATUS "FFmpeg headers: module tree ${FFMPEG_INCLUDE_DIR}")
|
|
48
49
|
else()
|
|
49
50
|
message(FATAL_ERROR "FFmpeg headers missing. Either:\n"
|
|
50
51
|
" - Build: cd third_party/ffmpeg_prebuilt && ./build_ffmpeg.sh (creates android/include)\n"
|
|
51
52
|
" - Or use a release that includes include/ (Gradle extracts to ${FFMPEG_INCLUDE_CPP})")
|
|
52
53
|
endif()
|
|
54
|
+
# Prebuilts may be either legacy layout android/<abi>/lib/ (build_ffmpeg.sh) or
|
|
55
|
+
# android/jni/<abi>/ (same as Gradle THIRD_PARTY in docs/PREBUILT_RESOLUTION.md).
|
|
56
|
+
set(FFMPEG_PREBUILT_JNI_ABI "${FFMPEG_PREBUILT_BASE}/jni/${ANDROID_ABI}")
|
|
53
57
|
if(EXISTS "${FFMPEG_PREBUILT_LIB}/libavcodec.so")
|
|
54
58
|
set(FFMPEG_LIB_DIR "${FFMPEG_PREBUILT_LIB}")
|
|
55
59
|
message(STATUS "FFmpeg libs: prebuilts ${FFMPEG_LIB_DIR}")
|
|
60
|
+
elseif(EXISTS "${FFMPEG_PREBUILT_JNI_ABI}/libavcodec.so")
|
|
61
|
+
set(FFMPEG_LIB_DIR "${FFMPEG_PREBUILT_JNI_ABI}")
|
|
62
|
+
message(STATUS "FFmpeg libs: prebuilts (jni/<abi>) ${FFMPEG_LIB_DIR}")
|
|
56
63
|
elseif(EXISTS "${FFMPEG_JNILIBS}/libavcodec.so")
|
|
57
64
|
set(FFMPEG_LIB_DIR "${FFMPEG_JNILIBS}")
|
|
58
65
|
message(STATUS "FFmpeg libs: jniLibs ${FFMPEG_LIB_DIR}")
|
|
59
66
|
else()
|
|
60
|
-
message(FATAL_ERROR "FFmpeg libs missing for ABI ${ANDROID_ABI}. Run
|
|
67
|
+
message(FATAL_ERROR "FFmpeg libs missing for ABI ${ANDROID_ABI}. Run a Gradle Android build so prebuilts populate jniLibs, or add local .so under jniLibs / ffmpeg prebuilts paths.")
|
|
61
68
|
endif()
|
|
62
69
|
endif(USE_FFMPEG)
|
|
63
70
|
|
|
@@ -82,7 +89,6 @@ set(SOURCES
|
|
|
82
89
|
jni/model_detect/sherpa-onnx-stt-wrapper.cpp
|
|
83
90
|
jni/model_detect/sherpa-onnx-tts-wrapper.cpp
|
|
84
91
|
jni/audio/sherpa-onnx-audio-convert-jni.cpp
|
|
85
|
-
jni/tts/sherpa-onnx-tts-zipvoice-jni.cpp
|
|
86
92
|
crypto/sha256.cpp
|
|
87
93
|
)
|
|
88
94
|
|
|
@@ -93,10 +99,19 @@ set(LIBARCHIVE_PREBUILT_LIB "${LIBARCHIVE_PREBUILT_BASE}/${ANDROID_ABI}/lib")
|
|
|
93
99
|
set(LIBARCHIVE_JNILIBS "${PROJECT_ROOT}/src/main/jniLibs/${ANDROID_ABI}")
|
|
94
100
|
set(LIBARCHIVE_INCLUDE_CPP "${PROJECT_ROOT}/src/main/cpp/include/libarchive")
|
|
95
101
|
set(USE_LIBARCHIVE_PREBUILT OFF)
|
|
102
|
+
set(LIBARCHIVE_PREBUILT_JNI_ABI "${LIBARCHIVE_PREBUILT_BASE}/jni/${ANDROID_ABI}")
|
|
96
103
|
if(EXISTS "${LIBARCHIVE_PREBUILT_LIB}/libarchive.so")
|
|
97
104
|
set(USE_LIBARCHIVE_PREBUILT ON)
|
|
98
105
|
set(LIBARCHIVE_LIB_DIR "${LIBARCHIVE_PREBUILT_LIB}")
|
|
99
|
-
if(EXISTS "${LIBARCHIVE_PREBUILT_BASE}/include")
|
|
106
|
+
if(EXISTS "${LIBARCHIVE_PREBUILT_BASE}/include/archive.h")
|
|
107
|
+
set(LIBARCHIVE_INCLUDE_DIR "${LIBARCHIVE_PREBUILT_BASE}/include")
|
|
108
|
+
elseif(EXISTS "${LIBARCHIVE_INCLUDE_CPP}/archive.h")
|
|
109
|
+
set(LIBARCHIVE_INCLUDE_DIR "${LIBARCHIVE_INCLUDE_CPP}")
|
|
110
|
+
endif()
|
|
111
|
+
elseif(EXISTS "${LIBARCHIVE_PREBUILT_JNI_ABI}/libarchive.so")
|
|
112
|
+
set(USE_LIBARCHIVE_PREBUILT ON)
|
|
113
|
+
set(LIBARCHIVE_LIB_DIR "${LIBARCHIVE_PREBUILT_JNI_ABI}")
|
|
114
|
+
if(EXISTS "${LIBARCHIVE_PREBUILT_BASE}/include/archive.h")
|
|
100
115
|
set(LIBARCHIVE_INCLUDE_DIR "${LIBARCHIVE_PREBUILT_BASE}/include")
|
|
101
116
|
elseif(EXISTS "${LIBARCHIVE_INCLUDE_CPP}/archive.h")
|
|
102
117
|
set(LIBARCHIVE_INCLUDE_DIR "${LIBARCHIVE_INCLUDE_CPP}")
|
|
@@ -128,15 +143,19 @@ add_library(sherpaonnx SHARED
|
|
|
128
143
|
# If we used IMPORTED here, AGP would also copy .so from CMake --> duplicate in mergeNativeLibs.
|
|
129
144
|
set(SHERPA_ONNX_PREBUILT_BASE "${PROJECT_ROOT}/../third_party/sherpa-onnx-prebuilt/android")
|
|
130
145
|
set(SHERPA_ONNX_ABI_LIB "${SHERPA_ONNX_PREBUILT_BASE}/${ANDROID_ABI}/lib")
|
|
146
|
+
set(SHERPA_ONNX_JNI_ABI "${SHERPA_ONNX_PREBUILT_BASE}/jni/${ANDROID_ABI}")
|
|
131
147
|
set(SHERPA_C_API_LIB_DIR "")
|
|
132
148
|
if(EXISTS "${SHERPA_ONNX_ABI_LIB}/libsherpa-onnx-c-api.so")
|
|
133
149
|
set(SHERPA_C_API_LIB_DIR "${SHERPA_ONNX_ABI_LIB}")
|
|
134
150
|
message(STATUS "sherpa-onnx C-API (link only): ${SHERPA_C_API_LIB_DIR}")
|
|
151
|
+
elseif(EXISTS "${SHERPA_ONNX_JNI_ABI}/libsherpa-onnx-c-api.so")
|
|
152
|
+
set(SHERPA_C_API_LIB_DIR "${SHERPA_ONNX_JNI_ABI}")
|
|
153
|
+
message(STATUS "sherpa-onnx C-API (link only, third_party jni/<abi>): ${SHERPA_C_API_LIB_DIR}")
|
|
135
154
|
elseif(EXISTS "${PROJECT_ROOT}/src/main/jniLibs/${ANDROID_ABI}/libsherpa-onnx-c-api.so")
|
|
136
155
|
set(SHERPA_C_API_LIB_DIR "${PROJECT_ROOT}/src/main/jniLibs/${ANDROID_ABI}")
|
|
137
156
|
message(STATUS "sherpa-onnx C-API (link only, jniLibs): ${SHERPA_C_API_LIB_DIR}")
|
|
138
157
|
else()
|
|
139
|
-
message(WARNING "sherpa-onnx C-API not found.
|
|
158
|
+
message(WARNING "sherpa-onnx C-API not found. Prebuilt sherpa native libs may be incomplete. "
|
|
140
159
|
"Build prebuilts: cd third_party/sherpa-onnx-prebuilt && ./build_sherpa_onnx.sh")
|
|
141
160
|
endif()
|
|
142
161
|
|
|
@@ -148,7 +167,6 @@ target_include_directories(sherpaonnx PRIVATE
|
|
|
148
167
|
${CMAKE_CURRENT_SOURCE_DIR}/jni/archive
|
|
149
168
|
${CMAKE_CURRENT_SOURCE_DIR}/jni/model_detect
|
|
150
169
|
${CMAKE_CURRENT_SOURCE_DIR}/jni/audio
|
|
151
|
-
${CMAKE_CURRENT_SOURCE_DIR}/jni/tts
|
|
152
170
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
|
153
171
|
)
|
|
154
172
|
if(USE_FFMPEG)
|
|
@@ -167,7 +185,7 @@ if(USE_LIBARCHIVE)
|
|
|
167
185
|
target_compile_definitions(sherpaonnx PRIVATE HAVE_LIBARCHIVE=1)
|
|
168
186
|
endif()
|
|
169
187
|
|
|
170
|
-
# Link libraries (Kotlin API from AAR handles STT/TTS
|
|
188
|
+
# Link libraries (Kotlin API from AAR handles STT/TTS incl. Zipvoice)
|
|
171
189
|
if(USE_FFMPEG)
|
|
172
190
|
target_link_directories(sherpaonnx PRIVATE ${FFMPEG_LIB_DIR})
|
|
173
191
|
endif()
|
|
@@ -75,6 +75,38 @@ static void DrainRemainingAndClose(ArchiveReadContext* ctx) {
|
|
|
75
75
|
fclose(ctx->file);
|
|
76
76
|
ctx->file = nullptr;
|
|
77
77
|
}
|
|
78
|
+
|
|
79
|
+
struct StreamReadContext {
|
|
80
|
+
std::array<unsigned char, 64 * 1024> buffer{};
|
|
81
|
+
Sha256Context sha_ctx{};
|
|
82
|
+
long long bytes_read = 0;
|
|
83
|
+
ArchiveHelper::StreamReadCallback read_cb = nullptr;
|
|
84
|
+
void* user_data = nullptr;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
static la_ssize_t ArchiveStreamReadCallback(struct archive* archive, void* client_data, const void** buff) {
|
|
88
|
+
auto* ctx = static_cast<StreamReadContext*>(client_data);
|
|
89
|
+
if (!ctx || !ctx->read_cb) {
|
|
90
|
+
archive_set_error(archive, EINVAL, "Invalid stream read context");
|
|
91
|
+
return -1;
|
|
92
|
+
}
|
|
93
|
+
std::ptrdiff_t n = ctx->read_cb(ctx->buffer.data(), ctx->buffer.size(), ctx->user_data);
|
|
94
|
+
if (n > 0) {
|
|
95
|
+
sha256_update(&ctx->sha_ctx, ctx->buffer.data(), static_cast<size_t>(n));
|
|
96
|
+
ctx->bytes_read += static_cast<long long>(n);
|
|
97
|
+
*buff = ctx->buffer.data();
|
|
98
|
+
return static_cast<la_ssize_t>(n);
|
|
99
|
+
}
|
|
100
|
+
if (n == 0) return 0;
|
|
101
|
+
archive_set_error(archive, EINVAL, "Stream read error");
|
|
102
|
+
return -1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// No-op close callback for stream mode: the stream lifetime is managed by the
|
|
106
|
+
// caller (e.g. a JNI InputStream), so libarchive must not close it.
|
|
107
|
+
static int ArchiveStreamCloseCallback(struct archive* /* archive */, void* /* client_data */) {
|
|
108
|
+
return ARCHIVE_OK;
|
|
109
|
+
}
|
|
78
110
|
#endif // HAVE_LIBARCHIVE
|
|
79
111
|
|
|
80
112
|
static std::string ToHex(const unsigned char* data, size_t size) {
|
|
@@ -122,13 +154,15 @@ bool ArchiveHelper::ExtractTarBz2(
|
|
|
122
154
|
return false;
|
|
123
155
|
}
|
|
124
156
|
|
|
125
|
-
//
|
|
157
|
+
// If target exists and is a directory, extract into it (merge). Otherwise require empty or force-remove.
|
|
126
158
|
if (std::filesystem::exists(target_path)) {
|
|
127
|
-
if (
|
|
159
|
+
if (std::filesystem::is_directory(target_path)) {
|
|
160
|
+
// Merge: extract into existing directory (e.g. multiple archives --> same base path)
|
|
161
|
+
} else if (force) {
|
|
128
162
|
std::error_code ec;
|
|
129
163
|
std::filesystem::remove_all(target_path, ec);
|
|
130
164
|
if (ec) {
|
|
131
|
-
if (out_error) *out_error = "Failed to remove target
|
|
165
|
+
if (out_error) *out_error = "Failed to remove target path: " + ec.message();
|
|
132
166
|
return false;
|
|
133
167
|
}
|
|
134
168
|
} else {
|
|
@@ -137,7 +171,6 @@ bool ArchiveHelper::ExtractTarBz2(
|
|
|
137
171
|
}
|
|
138
172
|
}
|
|
139
173
|
|
|
140
|
-
// Create target directory
|
|
141
174
|
std::error_code ec;
|
|
142
175
|
std::filesystem::create_directories(target_path, ec);
|
|
143
176
|
if (ec) {
|
|
@@ -167,11 +200,12 @@ bool ArchiveHelper::ExtractTarBz2(
|
|
|
167
200
|
return false;
|
|
168
201
|
}
|
|
169
202
|
|
|
170
|
-
// Configure archive to support tar and bzip2
|
|
203
|
+
// Configure archive to support tar and common compression (bzip2, gzip, xz, zstd)
|
|
171
204
|
archive_read_support_format_tar(archive);
|
|
172
205
|
archive_read_support_filter_bzip2(archive);
|
|
173
206
|
archive_read_support_filter_gzip(archive); // Also support gzip for compatibility
|
|
174
|
-
archive_read_support_filter_xz(archive);
|
|
207
|
+
archive_read_support_filter_xz(archive); // And xz
|
|
208
|
+
archive_read_support_filter_zstd(archive); // And zstd (.tar.zst)
|
|
175
209
|
|
|
176
210
|
ArchiveReadContext read_ctx;
|
|
177
211
|
read_ctx.file = fopen(source_path.c_str(), "rb");
|
|
@@ -354,6 +388,18 @@ bool ArchiveHelper::ExtractTarBz2(
|
|
|
354
388
|
close_reader();
|
|
355
389
|
return false;
|
|
356
390
|
}
|
|
391
|
+
|
|
392
|
+
result = archive_write_finish_entry(disk);
|
|
393
|
+
if (result != ARCHIVE_OK && result != ARCHIVE_WARN) {
|
|
394
|
+
const char* err = archive_error_string(disk);
|
|
395
|
+
if (out_error) {
|
|
396
|
+
*out_error = err ? std::string("Failed to finish entry: ") + err : "Failed to finish entry";
|
|
397
|
+
}
|
|
398
|
+
archive_read_free(archive);
|
|
399
|
+
archive_write_free(disk);
|
|
400
|
+
close_reader();
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
357
403
|
}
|
|
358
404
|
|
|
359
405
|
archive_read_free(archive);
|
|
@@ -376,6 +422,260 @@ bool ArchiveHelper::ExtractTarBz2(
|
|
|
376
422
|
#endif // HAVE_LIBARCHIVE
|
|
377
423
|
}
|
|
378
424
|
|
|
425
|
+
bool ArchiveHelper::ExtractTarZst(
|
|
426
|
+
const std::string& source_path,
|
|
427
|
+
const std::string& target_path,
|
|
428
|
+
bool force,
|
|
429
|
+
std::function<void(long long, long long, double)> on_progress,
|
|
430
|
+
std::string* out_error,
|
|
431
|
+
std::string* out_sha256) {
|
|
432
|
+
return ExtractTarBz2(source_path, target_path, force, on_progress, out_error, out_sha256);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
bool ArchiveHelper::ExtractFromStream(
|
|
436
|
+
StreamReadCallback read_cb,
|
|
437
|
+
void* read_user_data,
|
|
438
|
+
const std::string& target_path,
|
|
439
|
+
bool force,
|
|
440
|
+
std::function<void(long long, long long, double)> on_progress,
|
|
441
|
+
std::string* out_error,
|
|
442
|
+
std::string* out_sha256) {
|
|
443
|
+
cancel_requested_.store(false);
|
|
444
|
+
|
|
445
|
+
#ifndef HAVE_LIBARCHIVE
|
|
446
|
+
(void)read_cb;
|
|
447
|
+
(void)read_user_data;
|
|
448
|
+
(void)target_path;
|
|
449
|
+
(void)force;
|
|
450
|
+
(void)on_progress;
|
|
451
|
+
(void)out_sha256;
|
|
452
|
+
if (out_error) *out_error = "libarchive not available. Build with libarchive or set sherpaOnnxDisableLibarchive=false in gradle.properties. See docs/disable-libarchive.md.";
|
|
453
|
+
return false;
|
|
454
|
+
#else
|
|
455
|
+
if (!read_cb) {
|
|
456
|
+
if (out_error) *out_error = "Stream read callback is null";
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (std::filesystem::exists(target_path)) {
|
|
461
|
+
if (std::filesystem::is_directory(target_path)) {
|
|
462
|
+
// Merge: extract into existing directory (e.g. multiple archives --> same base path)
|
|
463
|
+
} else if (force) {
|
|
464
|
+
std::error_code ec;
|
|
465
|
+
std::filesystem::remove_all(target_path, ec);
|
|
466
|
+
if (ec) {
|
|
467
|
+
if (out_error) *out_error = "Failed to remove target path: " + ec.message();
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
} else {
|
|
471
|
+
if (out_error) *out_error = "Target path already exists";
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
std::error_code ec;
|
|
477
|
+
std::filesystem::create_directories(target_path, ec);
|
|
478
|
+
if (ec) {
|
|
479
|
+
if (out_error) *out_error = "Failed to create target directory: " + ec.message();
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
#ifndef NDEBUG
|
|
484
|
+
__android_log_print(ANDROID_LOG_INFO, "SherpaOnnx",
|
|
485
|
+
"ExtractFromStream target_path=%s", target_path.c_str());
|
|
486
|
+
#endif
|
|
487
|
+
|
|
488
|
+
std::string canonical_target = std::filesystem::canonical(target_path).string();
|
|
489
|
+
if (canonical_target.back() != '/') canonical_target += '/';
|
|
490
|
+
|
|
491
|
+
const long long total_bytes = 0;
|
|
492
|
+
|
|
493
|
+
struct archive* archive = archive_read_new();
|
|
494
|
+
if (!archive) {
|
|
495
|
+
if (out_error) *out_error = "Failed to create archive reader";
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
archive_read_support_format_tar(archive);
|
|
500
|
+
archive_read_support_filter_bzip2(archive);
|
|
501
|
+
archive_read_support_filter_gzip(archive);
|
|
502
|
+
archive_read_support_filter_xz(archive);
|
|
503
|
+
archive_read_support_filter_zstd(archive);
|
|
504
|
+
|
|
505
|
+
StreamReadContext stream_ctx;
|
|
506
|
+
stream_ctx.read_cb = read_cb;
|
|
507
|
+
stream_ctx.user_data = read_user_data;
|
|
508
|
+
sha256_init(&stream_ctx.sha_ctx);
|
|
509
|
+
|
|
510
|
+
if (archive_read_open(archive, &stream_ctx, nullptr, ArchiveStreamReadCallback, ArchiveStreamCloseCallback) != ARCHIVE_OK) {
|
|
511
|
+
const char* err = archive_error_string(archive);
|
|
512
|
+
if (out_error) *out_error = err ? std::string("Failed to open archive: ") + err : "Failed to open archive";
|
|
513
|
+
archive_read_free(archive);
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
struct archive* disk = archive_write_disk_new();
|
|
518
|
+
if (!disk) {
|
|
519
|
+
if (out_error) *out_error = "Failed to create disk writer";
|
|
520
|
+
archive_read_free(archive);
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
archive_write_disk_set_options(disk,
|
|
525
|
+
ARCHIVE_EXTRACT_TIME |
|
|
526
|
+
ARCHIVE_EXTRACT_PERM |
|
|
527
|
+
ARCHIVE_EXTRACT_ACL |
|
|
528
|
+
ARCHIVE_EXTRACT_FFLAGS);
|
|
529
|
+
archive_write_disk_set_standard_lookup(disk);
|
|
530
|
+
|
|
531
|
+
struct archive_entry* entry = nullptr;
|
|
532
|
+
int result = ARCHIVE_OK;
|
|
533
|
+
long long extracted_bytes = 0;
|
|
534
|
+
int last_percent = -1;
|
|
535
|
+
long long last_emit_bytes = 0;
|
|
536
|
+
int entry_index = 0;
|
|
537
|
+
|
|
538
|
+
while ((result = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) {
|
|
539
|
+
if (cancel_requested_.load()) {
|
|
540
|
+
if (out_error) *out_error = "Extraction cancelled";
|
|
541
|
+
archive_read_free(archive);
|
|
542
|
+
archive_write_free(disk);
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
const char* current_path = archive_entry_pathname(entry);
|
|
547
|
+
if (!current_path) {
|
|
548
|
+
archive_read_free(archive);
|
|
549
|
+
archive_write_free(disk);
|
|
550
|
+
if (out_error) *out_error = "Invalid entry path";
|
|
551
|
+
return false;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
std::string entry_path(current_path);
|
|
555
|
+
std::string full_path = target_path;
|
|
556
|
+
if (full_path.back() != '/') full_path += '/';
|
|
557
|
+
full_path += entry_path;
|
|
558
|
+
|
|
559
|
+
std::string canonical_entry;
|
|
560
|
+
try {
|
|
561
|
+
std::filesystem::path p(full_path);
|
|
562
|
+
std::filesystem::path parent = p.parent_path();
|
|
563
|
+
if (std::filesystem::exists(parent)) {
|
|
564
|
+
canonical_entry = std::filesystem::canonical(parent).string();
|
|
565
|
+
} else {
|
|
566
|
+
while (!std::filesystem::exists(parent) && parent != parent.parent_path()) {
|
|
567
|
+
parent = parent.parent_path();
|
|
568
|
+
}
|
|
569
|
+
if (std::filesystem::exists(parent)) {
|
|
570
|
+
canonical_entry = std::filesystem::canonical(parent).string();
|
|
571
|
+
} else {
|
|
572
|
+
canonical_entry = canonical_target;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
canonical_entry += '/';
|
|
576
|
+
canonical_entry += p.filename().string();
|
|
577
|
+
} catch (const std::exception&) {
|
|
578
|
+
canonical_entry = full_path;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
if (canonical_entry.find(canonical_target) != 0) {
|
|
582
|
+
archive_read_free(archive);
|
|
583
|
+
archive_write_free(disk);
|
|
584
|
+
if (out_error) *out_error = "Blocked path traversal: " + entry_path;
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
archive_entry_set_pathname(entry, full_path.c_str());
|
|
589
|
+
|
|
590
|
+
result = archive_write_header(disk, entry);
|
|
591
|
+
if (result != ARCHIVE_OK) {
|
|
592
|
+
const char* err = archive_error_string(disk);
|
|
593
|
+
if (out_error) *out_error = err ? std::string("Failed to write entry: ") + err : "Failed to write entry";
|
|
594
|
+
archive_read_free(archive);
|
|
595
|
+
archive_write_free(disk);
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
const void* buff = nullptr;
|
|
600
|
+
size_t size = 0;
|
|
601
|
+
la_int64_t offset = 0;
|
|
602
|
+
|
|
603
|
+
while ((result = archive_read_data_block(archive, &buff, &size, &offset)) == ARCHIVE_OK) {
|
|
604
|
+
if (cancel_requested_.load()) {
|
|
605
|
+
if (out_error) *out_error = "Extraction cancelled";
|
|
606
|
+
archive_read_free(archive);
|
|
607
|
+
archive_write_free(disk);
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
result = archive_write_data_block(disk, buff, size, offset);
|
|
612
|
+
if (result != ARCHIVE_OK) {
|
|
613
|
+
const char* err = archive_error_string(disk);
|
|
614
|
+
if (out_error) *out_error = err ? std::string("Failed to write data: ") + err : "Failed to write data";
|
|
615
|
+
archive_read_free(archive);
|
|
616
|
+
archive_write_free(disk);
|
|
617
|
+
return false;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
extracted_bytes += static_cast<long long>(size);
|
|
621
|
+
|
|
622
|
+
if (on_progress) {
|
|
623
|
+
if (total_bytes > 0) {
|
|
624
|
+
long long compressed_bytes = archive_filter_bytes(archive, -1);
|
|
625
|
+
int percent = static_cast<int>(total_bytes > 0 ? (compressed_bytes * 100) / total_bytes : 0);
|
|
626
|
+
percent = (percent > 100) ? 100 : ((percent < 0) ? 0 : percent);
|
|
627
|
+
if (percent != last_percent) {
|
|
628
|
+
last_percent = percent;
|
|
629
|
+
on_progress(compressed_bytes, total_bytes, static_cast<double>(percent));
|
|
630
|
+
}
|
|
631
|
+
} else if (stream_ctx.bytes_read - last_emit_bytes >= 1024 * 1024) {
|
|
632
|
+
last_emit_bytes = stream_ctx.bytes_read;
|
|
633
|
+
on_progress(stream_ctx.bytes_read, 0, 0.0);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
if (result != ARCHIVE_EOF && result != ARCHIVE_OK) {
|
|
639
|
+
const char* err = archive_error_string(archive);
|
|
640
|
+
if (out_error) *out_error = err ? std::string("Failed to read data: ") + err : "Failed to read data";
|
|
641
|
+
archive_read_free(archive);
|
|
642
|
+
archive_write_free(disk);
|
|
643
|
+
return false;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
result = archive_write_finish_entry(disk);
|
|
647
|
+
if (result != ARCHIVE_OK && result != ARCHIVE_WARN) {
|
|
648
|
+
const char* err = archive_error_string(disk);
|
|
649
|
+
if (out_error) *out_error = err ? std::string("Failed to finish entry: ") + err : "Failed to finish entry";
|
|
650
|
+
archive_read_free(archive);
|
|
651
|
+
archive_write_free(disk);
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
entry_index++;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
#ifndef NDEBUG
|
|
658
|
+
__android_log_print(ANDROID_LOG_INFO, "SherpaOnnx",
|
|
659
|
+
"ExtractFromStream done entries=%d", entry_index);
|
|
660
|
+
#endif
|
|
661
|
+
|
|
662
|
+
archive_read_free(archive);
|
|
663
|
+
archive_write_free(disk);
|
|
664
|
+
|
|
665
|
+
if (out_sha256) {
|
|
666
|
+
unsigned char digest[32];
|
|
667
|
+
sha256_final(&stream_ctx.sha_ctx, digest);
|
|
668
|
+
*out_sha256 = ToHex(digest, sizeof(digest));
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (on_progress) {
|
|
672
|
+
on_progress(stream_ctx.bytes_read, stream_ctx.bytes_read, 100.0);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return true;
|
|
676
|
+
#endif
|
|
677
|
+
}
|
|
678
|
+
|
|
379
679
|
bool ArchiveHelper::ComputeFileSha256(
|
|
380
680
|
const std::string& file_path,
|
|
381
681
|
std::string* out_error,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include <cstddef>
|
|
3
4
|
#include <string>
|
|
4
5
|
#include <functional>
|
|
5
6
|
#include <atomic>
|
|
@@ -10,14 +11,17 @@
|
|
|
10
11
|
*/
|
|
11
12
|
class ArchiveHelper {
|
|
12
13
|
public:
|
|
14
|
+
/** Callback to read bytes from a stream (e.g. Java InputStream via JNI). Returns bytes read, 0 on EOF, -1 on error. */
|
|
15
|
+
using StreamReadCallback = std::ptrdiff_t (*)(void* buf, size_t len, void* user_data);
|
|
16
|
+
|
|
13
17
|
/**
|
|
14
|
-
* Extract tar.bz2 file to target directory
|
|
18
|
+
* Extract tar.bz2 (or .tar.zst, .tar.gz, .tar.xz) file to target directory.
|
|
15
19
|
*
|
|
16
|
-
* @param sourcePath Path to the
|
|
20
|
+
* @param sourcePath Path to the archive file
|
|
17
21
|
* @param targetPath Destination directory path
|
|
18
22
|
* @param force Whether to overwrite existing target directory
|
|
19
23
|
* @param onProgress Callback for progress updates (bytesExtracted, totalBytes, percent)
|
|
20
|
-
|
|
24
|
+
* @param outSha256 Optional output SHA-256 hex of the archive file
|
|
21
25
|
* @return true if extraction succeeded, false otherwise
|
|
22
26
|
*/
|
|
23
27
|
static bool ExtractTarBz2(
|
|
@@ -28,7 +32,32 @@ class ArchiveHelper {
|
|
|
28
32
|
std::string* out_error = nullptr,
|
|
29
33
|
std::string* out_sha256 = nullptr);
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Extract .tar.zst (or other supported tar compression) file to target directory.
|
|
37
|
+
* Uses the same implementation as ExtractTarBz2 (libarchive supports zstd when built with ENABLE_ZSTD).
|
|
38
|
+
*/
|
|
39
|
+
static bool ExtractTarZst(
|
|
40
|
+
const std::string& source_path,
|
|
41
|
+
const std::string& target_path,
|
|
42
|
+
bool force,
|
|
43
|
+
std::function<void(long long, long long, double)> on_progress = nullptr,
|
|
44
|
+
std::string* out_error = nullptr,
|
|
45
|
+
std::string* out_sha256 = nullptr);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Extract a tar archive (tar.zst or tar.bz2) from a stream via read_cb.
|
|
49
|
+
* Used for Android AssetManager streams; total_bytes can be 0 (progress then uses compressed bytes or periodic emit).
|
|
50
|
+
*/
|
|
51
|
+
static bool ExtractFromStream(
|
|
52
|
+
StreamReadCallback read_cb,
|
|
53
|
+
void* read_user_data,
|
|
54
|
+
const std::string& target_path,
|
|
55
|
+
bool force,
|
|
56
|
+
std::function<void(long long, long long, double)> on_progress = nullptr,
|
|
57
|
+
std::string* out_error = nullptr,
|
|
58
|
+
std::string* out_sha256 = nullptr);
|
|
59
|
+
|
|
60
|
+
/**
|
|
32
61
|
* Compute SHA-256 of a file.
|
|
33
62
|
*
|
|
34
63
|
* @param file_path Path to the file
|