├── .editorconfig ├── .editorconfig-checker.json ├── .gitattributes ├── .github └── workflows │ ├── build-check-linux.yml │ ├── build-check-macos.yml │ ├── build-check-windows.yml │ ├── build-push.yml │ └── build-release.yml ├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── NEWS ├── README.md ├── ROADMAP ├── automake.sh ├── build ├── build-debug.sh ├── build-static.sh ├── build.sh ├── release.sh └── sign-release.sh ├── config.guess ├── config.h.in ├── config.sub ├── configure.ac ├── depcomp ├── m4 ├── acx_pthread.m4 ├── ax_check_compile_flag.m4 ├── ax_check_link_flag.m4 └── ax_cxx_compile_stdcxx.m4 ├── man └── par2.1 ├── mkinstalldirs ├── par2cmdline.sln ├── par2cmdline.vcxproj ├── par2cmdline.vcxproj.filters ├── parpar ├── gf16.vcxproj ├── gf16 │ ├── controller.cpp │ ├── controller.h │ ├── controller_cpu.cpp │ ├── controller_cpu.h │ ├── controller_ocl.cpp │ ├── controller_ocl.h │ ├── controller_ocl_init.cpp │ ├── gf16_affine.h │ ├── gf16_affine2x_x86.h │ ├── gf16_affine_avx10.c │ ├── gf16_affine_avx10.h │ ├── gf16_affine_avx2.c │ ├── gf16_affine_avx512.c │ ├── gf16_affine_gfni.c │ ├── gf16_bitdep_init_avx2.h │ ├── gf16_bitdep_init_sse2.h │ ├── gf16_checksum_arm.h │ ├── gf16_checksum_generic.h │ ├── gf16_checksum_rvv.h │ ├── gf16_checksum_sve.h │ ├── gf16_checksum_x86.h │ ├── gf16_cksum.h │ ├── gf16_cksum_avx2.c │ ├── gf16_cksum_avx512.c │ ├── gf16_cksum_base.h │ ├── gf16_cksum_generic.c │ ├── gf16_cksum_neon.c │ ├── gf16_cksum_rvv.c │ ├── gf16_cksum_sse2.c │ ├── gf16_cksum_sve.c │ ├── gf16_cksum_x86.h │ ├── gf16_clmul.h │ ├── gf16_clmul_neon.c │ ├── gf16_clmul_neon.h │ ├── gf16_clmul_neon_base.h │ ├── gf16_clmul_rvv.c │ ├── gf16_clmul_rvv.h │ ├── gf16_clmul_sha3.c │ ├── gf16_clmul_sve2.c │ ├── gf16_clmul_sve2.h │ ├── gf16_global.h │ ├── gf16_lookup.c │ ├── gf16_lookup.h │ ├── gf16_lookup_sse2.c │ ├── gf16_muladd_multi.h │ ├── gf16_neon_common.h │ ├── gf16_rvv_common.h │ ├── gf16_shuffle.h │ ├── gf16_shuffle128_rvv.c │ ├── gf16_shuffle128_sve.c │ ├── gf16_shuffle128_sve2.c │ ├── gf16_shuffle128_sve_common.h │ ├── gf16_shuffle2x128_sve2.c │ ├── gf16_shuffle2x_x86.h │ ├── gf16_shuffle512_sve2.c │ ├── gf16_shuffle_avx.c │ ├── gf16_shuffle_avx2.c │ ├── gf16_shuffle_avx512.c │ ├── gf16_shuffle_neon.c │ ├── gf16_shuffle_ssse3.c │ ├── gf16_shuffle_vbmi.c │ ├── gf16_shuffle_x86.h │ ├── gf16_shuffle_x86_common.h │ ├── gf16_shuffle_x86_prepare.h │ ├── gf16_sve_common.h │ ├── gf16_xor.h │ ├── gf16_xor_avx2.c │ ├── gf16_xor_avx512.c │ ├── gf16_xor_common.h │ ├── gf16_xor_common_funcs.h │ ├── gf16_xor_sse2.c │ ├── gf16mul.cpp │ ├── gf16mul.h │ ├── gf16pmul.cpp │ ├── gf16pmul.h │ ├── gf16pmul_avx2.c │ ├── gf16pmul_neon.c │ ├── gf16pmul_rvv.c │ ├── gf16pmul_sse.c │ ├── gf16pmul_sve2.c │ ├── gf16pmul_vpclgfni.c │ ├── gf16pmul_vpclmul.c │ ├── gf16pmul_x86.h │ ├── gf_add.h │ ├── gf_add_avx10.c │ ├── gf_add_avx2.c │ ├── gf_add_avx512.c │ ├── gf_add_common.h │ ├── gf_add_generic.c │ ├── gf_add_neon.c │ ├── gf_add_rvv.c │ ├── gf_add_sse2.c │ ├── gf_add_sve.c │ ├── gf_add_sve2.c │ ├── gf_add_x86.h │ ├── gfmat_coeff.c │ ├── gfmat_coeff.h │ ├── gfmat_inv.cpp │ ├── gfmat_inv.h │ ├── opencl-include │ │ ├── CL │ │ │ ├── cl.h │ │ │ ├── cl_platform.h │ │ │ ├── cl_version.h │ │ │ └── opencl.hpp │ │ ├── cl.c │ │ ├── cl.h │ │ └── readme.txt │ ├── suppressions-valgrind.supp │ ├── threadqueue.h │ ├── x86_jit.h │ └── xor_jit_stub_masm64.asm ├── hasher.vcxproj ├── hasher │ ├── crc_arm.h │ ├── crc_clmul.h │ ├── crc_rvzbc.h │ ├── crc_slice4.h │ ├── crc_zeropad.c │ ├── crc_zeropad.h │ ├── hasher.cpp │ ├── hasher.h │ ├── hasher_armcrc.cpp │ ├── hasher_avx2.cpp │ ├── hasher_avx512.cpp │ ├── hasher_avx512vl.cpp │ ├── hasher_bmi1.cpp │ ├── hasher_clmul.cpp │ ├── hasher_input.cpp │ ├── hasher_input.h │ ├── hasher_input_base.h │ ├── hasher_input_impl.h │ ├── hasher_input_stub.h │ ├── hasher_md5crc.cpp │ ├── hasher_md5crc.h │ ├── hasher_md5crc_base.h │ ├── hasher_md5crc_impl.h │ ├── hasher_md5crc_stub.h │ ├── hasher_md5mb.cpp │ ├── hasher_md5mb.h │ ├── hasher_md5mb_base.h │ ├── hasher_md5mb_impl.h │ ├── hasher_md5mb_stub.h │ ├── hasher_neon.cpp │ ├── hasher_neoncrc.cpp │ ├── hasher_rvzbc.cpp │ ├── hasher_scalar.cpp │ ├── hasher_sse.cpp │ ├── hasher_sve2.cpp │ ├── hasher_xop.cpp │ ├── md5-arm-asm.h │ ├── md5-arm64-asm.h │ ├── md5-avx512-asm.h │ ├── md5-avx512.h │ ├── md5-base.h │ ├── md5-final.c │ ├── md5-final.h │ ├── md5-scalar-base.h │ ├── md5-scalar.h │ ├── md5-x86-asm.h │ ├── md5mb-base.h │ ├── md5mb-neon.h │ ├── md5mb-scalar.h │ ├── md5mb-sse.h │ ├── md5mb-sve2.h │ ├── md5x2-arm-asm.h │ ├── md5x2-base.h │ ├── md5x2-neon-asm.h │ ├── md5x2-neon.h │ ├── md5x2-scalar.h │ ├── md5x2-sse-asm.h │ ├── md5x2-sse.h │ ├── md5x2-x86-asm.h │ └── tables.cpp └── src │ ├── cpuid.h │ ├── hedley.h │ ├── platform.h │ ├── platform_warnings.c │ └── stdint.h ├── src ├── commandline.cpp ├── commandline.h ├── commandline_test.cpp ├── crc.cpp ├── crc.h ├── crc_test.cpp ├── creatorpacket.cpp ├── creatorpacket.h ├── criticalpacket.cpp ├── criticalpacket.h ├── criticalpacket_test.cpp ├── datablock.cpp ├── datablock.h ├── descriptionpacket.cpp ├── descriptionpacket.h ├── descriptionpacket_test.cpp ├── diskfile.cpp ├── diskfile.h ├── diskfile_test.cpp ├── filechecksummer.cpp ├── filechecksummer.h ├── foreach_parallel.h ├── galois.cpp ├── galois.h ├── galois_test.cpp ├── hasher.h ├── letype.h ├── letype_test.cpp ├── libpar2.cpp ├── libpar2.h ├── libpar2_test.cpp ├── libpar2internal.h ├── mainpacket.cpp ├── mainpacket.h ├── md5.cpp ├── md5.h ├── md5_test.cpp ├── par1fileformat.cpp ├── par1fileformat.h ├── par1repairer.cpp ├── par1repairer.h ├── par1repairersourcefile.cpp ├── par1repairersourcefile.h ├── par2cmdline.cpp ├── par2creator.cpp ├── par2creator.h ├── par2creatorsourcefile.cpp ├── par2creatorsourcefile.h ├── par2fileformat.cpp ├── par2fileformat.h ├── par2repairer.cpp ├── par2repairer.h ├── par2repairersourcefile.cpp ├── par2repairersourcefile.h ├── recoverypacket.cpp ├── recoverypacket.h ├── reedsolomon.cpp ├── reedsolomon.h ├── reedsolomon_test.cpp ├── utf8.cpp ├── utf8.h ├── utf8_test.cpp ├── verificationhashtable.cpp ├── verificationhashtable.h ├── verificationpacket.cpp └── verificationpacket.h ├── stamp-h.in └── tests ├── 100blocks.tar.gz ├── bug128-parfiles.tar.gz ├── bug190.tar.gz ├── bug44.tar.gz ├── flatdata-par1files.tar.gz ├── flatdata-par2files.tar.gz ├── flatdata.tar.gz ├── par2-0.6.8-crash.tar.gz ├── readbeyondeof.tar.gz ├── smallsubdirdata-par2files.tar.gz ├── smallsubdirdata.tar.gz ├── subdirdata-par2files-unix.tar.gz ├── subdirdata-par2files-win.tar.gz ├── subdirdata.tar.gz ├── test1 ├── test10 ├── test11 ├── test12 ├── test13 ├── test14 ├── test15 ├── test16 ├── test17 ├── test18 ├── test19 ├── test2 ├── test20 ├── test21 ├── test22 ├── test23 ├── test24 ├── test25 ├── test26 ├── test27 ├── test28 ├── test29 ├── test3 ├── test30 ├── test31 ├── test32 ├── test4 ├── test5 ├── test5rk ├── test6 ├── test7 ├── test8 ├── test9 ├── testMem ├── testcollision ├── 2mb_0s.bin ├── 2mb_0s.bin.par2 ├── 2mb_col.bin ├── 2mb_col.bin.par2 ├── pattern16.bin └── pattern16.bin.par2 └── unit_tests /.editorconfig: -------------------------------------------------------------------------------- 1 | root=true 2 | 3 | [*] 4 | end_of_line = lf 5 | indent_style = space 6 | indent_size = 2 7 | -------------------------------------------------------------------------------- /.editorconfig-checker.json: -------------------------------------------------------------------------------- 1 | { 2 | "Verbose": false, 3 | "Debug": false, 4 | "IgnoreDefaults": false, 5 | "SpacesAfterTabs": false, 6 | "NoColor": false, 7 | "Exclude": ["\\.par2$"], 8 | "AllowedContentTypes": [], 9 | "PassedFiles": [], 10 | "Disable": { 11 | "EndOfLine": false, 12 | "Indentation": false, 13 | "IndentSize": false, 14 | "InsertFinalNewline": false, 15 | "TrimTrailingWhitespace": false, 16 | "MaxLineLength": false 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | # see http://stackoverflow.com/questions/170961/whats-the-best-crlf-carriage-return-line-feed-handling-strategy-with-git 3 | 4 | * text=auto 5 | 6 | *.cpp text 7 | *.h text 8 | *.txt text 9 | *.s text 10 | 11 | *.csproj text merge=union 12 | *.sln text=unset merge=union 13 | *.vcproj text=unset merge=union 14 | *.vcxproj* text=unset merge=union 15 | 16 | # The VC++ files were already in the repo with DOS line endings 17 | # This setting would make git store them internally with LF 18 | #*.sln text merge=union eol=crlf 19 | 20 | # instead, use text=unset to tell git to not do any conversions on 21 | # those files 22 | 23 | 24 | # This will only work well in a repo where all the files have Unix line 25 | # endings. Having this file in a repo with DOS text files in the tree will 26 | # make git see those files as changed (to Unix line endings, regardless of 27 | # what they are in your working copy). 28 | 29 | # Conversely, this will make all new commits of text files commit with Unix 30 | # line endings, regardless of what they are in your working copy. 31 | -------------------------------------------------------------------------------- /.github/workflows/build-check-linux.yml: -------------------------------------------------------------------------------- 1 | name: par2cmdline CI linux 2 | 3 | on: 4 | workflow_call: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | build-check-linux: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: automake 15 | run: ./automake.sh 16 | 17 | - name: configure 18 | run: ./configure 19 | 20 | - name: make 21 | run: make 22 | 23 | - name: make check 24 | run: make check 25 | 26 | - name: make distcheck 27 | run: make distcheck 28 | -------------------------------------------------------------------------------- /.github/workflows/build-check-macos.yml: -------------------------------------------------------------------------------- 1 | name: par2cmdline CI macos 2 | 3 | on: 4 | workflow_call: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | build-check-macos: 9 | runs-on: macos-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: prepare 15 | run: brew install automake 16 | 17 | - name: automake 18 | run: ./automake.sh 19 | 20 | - name: configure 21 | run: ./configure 22 | 23 | - name: make 24 | run: make 25 | 26 | - name: make check 27 | run: make check 28 | 29 | - name: make distcheck 30 | run: make distcheck 31 | -------------------------------------------------------------------------------- /.github/workflows/build-check-windows.yml: -------------------------------------------------------------------------------- 1 | name: par2cmdline CI windows 2 | 3 | on: 4 | workflow_call: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | build-check-windows: 9 | 10 | runs-on: windows-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Add MSBuild to PATH 16 | uses: microsoft/setup-msbuild@v2 17 | 18 | - name: Build 19 | run: msbuild -property:PlatformToolset=ClangCL -property:Configuration=Release -property:Platform=x64 par2cmdline.sln 20 | -------------------------------------------------------------------------------- /.github/workflows/build-push.yml: -------------------------------------------------------------------------------- 1 | name: par2cmdline push build 2 | 3 | on: 4 | push: 5 | branches: 6 | - '**' 7 | - '!master' 8 | - '!turbo' 9 | 10 | jobs: 11 | build-check-linux: 12 | uses: ./.github/workflows/build-check-linux.yml 13 | 14 | build-check-windows: 15 | uses: ./.github/workflows/build-check-windows.yml 16 | 17 | build-check-macos: 18 | uses: ./.github/workflows/build-check-macos.yml 19 | 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # when developing and you really want to clean everything up 2 | # run git clean -fdx 3 | # thx @spider-mario 4 | 5 | # compilation output 6 | par2 7 | libpar2.a 8 | libparpar*.a 9 | *.o 10 | .deps/ 11 | par2.exe 12 | tests/*.exe 13 | 14 | # test output 15 | *.trs 16 | *.log 17 | tests/runtest* 18 | 19 | # unit test binaries 20 | tests/*_test 21 | tests/.dirstamp 22 | 23 | # autotools output 24 | aclocal.m4 25 | autom4te.cache/ 26 | compile 27 | test-driver 28 | Makefile.in 29 | Makefile 30 | config.h 31 | config.status 32 | configure 33 | stamp-h 34 | stamp-h1 35 | src/.dirstamp 36 | parpar/*/.dirstamp 37 | install-sh 38 | missing 39 | ar-lib 40 | 41 | # windows 42 | Release/ 43 | Debug/ 44 | *.old 45 | par2cmdline.vcxproj.user 46 | par2cmdline.suo 47 | .vs/ 48 | 49 | test.* 50 | # Linux perf record output 51 | perf.* 52 | # gcc -fprofile-use 53 | *.gcda 54 | 55 | # eclipse stuff you get when you point it at a Makefile project 56 | .cproject 57 | .project 58 | .settings 59 | 60 | # emacs files 61 | *~ 62 | .#* 63 | \#*# 64 | .~lock.*# 65 | 66 | .vscode 67 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Peter Brian Clements 2 | Marcel Partap 3 | Ike Devolder 4 | Jussi Kansanen 5 | Michael Nahas 6 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/NEWS -------------------------------------------------------------------------------- /automake.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | aclocal 6 | automake --warnings=all --add-missing 7 | autoconf --warnings=all 8 | -------------------------------------------------------------------------------- /build/build-debug.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export CFLAGS="-g -O0" 4 | export CXXFLAGS="-g -O0" 5 | 6 | # automake 7 | ./automake.sh 8 | # configure 9 | ./configure 10 | # make 11 | make 12 | -------------------------------------------------------------------------------- /build/build-static.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export CFLAGS="-O3 -pipe -fstack-protector-strong" 4 | export CXXFLAGS="-O3 -pipe -fstack-protector-strong" 5 | export LDFLAGS="-static -s" 6 | 7 | # automake 8 | ./automake.sh 9 | # configure 10 | ./configure 11 | # make 12 | make 13 | -------------------------------------------------------------------------------- /build/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export CFLAGS="-O3 -pipe -fstack-protector-strong" 4 | export CXXFLAGS="-O3 -pipe -fstack-protector-strong" 5 | 6 | # automake 7 | ./automake.sh 8 | # configure 9 | ./configure 10 | # make 11 | make 12 | -------------------------------------------------------------------------------- /build/release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | git clean -xfd 6 | build/build.sh 7 | make check 8 | make distcheck 9 | version=$(ls -1 par2cmdline*.tar.gz | tail -n1 | sed -e 's/par2cmdline-\([0-9\.]\+\)\.tar\.gz/\1/') 10 | [[ -d ../par2release ]] && rm -r ../par2release 11 | mkdir -p ../par2release 12 | mv par2cmdline-$version.tar.gz ../par2release 13 | ( 14 | cd ../par2release 15 | zcat par2cmdline-$version.tar.gz | bzip2 > par2cmdline-$version.tar.bz2 16 | ) 17 | 18 | # build/release-win.sh 19 | 20 | git tag -a --sign v$version 21 | -------------------------------------------------------------------------------- /build/sign-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ( 4 | cd ../par2release 5 | sha512sum *.tar* *.zip > checksums.sha512 6 | for file in *.tar* *.zip; do 7 | gpg --detach-sign $file 8 | done 9 | ) 10 | -------------------------------------------------------------------------------- /m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 44 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 45 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_COMPILE_FLAGS 54 | -------------------------------------------------------------------------------- /m4/ax_check_link_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the linker or gives an error. 12 | # (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the linker's default flags 18 | # when the check is done. The check is thus made with the flags: "LDFLAGS 19 | # EXTRA-FLAGS FLAG". This can for example be used to force the linker to 20 | # issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_LINK_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_LINK_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$LDFLAGS 44 | LDFLAGS="$LDFLAGS $4 $1" 45 | AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | LDFLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_LINK_FLAGS 54 | -------------------------------------------------------------------------------- /parpar/gf16/gf16_affine_avx10.c: -------------------------------------------------------------------------------- 1 | 2 | #include "gf16_global.h" 3 | #include "../src/platform.h" 4 | 5 | #define MWORD_SIZE 32 6 | #define _mword __m256i 7 | #define _MM(f) _mm256_ ## f 8 | #define _MMI(f) _mm256_ ## f ## _si256 9 | #define _FNSUFFIX _avx10 10 | #define _FNPREP(f) f##_avx10 11 | #define _MM_END _mm256_zeroupper(); 12 | 13 | // MSVC doesn't officially support AVX10 yet, so we don't compile this on MSVC 14 | #if defined(__GFNI__) && defined(__AVX512BW__) && defined(__AVX512VL__) && !defined(__EVEX512__) && (defined(__AVX10_1__) || defined(__EVEX256__)) 15 | # define _AVAILABLE 1 16 | #endif 17 | 18 | #define _EXCLUDE_FINISH_FUNCS 1 // ...because we can just use the AVX2 variants 19 | 20 | #include "gf16_affine_avx10.h" 21 | #ifdef _AVAILABLE 22 | # undef _AVAILABLE 23 | #endif 24 | #undef _MM_END 25 | #undef _FNSUFFIX 26 | #undef _FNPREP 27 | #undef _MMI 28 | #undef _MM 29 | #undef _mword 30 | #undef MWORD_SIZE 31 | #undef _EXCLUDE_FINISH_FUNCS 32 | -------------------------------------------------------------------------------- /parpar/gf16/gf16_bitdep_init_avx2.h: -------------------------------------------------------------------------------- 1 | 2 | #include "../src/hedley.h" 3 | #include "../src/platform.h" 4 | #ifdef __AVX2__ 5 | static inline __m256i gf16_bitdep256_swap(__m256i v, int genAffine) { 6 | if(genAffine) { 7 | // swap for affine2x 8 | return _mm256_permute4x64_epi64(v, _MM_SHUFFLE(1,2,0,3)); 9 | } else { 10 | // interleave so that word pairs are split 11 | __m256i swapped = _mm256_shuffle_epi8(v, _mm256_set_epi32( 12 | // first half -> slli_epi16(x, 8) 13 | 0x0e800c80, 0x0a800880, 0x06800480, 0x02800080, 14 | // second half -> srli_epi16(x, 8) 15 | 0x800f800d, 0x800b8009, 0x80078005, 0x80038001 16 | )); 17 | swapped = _mm256_permute2x128_si256(swapped, swapped, 0x01); 18 | // interleave 19 | return _mm256_blendv_epi8(v, swapped, _mm256_set_epi32( 20 | 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 21 | 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00 22 | )); 23 | } 24 | } 25 | #endif 26 | 27 | #ifdef __AVX2__ 28 | static void gf16_bitdep_init256(void* dst, int polynomial, int genAffine) { 29 | // expand polynomial into vector 30 | __m128i shuf = _mm_cmpeq_epi8( 31 | _mm_setzero_si128(), 32 | _mm_and_si128( 33 | _mm_shuffle_epi8( 34 | _mm_cvtsi32_si128(polynomial & 0xffff), 35 | _mm_set_epi32(0, 0, 0x01010101, 0x01010101) 36 | ), 37 | _mm_set_epi32(0x01020408, 0x10204080, 0x01020408, 0x10204080) 38 | ) 39 | ); 40 | /* AVX512 version: 41 | __m128i shuf = _mm_shuffle_epi8(_mm_movm_epi8(~(polynomial & 0xFFFF)), _mm_set_epi8( 42 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 43 | )); 44 | */ 45 | 46 | 47 | // pre-generate lookup tables for getting bitdeps 48 | __m256i addvals = genAffine ? _mm256_set_epi8( 49 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 50 | 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 51 | ) : _mm256_set_epi8( 52 | 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 53 | 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 54 | ); 55 | __m256i shuf2 = _mm256_inserti128_si256(_mm256_castsi128_si256(shuf), shuf, 1); 56 | for(int val=0; val<16; val++) { 57 | __m256i valtest = _mm256_set1_epi16(val << 12); 58 | __m256i addmask = _mm256_srai_epi16(valtest, 15); 59 | __m256i depmask = _mm256_and_si256(addvals, addmask); 60 | for(int i=0; i<3; i++) { 61 | // rotate 62 | __m256i last = _mm256_shuffle_epi8(depmask, shuf2); 63 | depmask = _mm256_srli_si256(depmask, 1); 64 | 65 | // XOR poly 66 | depmask = _mm256_xor_si256(depmask, last); 67 | 68 | valtest = _mm256_add_epi16(valtest, valtest); 69 | addmask = _mm256_srai_epi16(valtest, 15); 70 | addmask = _mm256_and_si256(addvals, addmask); 71 | 72 | depmask = _mm256_xor_si256(depmask, addmask); 73 | } 74 | _mm256_store_si256((__m256i*)dst + (val*4 + 0), gf16_bitdep256_swap(depmask, genAffine)); 75 | for(int j=1; j<4; j++) { 76 | for(int i=0; i<4; i++) { 77 | __m256i last = _mm256_shuffle_epi8(depmask, shuf2); 78 | depmask = _mm256_srli_si256(depmask, 1); 79 | depmask = _mm256_xor_si256(depmask, last); 80 | } 81 | _mm256_store_si256((__m256i*)dst + (val*4 + j), gf16_bitdep256_swap(depmask, genAffine)); 82 | } 83 | } 84 | } 85 | #endif 86 | -------------------------------------------------------------------------------- /parpar/gf16/gf16_checksum_sve.h: -------------------------------------------------------------------------------- 1 | #ifndef __GF16_CHECKSUM_H 2 | #define __GF16_CHECKSUM_H 3 | 4 | #include "gf16_sve_common.h" 5 | 6 | #ifdef __ARM_FEATURE_SVE 7 | static HEDLEY_ALWAYS_INLINE void gf16_checksum_block_sve(const void *HEDLEY_RESTRICT src, void *HEDLEY_RESTRICT checksum, const size_t blockLen, const int aligned) { 8 | UNUSED(aligned); 9 | const unsigned words = blockLen/svcntb(); 10 | 11 | svint16_t v = *(svint16_t*)checksum; 12 | v = gf16_vec_mul2_sve(v); 13 | int16_t* _src = (int16_t*)src; 14 | for(unsigned i=0; i 10 | # if defined(__clang__) && __clang_major__ < 16 11 | # define RV(f) f 12 | # else 13 | # define RV(f) __riscv_##f 14 | # endif 15 | 16 | 17 | // TODO: evaluate endian requirements 18 | # if __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ 19 | # define __RVV_LE 20 | # endif 21 | 22 | static HEDLEY_ALWAYS_INLINE vint16m1_t gf16_vec_mul2_rvv(vint16m1_t v) { 23 | size_t vl = RV(vsetvlmax_e16m1)(); 24 | vbool16_t maskPoly = RV(vmslt_vx_i16m1_b16)(v, 0, vl); 25 | v = RV(vadd_vv_i16m1)(v, v, vl); 26 | #ifdef __riscv_v_intrinsic 27 | return RV(vxor_vx_i16m1_mu) 28 | #else 29 | return RV(vxor_vx_i16m1_m) 30 | #endif 31 | ( 32 | maskPoly, 33 | v, v, 34 | GF16_POLYNOMIAL & 0xffff, 35 | vl 36 | ); 37 | } 38 | 39 | 40 | #endif 41 | 42 | #endif -------------------------------------------------------------------------------- /parpar/gf16/gf16_shuffle_avx.c: -------------------------------------------------------------------------------- 1 | 2 | #include "../src/platform.h" 3 | 4 | #define MWORD_SIZE 16 5 | #define _mword __m128i 6 | #define _MM(f) _mm_ ## f 7 | #define _MMI(f) _mm_ ## f ## _si128 8 | #define _FNSUFFIX _avx 9 | #define _MM_END 10 | 11 | #if defined(__AVX__) 12 | # define _AVAILABLE 13 | # define _AVAILABLE_AVX 14 | #endif 15 | #include "gf16_shuffle_x86.h" 16 | #undef _AVAILABLE 17 | #undef _AVAILABLE_AVX 18 | 19 | #undef MWORD_SIZE 20 | #undef _mword 21 | #undef _MM 22 | #undef _MMI 23 | #undef _FNSUFFIX 24 | #undef _MM_END 25 | 26 | -------------------------------------------------------------------------------- /parpar/gf16/gf16_shuffle_x86_prepare.h: -------------------------------------------------------------------------------- 1 | 2 | #include "gf16_shuffle_x86_common.h" 3 | #include "gf16_checksum_x86.h" 4 | 5 | static HEDLEY_ALWAYS_INLINE void _FN(gf16_shuffle_prepare_block)(void* dst, const void* src) { 6 | _mword ta = _MMI(loadu)((_mword*)src); 7 | _mword tb = _MMI(loadu)((_mword*)src + 1); 8 | 9 | ta = separate_low_high(ta); 10 | tb = separate_low_high(tb); 11 | 12 | _MMI(store)((_mword*)dst, 13 | _MM(unpackhi_epi64)(ta, tb) 14 | ); 15 | _MMI(store)((_mword*)dst + 1, 16 | _MM(unpacklo_epi64)(ta, tb) 17 | ); 18 | } 19 | // final block 20 | static HEDLEY_ALWAYS_INLINE void _FN(gf16_shuffle_prepare_blocku)(void* dst, const void* src, size_t remaining) { 21 | _mword ta, tb; 22 | if(remaining & sizeof(_mword)) 23 | ta = _MMI(loadu)((_mword*)src); 24 | else 25 | ta = partial_load(src, remaining); 26 | 27 | ta = separate_low_high(ta); 28 | 29 | if(remaining <= sizeof(_mword)) 30 | tb = _MMI(setzero)(); 31 | else { 32 | tb = partial_load((char*)src + sizeof(_mword), remaining - sizeof(_mword)); 33 | tb = separate_low_high(tb); 34 | } 35 | 36 | _MMI(store)((_mword*)dst, 37 | _MM(unpackhi_epi64)(ta, tb) 38 | ); 39 | _MMI(store)((_mword*)dst + 1, 40 | _MM(unpacklo_epi64)(ta, tb) 41 | ); 42 | } 43 | 44 | static HEDLEY_ALWAYS_INLINE void _FN(gf16_shuffle_finish_block)(void *HEDLEY_RESTRICT dst) { 45 | _mword ta = _MMI(load)((_mword*)dst); 46 | _mword tb = _MMI(load)((_mword*)dst + 1); 47 | 48 | _MMI(store)((_mword*)dst, _MM(unpacklo_epi8)(tb, ta)); 49 | _MMI(store)((_mword*)dst + 1, _MM(unpackhi_epi8)(tb, ta)); 50 | } 51 | 52 | static HEDLEY_ALWAYS_INLINE void _FN(gf16_shuffle_finish_copy_block)(void *HEDLEY_RESTRICT dst, const void *HEDLEY_RESTRICT src) { 53 | _mword ta = _MMI(load)((_mword*)src); 54 | _mword tb = _MMI(load)((_mword*)src + 1); 55 | 56 | _MMI(storeu)((_mword*)dst, _MM(unpacklo_epi8)(tb, ta)); 57 | _MMI(storeu)((_mword*)dst + 1, _MM(unpackhi_epi8)(tb, ta)); 58 | } 59 | 60 | static HEDLEY_ALWAYS_INLINE void _FN(gf16_shuffle_finish_copy_blocku)(void *HEDLEY_RESTRICT dst, const void *HEDLEY_RESTRICT src, size_t bytes) { 61 | _mword ta = _MMI(load)((_mword*)src); 62 | _mword tb = _MMI(load)((_mword*)src + 1); 63 | 64 | _mword a = _MM(unpacklo_epi8)(tb, ta); 65 | _mword b = _MM(unpackhi_epi8)(tb, ta); 66 | 67 | if(bytes & sizeof(_mword)) { 68 | _MMI(storeu)((_mword*)dst, a); 69 | bytes ^= sizeof(_mword); 70 | if(bytes) 71 | partial_store((_mword*)dst + 1, b, bytes); 72 | } else 73 | partial_store(dst, a, bytes); 74 | } 75 | -------------------------------------------------------------------------------- /parpar/gf16/gf16_sve_common.h: -------------------------------------------------------------------------------- 1 | #ifndef __GF16_SVE_COMMON_H 2 | #define __GF16_SVE_COMMON_H 3 | 4 | #include "gf16_global.h" 5 | #include "../src/platform.h" 6 | 7 | 8 | #if defined(__ARM_FEATURE_SVE) 9 | #define NOMASK(f, ...) f ## _x(svptrue_b8(), __VA_ARGS__) 10 | 11 | // headers 12 | # include 13 | 14 | 15 | static HEDLEY_ALWAYS_INLINE svint16_t gf16_vec_mul2_sve(svint16_t v) { 16 | return sveor_n_s16_m( 17 | svcmplt_n_s16(svptrue_b16(), v, 0), 18 | NOMASK(svadd_s16, v, v), 19 | GF16_POLYNOMIAL & 0xffff 20 | ); 21 | } 22 | 23 | 24 | // copying prepare block for both shuffle/clmul 25 | static HEDLEY_ALWAYS_INLINE void gf16_prepare_block_sve(void *HEDLEY_RESTRICT dst, const void *HEDLEY_RESTRICT src) { 26 | svst1_u8(svptrue_b8(), dst, svld1_u8(svptrue_b8(), src)); 27 | svst1_vnum_u8(svptrue_b8(), dst, 1, svld1_vnum_u8(svptrue_b8(), src, 1)); 28 | } 29 | static HEDLEY_ALWAYS_INLINE void gf16_prepare_half_block_sve(void *HEDLEY_RESTRICT dst, const void *HEDLEY_RESTRICT src) { 30 | svst1_u8(svptrue_b8(), dst, svld1_u8(svptrue_b8(), src)); 31 | } 32 | // final block 33 | static HEDLEY_ALWAYS_INLINE void gf16_prepare_blocku_sve(void *HEDLEY_RESTRICT dst, const void *HEDLEY_RESTRICT src, size_t remaining) { 34 | svst1_u8(svptrue_b8(), dst, svld1_u8(svwhilelt_b8((uint64_t)0, (uint64_t)remaining), src)); 35 | svst1_vnum_u8(svptrue_b8(), dst, 1, svld1_vnum_u8(svwhilelt_b8((uint64_t)svcntb(), (uint64_t)remaining), src, 1)); 36 | } 37 | static HEDLEY_ALWAYS_INLINE void gf16_prepare_half_blocku_sve(void *HEDLEY_RESTRICT dst, const void *HEDLEY_RESTRICT src, size_t remaining) { 38 | svst1_u8(svptrue_b8(), dst, svld1_u8(svwhilelt_b8((uint64_t)0, (uint64_t)remaining), src)); 39 | } 40 | static HEDLEY_ALWAYS_INLINE void gf16_finish_blocku_sve(void *HEDLEY_RESTRICT dst, const void *HEDLEY_RESTRICT src, size_t remaining) { 41 | svst1_u8(svwhilelt_b8((uint64_t)0, (uint64_t)remaining), dst, svld1_u8(svptrue_b8(), src)); 42 | svst1_vnum_u8(svwhilelt_b8((uint64_t)svcntb(), (uint64_t)remaining), dst, 1, svld1_vnum_u8(svptrue_b8(), src, 1)); 43 | } 44 | static HEDLEY_ALWAYS_INLINE void gf16_finish_half_blocku_sve(void *HEDLEY_RESTRICT dst, const void *HEDLEY_RESTRICT src, size_t remaining) { 45 | svst1_u8(svwhilelt_b8((uint64_t)0, (uint64_t)remaining), dst, svld1_u8(svptrue_b8(), src)); 46 | } 47 | 48 | static HEDLEY_ALWAYS_INLINE void gf16_checksum_prepare_sve(void *HEDLEY_RESTRICT dst, void *HEDLEY_RESTRICT checksum, const size_t blockLen, gf16_transform_block_rst prepareBlock) { 49 | ALIGN_TO(16, int16_t tmp[blockLen/2]); 50 | memset(tmp, 0, blockLen); 51 | svst1_s16(svptrue_b16(), tmp, *(svint16_t*)checksum); 52 | 53 | prepareBlock(dst, tmp); 54 | } 55 | #endif 56 | 57 | #endif -------------------------------------------------------------------------------- /parpar/gf16/gf16pmul.cpp: -------------------------------------------------------------------------------- 1 | #include "gf16pmul.h" 2 | #include "../src/cpuid.h" 3 | 4 | Gf16PMulFunc gf16pmul = nullptr; 5 | Galois16PointMulMethods gf16pmul_method = GF16PMUL_NONE; 6 | size_t gf16pmul_alignment = 1; 7 | size_t gf16pmul_blocklen = 1; 8 | 9 | void setup_pmul() { 10 | gf16pmul = nullptr; 11 | gf16pmul_method = GF16PMUL_NONE; 12 | gf16pmul_alignment = 1; 13 | gf16pmul_blocklen = 1; 14 | 15 | // CPU detection 16 | #ifdef PLATFORM_X86 17 | int cpuInfo[4]; 18 | int cpuInfoX[4]; 19 | _cpuid(cpuInfo, 1); 20 | bool hasClMul = ((cpuInfo[2] & 0x80202) == 0x80202); // SSE4.1 + SSSE3 + CLMUL 21 | bool hasAVX2 = false, hasVPCLMUL = false, hasGFNI = false; 22 | 23 | #if !defined(_MSC_VER) || _MSC_VER >= 1600 24 | _cpuidX(cpuInfoX, 7, 0); 25 | if((cpuInfo[2] & 0x1C000000) == 0x1C000000) { // has AVX + OSXSAVE + XSAVE 26 | int xcr = _GET_XCR() & 0xff; 27 | if((xcr & 6) == 6) { // AVX enabled 28 | hasAVX2 = cpuInfoX[1] & 0x20; 29 | hasVPCLMUL = hasAVX2 && (cpuInfoX[2] & 0x400); 30 | } 31 | } 32 | hasGFNI = (cpuInfoX[2] & 0x100) == 0x100; 33 | #endif 34 | 35 | if(!hasGFNI) gf16pmul_available_vpclgfni = 0; 36 | if(!hasVPCLMUL) { 37 | gf16pmul_available_vpclmul = 0; 38 | gf16pmul_available_vpclgfni = 0; 39 | } 40 | if(!hasAVX2) gf16pmul_available_avx2 = 0; 41 | if(!hasClMul) gf16pmul_available_sse = 0; 42 | 43 | if(gf16pmul_available_vpclgfni) { 44 | gf16pmul = &gf16pmul_vpclgfni; 45 | gf16pmul_method = GF16PMUL_VPCLMUL_GFNI; 46 | gf16pmul_alignment = 32; 47 | gf16pmul_blocklen = 64; 48 | } 49 | else if(gf16pmul_available_vpclmul) { 50 | gf16pmul = &gf16pmul_vpclmul; 51 | gf16pmul_method = GF16PMUL_VPCLMUL; 52 | gf16pmul_alignment = 32; 53 | gf16pmul_blocklen = 32; 54 | } 55 | else if(gf16pmul_available_avx2) { 56 | gf16pmul = &gf16pmul_avx2; 57 | gf16pmul_method = GF16PMUL_AVX2; 58 | gf16pmul_alignment = 32; 59 | gf16pmul_blocklen = 32; 60 | } 61 | else if(gf16pmul_available_sse) { 62 | gf16pmul = &gf16pmul_sse; 63 | gf16pmul_method = GF16PMUL_PCLMUL; 64 | gf16pmul_alignment = 16; 65 | gf16pmul_blocklen = 16; 66 | } 67 | #endif 68 | 69 | #ifdef PLATFORM_ARM 70 | if(!CPU_HAS_SVE2) gf16pmul_available_sve2 = 0; 71 | if(!CPU_HAS_NEON) gf16pmul_available_neon = 0; 72 | 73 | if(gf16pmul_available_sve2) { 74 | gf16pmul = &gf16pmul_sve2; 75 | gf16pmul_method = GF16PMUL_SVE2; 76 | gf16pmul_alignment = gf16pmul_sve2_width(); 77 | gf16pmul_blocklen = gf16pmul_alignment*2; 78 | } 79 | else if(gf16pmul_available_neon) { 80 | gf16pmul = &gf16pmul_neon; 81 | gf16pmul_method = GF16PMUL_NEON; 82 | gf16pmul_alignment = 16; 83 | gf16pmul_blocklen = 32; 84 | } 85 | #endif 86 | #ifdef __riscv 87 | if(!CPU_HAS_VECTOR || !CPU_HAS_GC || !CPU_HAS_Zvbc) gf16pmul_available_rvv = 0; 88 | 89 | if(gf16pmul_available_rvv) { 90 | gf16pmul = &gf16pmul_rvv; 91 | gf16pmul_method = GF16PMUL_RVV; 92 | gf16pmul_alignment = gf16pmul_rvv_width(); 93 | gf16pmul_blocklen = gf16pmul_alignment; 94 | } 95 | #endif 96 | } 97 | 98 | const char* gf16pmul_methodName(Galois16PointMulMethods method) { 99 | const char* names[] = { 100 | "None", 101 | "PCLMUL", 102 | "AVX2", 103 | "VPCLMUL", 104 | "VPCLMUL+GFNI", 105 | "NEON", 106 | "SVE2", 107 | "RVV+Zvbc" 108 | }; 109 | 110 | return names[(int)method]; 111 | } 112 | -------------------------------------------------------------------------------- /parpar/gf16/gf16pmul.h: -------------------------------------------------------------------------------- 1 | #ifndef __GF16PMUL_H__ 2 | #define __GF16PMUL_H__ 3 | 4 | #include "../src/hedley.h" 5 | #include 6 | 7 | enum Galois16PointMulMethods { 8 | GF16PMUL_NONE, 9 | GF16PMUL_PCLMUL, 10 | GF16PMUL_AVX2, 11 | GF16PMUL_VPCLMUL, 12 | GF16PMUL_VPCLMUL_GFNI, 13 | GF16PMUL_NEON, 14 | GF16PMUL_SVE2, 15 | GF16PMUL_RVV 16 | }; 17 | 18 | // TODO: consider multi-dest 19 | typedef void(*Gf16PMulFunc)(void *HEDLEY_RESTRICT dst, const void* src1, const void* src2, size_t len); 20 | extern Gf16PMulFunc gf16pmul; 21 | extern Galois16PointMulMethods gf16pmul_method; 22 | extern size_t gf16pmul_alignment; 23 | extern size_t gf16pmul_blocklen; 24 | const char* gf16pmul_methodName(Galois16PointMulMethods method); 25 | inline const char* gf16pmul_methodName() { 26 | return gf16pmul_methodName(gf16pmul_method); 27 | } 28 | 29 | void setup_pmul(); 30 | 31 | HEDLEY_BEGIN_C_DECLS 32 | #define _PMUL_DECL(f) \ 33 | void gf16pmul_##f(void *HEDLEY_RESTRICT dst, const void* src1, const void* src2, size_t len); \ 34 | extern int gf16pmul_available_##f 35 | 36 | _PMUL_DECL(sse); 37 | _PMUL_DECL(avx2); 38 | _PMUL_DECL(vpclmul); 39 | _PMUL_DECL(vpclgfni); 40 | _PMUL_DECL(neon); 41 | _PMUL_DECL(sve2); 42 | _PMUL_DECL(rvv); 43 | 44 | #undef _PMUL_DECL 45 | 46 | unsigned gf16pmul_sve2_width(); 47 | unsigned gf16pmul_rvv_width(); 48 | 49 | HEDLEY_END_C_DECLS 50 | 51 | #endif // defined(__GF16PMUL_H__) 52 | -------------------------------------------------------------------------------- /parpar/gf16/gf16pmul_avx2.c: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | #define _mword __m256i 4 | #define _MM(f) _mm256_ ## f 5 | #define _MMI(f) _mm256_ ## f ## _si256 6 | #define MWORD_SIZE 32 7 | #define _FNSUFFIX _avx2 8 | 9 | #if defined(__PCLMUL__) && defined(__AVX2__) 10 | # define _AVAILABLE 1 11 | #endif 12 | #include "gf16pmul_x86.h" 13 | -------------------------------------------------------------------------------- /parpar/gf16/gf16pmul_neon.c: -------------------------------------------------------------------------------- 1 | #include "gf16_global.h" 2 | 3 | #ifdef __ARM_NEON 4 | # define _AVAILABLE 5 | #endif 6 | #include "gf16_clmul_neon.h" 7 | 8 | #ifdef __ARM_NEON 9 | # undef _AVAILABLE 10 | 11 | int gf16pmul_available_neon = 1; 12 | 13 | void gf16pmul_neon(void *HEDLEY_RESTRICT dst, const void* src1, const void* src2, size_t len) { 14 | assert(len % sizeof(uint8x16_t)*2 == 0); 15 | 16 | const poly8_t* _src1 = (const poly8_t*)src1 + len; 17 | const poly8_t* _src2 = (const poly8_t*)src2 + len; 18 | uint8_t* _dst = (uint8_t*)dst + len; 19 | 20 | for(intptr_t ptr = -(intptr_t)len; ptr; ptr += sizeof(uint8x16_t)*2) { 21 | poly8x16x2_t data1 = vld2q_p8(_src1+ptr); 22 | poly8x16x2_t data2 = vld2q_p8(_src2+ptr); 23 | poly16x8_t low1 = vmull_p8(vget_low_p8(data1.val[0]), vget_low_p8(data2.val[0])); 24 | poly8x16_t dataMid1 = veorq_p8(data1.val[0], data1.val[1]); 25 | poly8x16_t dataMid2 = veorq_p8(data2.val[0], data2.val[1]); 26 | poly16x8_t mid1 = vmull_p8(vget_low_p8(dataMid1), vget_low_p8(dataMid2)); 27 | poly16x8_t high1 = vmull_p8(vget_low_p8(data1.val[1]), vget_low_p8(data2.val[1])); 28 | #ifdef __aarch64__ 29 | poly16x8_t low2 = pmull_high(data1.val[0], data2.val[0]); 30 | poly16x8_t mid2 = pmull_high(dataMid1, dataMid2); 31 | poly16x8_t high2 = pmull_high(data1.val[1], data2.val[1]); 32 | #else 33 | poly16x8_t low2 = vmull_p8(vget_high_p8(data1.val[0]), vget_high_p8(data2.val[0])); 34 | poly16x8_t mid2 = vmull_p8(vget_high_p8(dataMid1), vget_high_p8(dataMid2)); 35 | poly16x8_t high2 = vmull_p8(vget_high_p8(data1.val[1]), vget_high_p8(data2.val[1])); 36 | #endif 37 | 38 | gf16_clmul_neon_reduction(&low1, &low2, mid1, mid2, &high1, &high2); 39 | uint8x16x2_t out; 40 | out.val[0] = veorq_u8(vreinterpretq_u8_p16(low1), vreinterpretq_u8_p16(low2)); 41 | out.val[1] = veorq_u8(vreinterpretq_u8_p16(high1), vreinterpretq_u8_p16(high2)); 42 | vst2q_u8(_dst+ptr, out); 43 | } 44 | } 45 | 46 | #else // defined(__ARM_NEON) 47 | int gf16pmul_available_neon = 0; 48 | void gf16pmul_neon(void *HEDLEY_RESTRICT dst, const void* src1, const void* src2, size_t len) { 49 | UNUSED(dst); UNUSED(src1); UNUSED(src2); UNUSED(len); 50 | } 51 | #endif 52 | -------------------------------------------------------------------------------- /parpar/gf16/gf16pmul_rvv.c: -------------------------------------------------------------------------------- 1 | #include "gf16_global.h" 2 | #include "gf16_clmul_rvv.h" 3 | 4 | #ifdef RISCV_ZVBC_INTRIN 5 | int gf16pmul_available_rvv = 1; 6 | 7 | void gf16pmul_rvv(void *HEDLEY_RESTRICT dst, const void* src1, const void* src2, size_t len) { 8 | size_t vl = RV(vsetvlmax_e8m1)(); 9 | assert(len % vl == 0); 10 | 11 | const uint8_t* _src1 = (const uint8_t*)src1 + len; 12 | const uint8_t* _src2 = (const uint8_t*)src2 + len; 13 | uint8_t* _dst = (uint8_t*)dst + len; 14 | 15 | #if defined(__riscv_v_intrinsic) && __riscv_v_intrinsic >= 12000 16 | vbool32_t alt = RV(vreinterpret_b32)(RV(vmv_v_x_u8m1)(0xaa, vl)); 17 | #else 18 | vuint8m1_t altTmp = RV(vmv_v_x_u8m1)(0xaa, vl); 19 | vbool32_t alt = *(vbool32_t*)(&altTmp); 20 | #endif 21 | 22 | // TODO: consider using LMUL=2 23 | for(intptr_t ptr = -(intptr_t)len; ptr; ptr += vl) { 24 | vuint32m1_t s1 = RV(vle32_v_u32m1)((const uint32_t*)(_src1+ptr), vl); 25 | vuint32m1_t s2 = RV(vle32_v_u32m1)((const uint32_t*)(_src2+ptr), vl); 26 | vuint64m1_t tmp1 = RV(vreinterpret_v_u32m1_u64m1)(RV(vand_vx_u32m1)(s1, 0xffff, vl)); 27 | vuint64m1_t tmp2 = RV(vreinterpret_v_u32m1_u64m1)(RV(vand_vx_u32m1)(s2, 0xffff, vl)); 28 | vuint32m1_t raa = RV(vreinterpret_v_u64m1_u32m1)(RV(vclmul_vv_u64m1)(tmp1, tmp2, vl)); 29 | vuint32m1_t rab = RV(vreinterpret_v_u64m1_u32m1)(RV(vclmul_vv_u64m1)(RV(vsrl_vx_u64m1)(tmp1, 32, vl), tmp2, vl)); 30 | tmp1 = RV(vreinterpret_v_u32m1_u64m1)(RV(vsrl_vx_u32m1)(s1, 16, vl)); 31 | tmp2 = RV(vreinterpret_v_u32m1_u64m1)(RV(vsrl_vx_u32m1)(s2, 16, vl)); 32 | vuint32m1_t rba = RV(vreinterpret_v_u64m1_u32m1)(RV(vclmul_vv_u64m1)(tmp1, tmp2, vl)); 33 | vuint32m1_t rbb = RV(vreinterpret_v_u64m1_u32m1)(RV(vclmul_vv_u64m1)(RV(vsrl_vx_u64m1)(tmp1, 32, vl), tmp2, vl)); 34 | 35 | #ifdef __riscv_v_intrinsic 36 | vuint64m1_t ra = RV(vreinterpret_v_u32m1_u64m1)(RV(vmerge_vvm_u32m1)(raa, rab, alt, vl)); 37 | vuint64m1_t rb = RV(vreinterpret_v_u32m1_u64m1)(RV(vmerge_vvm_u32m1)(rba, rbb, alt, vl)); 38 | #else 39 | vuint64m1_t ra = RV(vreinterpret_v_u32m1_u64m1)(RV(vmerge_vvm_u32m1)(alt, raa, rab, vl)); 40 | vuint64m1_t rb = RV(vreinterpret_v_u32m1_u64m1)(RV(vmerge_vvm_u32m1)(alt, rba, rbb, vl)); 41 | #endif 42 | 43 | vuint16m1_t res = gf16_clmul_rvv_reduction(ra, rb, vl); 44 | RV(vse16_v_u16m1)((uint16_t*)(_dst+ptr), res, vl); 45 | } 46 | } 47 | 48 | unsigned gf16pmul_rvv_width() { 49 | return RV(vsetvlmax_e8m1)(); 50 | } 51 | 52 | #else // defined(RISCV_ZVBC_INTRIN) 53 | int gf16pmul_available_rvv = 0; 54 | void gf16pmul_rvv(void *HEDLEY_RESTRICT dst, const void* src1, const void* src2, size_t len) { 55 | UNUSED(dst); UNUSED(src1); UNUSED(src2); UNUSED(len); 56 | } 57 | 58 | unsigned gf16pmul_rvv_width() { 59 | return 1; 60 | } 61 | #endif 62 | -------------------------------------------------------------------------------- /parpar/gf16/gf16pmul_sse.c: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | #define _mword __m128i 4 | #define _MM(f) _mm_ ## f 5 | #define _MMI(f) _mm_ ## f ## _si128 6 | #define MWORD_SIZE 16 7 | #define _FNSUFFIX _sse 8 | 9 | #if defined(__PCLMUL__) && defined(__SSSE3__) && defined(__SSE4_1__) 10 | # define _AVAILABLE 1 11 | #endif 12 | #include "gf16pmul_x86.h" 13 | -------------------------------------------------------------------------------- /parpar/gf16/gf16pmul_sve2.c: -------------------------------------------------------------------------------- 1 | #include "gf16_global.h" 2 | #include "gf16_clmul_sve2.h" 3 | 4 | #ifdef __ARM_FEATURE_SVE2 5 | int gf16pmul_available_sve2 = 1; 6 | 7 | void gf16pmul_sve2(void *HEDLEY_RESTRICT dst, const void* src1, const void* src2, size_t len) { 8 | assert(len % svcntb()*2 == 0); 9 | 10 | const uint8_t* _src1 = (const uint8_t*)src1 + len; 11 | const uint8_t* _src2 = (const uint8_t*)src2 + len; 12 | uint8_t* _dst = (uint8_t*)dst + len; 13 | 14 | for(intptr_t ptr = -(intptr_t)len; ptr; ptr += svcntb()*2) { 15 | svuint8x2_t data1 = svld2_u8(svptrue_b8(), _src1+ptr); 16 | svuint8x2_t data2 = svld2_u8(svptrue_b8(), _src2+ptr); 17 | svuint8_t low1 = svpmullb_pair_u8(svget2(data1, 0), svget2(data2, 0)); 18 | svuint8_t low2 = svpmullt_pair_u8(svget2(data1, 0), svget2(data2, 0)); 19 | svuint8_t dataMid1 = NOMASK(sveor_u8, svget2(data1, 0), svget2(data1, 1)); 20 | svuint8_t dataMid2 = NOMASK(sveor_u8, svget2(data2, 0), svget2(data2, 1)); 21 | svuint8_t mid1 = svpmullb_pair_u8(dataMid1, dataMid2); 22 | svuint8_t mid2 = svpmullt_pair_u8(dataMid1, dataMid2); 23 | svuint8_t high1 = svpmullb_pair_u8(svget2(data1, 1), svget2(data2, 1)); 24 | svuint8_t high2 = svpmullt_pair_u8(svget2(data1, 1), svget2(data2, 1)); 25 | 26 | gf16_clmul_sve2_reduction(&low1, &low2, mid1, mid2, &high1, &high2); 27 | low1 = NOMASK(sveor_u8, low1, low2); 28 | high1 = NOMASK(sveor_u8, high1, high2); 29 | svst2_u8(svptrue_b8(), _dst+ptr, svcreate2_u8(low1, high1)); 30 | } 31 | } 32 | 33 | unsigned gf16pmul_sve2_width() { 34 | return svcntb(); 35 | } 36 | 37 | #else // defined(__ARM_FEATURE_SVE2) 38 | int gf16pmul_available_sve2 = 0; 39 | void gf16pmul_sve2(void *HEDLEY_RESTRICT dst, const void* src1, const void* src2, size_t len) { 40 | UNUSED(dst); UNUSED(src1); UNUSED(src2); UNUSED(len); 41 | } 42 | 43 | unsigned gf16pmul_sve2_width() { 44 | return 1; 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /parpar/gf16/gf16pmul_vpclgfni.c: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | #define _mword __m256i 4 | #define _MM(f) _mm256_ ## f 5 | #define _MMI(f) _mm256_ ## f ## _si256 6 | #define MWORD_SIZE 32 7 | #define _FNSUFFIX _vpclgfni 8 | 9 | #define _USE_VPCLMUL 1 10 | #define _USE_GFNI 1 11 | 12 | #if defined(__VPCLMULQDQ__) && defined(__GFNI__) && defined(__AVX2__) 13 | # define _AVAILABLE 1 14 | #endif 15 | #include "gf16pmul_x86.h" 16 | -------------------------------------------------------------------------------- /parpar/gf16/gf16pmul_vpclmul.c: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | #define _mword __m256i 4 | #define _MM(f) _mm256_ ## f 5 | #define _MMI(f) _mm256_ ## f ## _si256 6 | #define MWORD_SIZE 32 7 | #define _FNSUFFIX _vpclmul 8 | 9 | #define _USE_VPCLMUL 1 10 | 11 | #if defined(__VPCLMULQDQ__) && defined(__AVX2__) 12 | # define _AVAILABLE 1 13 | #endif 14 | #include "gf16pmul_x86.h" 15 | -------------------------------------------------------------------------------- /parpar/gf16/gf_add.h: -------------------------------------------------------------------------------- 1 | 2 | #include "../src/hedley.h" 3 | 4 | #ifdef PARPAR_INCLUDE_BASIC_OPS 5 | void gf_add_multi_generic(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len); 6 | void gf_add_multi_sse2(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len); 7 | void gf_add_multi_avx2(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len); 8 | void gf_add_multi_avx512(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len); 9 | void gf_add_multi_neon(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len); 10 | void gf_add_multi_sve(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len); 11 | void gf_add_multi_sve2(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len); 12 | void gf_add_multi_rvv(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len); 13 | #endif 14 | 15 | 16 | #ifdef PARPAR_INCLUDE_BASIC_OPS 17 | #define FUNCS(f) \ 18 | void gf_add_multi_packed_##f(unsigned packRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len); \ 19 | void gf_add_multi_packpf_##f(unsigned packRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) 20 | #else 21 | #define FUNCS(f) \ 22 | void gf_add_multi_packpf_##f(unsigned packRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) 23 | #endif 24 | 25 | #ifdef PLATFORM_AMD64 26 | FUNCS(v1i6_sse2); 27 | FUNCS(v2i3_sse2); 28 | FUNCS(v1i6_avx2); 29 | FUNCS(v16i1_avx2); 30 | FUNCS(v1i6_avx512); 31 | FUNCS(v1i12_avx512); 32 | FUNCS(v1i12_avx10); 33 | FUNCS(v2i3_avx512); 34 | FUNCS(v2i4_avx512); 35 | FUNCS(v2i6_avx512); 36 | FUNCS(v2i6_avx10); 37 | FUNCS(v16i6_avx512); 38 | #else 39 | FUNCS(v1i2_sse2); 40 | FUNCS(v1i1_avx2); 41 | FUNCS(v1i1_avx512); 42 | FUNCS(v1i2_avx512); 43 | FUNCS(v2i1_avx512); 44 | #endif 45 | FUNCS(v2i1_sse2); 46 | FUNCS(v16i1_sse2); 47 | FUNCS(v1i2_avx2); 48 | FUNCS(v2i1_avx2); 49 | FUNCS(v2i3_avx2); 50 | FUNCS(shuffle_neon); 51 | FUNCS(clmul_neon); 52 | FUNCS(sve); 53 | FUNCS(v1i6_sve2); 54 | FUNCS(v2i3_sve2); 55 | FUNCS(v2i4_sve2); 56 | FUNCS(v2i8_sve2); 57 | FUNCS(v2i3_rvv); 58 | FUNCS(v1i12_rvv); 59 | 60 | FUNCS(generic); 61 | FUNCS(lookup3); 62 | #undef FUNCS 63 | -------------------------------------------------------------------------------- /parpar/gf16/gf_add_avx10.c: -------------------------------------------------------------------------------- 1 | #include "gf16_global.h" 2 | #include "../src/platform.h" 3 | #include "gf_add_common.h" 4 | 5 | #define _mword __m256i 6 | #define _MM(f) _mm256_ ## f 7 | #define _MMI(f) _mm256_ ## f ## _si256 8 | #define _FNSUFFIX _avx10 9 | #if defined(__AVX512VL__) && !defined(__EVEX512__) && (defined(__AVX10_1__) || defined(__EVEX256__)) 10 | # define _AVAILABLE 11 | #endif 12 | #define _ADD_USE_TERNLOG 13 | 14 | #include "gf_add_x86.h" 15 | 16 | #undef _ADD_USE_TERNLOG 17 | #undef _FNSUFFIX 18 | #undef _MMI 19 | #undef _MM 20 | #undef _mword 21 | 22 | 23 | #ifdef _AVAILABLE 24 | # ifdef PARPAR_INCLUDE_BASIC_OPS 25 | # define PACKED_FUNC(vs, il, it) \ 26 | void gf_add_multi_packed_v##vs##i##il##_avx10(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len) { \ 27 | gf16_muladd_multi_packed((void*)vs, &gf_add_x_avx10, il, it, packedRegions, regions, dst, src, len, sizeof(__m256i)*vs, NULL); \ 28 | _mm256_zeroupper(); \ 29 | } \ 30 | void gf_add_multi_packpf_v##vs##i##il##_avx10(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 31 | gf16_muladd_multi_packpf((void*)vs, &gf_add_x_avx10, il, it, packedRegions, regions, dst, src, len, sizeof(__m256i)*vs, NULL, vs>1, prefetchIn, prefetchOut); \ 32 | _mm256_zeroupper(); \ 33 | } 34 | # else 35 | # define PACKED_FUNC(vs, il, it) \ 36 | void gf_add_multi_packpf_v##vs##i##il##_avx10(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 37 | gf16_muladd_multi_packpf((void*)vs, &gf_add_x_avx10, il, it, packedRegions, regions, dst, src, len, sizeof(__m256i)*vs, NULL, vs>1, prefetchIn, prefetchOut); \ 38 | _mm256_zeroupper(); \ 39 | } 40 | # endif 41 | #else 42 | # define PACKED_FUNC(vs, il, it) PACKED_STUB(avx10, vs, il, it) 43 | #endif 44 | 45 | #ifdef PLATFORM_AMD64 46 | PACKED_FUNC_NOTSLIM(avx10, 1, 12, 12) 47 | PACKED_FUNC(2, 6, 18) 48 | #endif 49 | 50 | #undef PACKED_FUNC 51 | 52 | #ifdef _AVAILABLE 53 | # undef _AVAILABLE 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /parpar/gf16/gf_add_avx2.c: -------------------------------------------------------------------------------- 1 | #include "gf16_global.h" 2 | #include "../src/platform.h" 3 | #include "gf_add_common.h" 4 | 5 | #define _mword __m256i 6 | #define _MM(f) _mm256_ ## f 7 | #define _MMI(f) _mm256_ ## f ## _si256 8 | #define _FNSUFFIX _avx2 9 | #ifdef __AVX2__ 10 | # define _AVAILABLE 11 | #endif 12 | 13 | #include "gf_add_x86.h" 14 | 15 | #ifdef _AVAILABLE 16 | # undef _AVAILABLE 17 | #endif 18 | #undef _FNSUFFIX 19 | #undef _MMI 20 | #undef _MM 21 | #undef _mword 22 | 23 | 24 | #ifdef PARPAR_INCLUDE_BASIC_OPS 25 | void gf_add_multi_avx2(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len) { 26 | #ifdef __AVX2__ 27 | gf16_muladd_multi((void*)1, &gf_add_x_avx2, 6, regions, offset, dst, src, len, NULL); 28 | _mm256_zeroupper(); 29 | #else 30 | UNUSED(regions); UNUSED(offset); UNUSED(dst); UNUSED(src); UNUSED(len); 31 | #endif 32 | } 33 | #endif 34 | 35 | #ifdef __AVX2__ 36 | # ifdef PARPAR_INCLUDE_BASIC_OPS 37 | # define PACKED_FUNC(vs, il, it) \ 38 | void gf_add_multi_packed_v##vs##i##il##_avx2(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len) { \ 39 | gf16_muladd_multi_packed((void*)vs, &gf_add_x_avx2, il, it, packedRegions, regions, dst, src, len, sizeof(__m256i)*vs, NULL); \ 40 | _mm256_zeroupper(); \ 41 | } \ 42 | void gf_add_multi_packpf_v##vs##i##il##_avx2(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 43 | gf16_muladd_multi_packpf((void*)vs, &gf_add_x_avx2, il, it, packedRegions, regions, dst, src, len, sizeof(__m256i)*vs, NULL, vs>1, prefetchIn, prefetchOut); \ 44 | _mm256_zeroupper(); \ 45 | } 46 | # else 47 | # define PACKED_FUNC(vs, il, it) \ 48 | void gf_add_multi_packpf_v##vs##i##il##_avx2(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 49 | gf16_muladd_multi_packpf((void*)vs, &gf_add_x_avx2, il, it, packedRegions, regions, dst, src, len, sizeof(__m256i)*vs, NULL, vs>1, prefetchIn, prefetchOut); \ 50 | _mm256_zeroupper(); \ 51 | } 52 | # endif 53 | #else 54 | # define PACKED_FUNC(vs, il, it) PACKED_STUB(avx2, vs, il, it) 55 | #endif 56 | 57 | PACKED_FUNC_NOTSLIM(avx2, 1, 2, 8) 58 | #ifdef PLATFORM_AMD64 59 | PACKED_FUNC_NOTSLIM(avx2, 1, 6, 18) 60 | PACKED_FUNC(16, 1, 6) 61 | #else 62 | PACKED_FUNC_NOTSLIM(avx2, 1, 1, 6) 63 | #endif 64 | PACKED_FUNC(2, 1, 6) 65 | PACKED_FUNC(2, 3, 12) 66 | 67 | #undef PACKED_FUNC 68 | -------------------------------------------------------------------------------- /parpar/gf16/gf_add_avx512.c: -------------------------------------------------------------------------------- 1 | #include "gf16_global.h" 2 | #include "../src/platform.h" 3 | #include "gf_add_common.h" 4 | 5 | #define _mword __m512i 6 | #define _MM(f) _mm512_ ## f 7 | #define _MMI(f) _mm512_ ## f ## _si512 8 | #define _FNSUFFIX _avx512 9 | #ifdef __AVX512F__ 10 | # define _AVAILABLE 11 | #endif 12 | #define _ADD_USE_TERNLOG 13 | 14 | #include "gf_add_x86.h" 15 | 16 | #undef _ADD_USE_TERNLOG 17 | #ifdef _AVAILABLE 18 | # undef _AVAILABLE 19 | #endif 20 | #undef _FNSUFFIX 21 | #undef _MMI 22 | #undef _MM 23 | #undef _mword 24 | 25 | 26 | #ifdef PARPAR_INCLUDE_BASIC_OPS 27 | void gf_add_multi_avx512(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len) { 28 | #ifdef __AVX512F__ 29 | gf16_muladd_multi((void*)1, &gf_add_x_avx512, 6, regions, offset, dst, src, len, NULL); 30 | _mm256_zeroupper(); 31 | #else 32 | UNUSED(regions); UNUSED(offset); UNUSED(dst); UNUSED(src); UNUSED(len); 33 | #endif 34 | } 35 | #endif 36 | 37 | #ifdef __AVX512F__ 38 | # ifdef PARPAR_INCLUDE_BASIC_OPS 39 | # define PACKED_FUNC(vs, il, it) \ 40 | void gf_add_multi_packed_v##vs##i##il##_avx512(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len) { \ 41 | gf16_muladd_multi_packed((void*)vs, &gf_add_x_avx512, il, it, packedRegions, regions, dst, src, len, sizeof(__m512i)*vs, NULL); \ 42 | _mm256_zeroupper(); \ 43 | } \ 44 | void gf_add_multi_packpf_v##vs##i##il##_avx512(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 45 | gf16_muladd_multi_packpf((void*)vs, &gf_add_x_avx512, il, it, packedRegions, regions, dst, src, len, sizeof(__m512i)*vs, NULL, vs>1, prefetchIn, prefetchOut); \ 46 | _mm256_zeroupper(); \ 47 | } 48 | # else 49 | # define PACKED_FUNC(vs, il, it) \ 50 | void gf_add_multi_packpf_v##vs##i##il##_avx512(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 51 | gf16_muladd_multi_packpf((void*)vs, &gf_add_x_avx512, il, it, packedRegions, regions, dst, src, len, sizeof(__m512i)*vs, NULL, vs>1, prefetchIn, prefetchOut); \ 52 | _mm256_zeroupper(); \ 53 | } 54 | # endif 55 | #else 56 | # define PACKED_FUNC(vs, il, it) PACKED_STUB(avx512, vs, il, it) 57 | #endif 58 | 59 | #ifdef PLATFORM_AMD64 60 | PACKED_FUNC_NOTSLIM(avx512, 1, 6, 18) 61 | PACKED_FUNC_NOTSLIM(avx512, 1, 12, 12) 62 | PACKED_FUNC(2, 3, 12) 63 | PACKED_FUNC(2, 4, 12) 64 | PACKED_FUNC(2, 6, 18) 65 | PACKED_FUNC_NOTSLIM(avx512, 16, 6, 18) 66 | #else 67 | PACKED_FUNC_NOTSLIM(avx512, 1, 1, 6) 68 | PACKED_FUNC_NOTSLIM(avx512, 1, 2, 8) 69 | PACKED_FUNC(2, 1, 6) 70 | #endif 71 | 72 | #undef PACKED_FUNC 73 | 74 | -------------------------------------------------------------------------------- /parpar/gf16/gf_add_common.h: -------------------------------------------------------------------------------- 1 | 2 | #ifdef PARPAR_INCLUDE_BASIC_OPS 3 | # define PACKED_STUB(suf, vs, il, it) \ 4 | void gf_add_multi_packed_v##vs##i##il##_##suf(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len) { \ 5 | UNUSED(packedRegions); UNUSED(regions); UNUSED(dst); UNUSED(src); UNUSED(len); \ 6 | } \ 7 | void gf_add_multi_packpf_v##vs##i##il##_##suf(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 8 | UNUSED(packedRegions); UNUSED(regions); UNUSED(dst); UNUSED(src); UNUSED(len); UNUSED(prefetchIn); UNUSED(prefetchOut); \ 9 | } 10 | #else 11 | # define PACKED_STUB(suf, vs, il, it) \ 12 | void gf_add_multi_packpf_v##vs##i##il##_##suf(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 13 | UNUSED(packedRegions); UNUSED(regions); UNUSED(dst); UNUSED(src); UNUSED(len); UNUSED(prefetchIn); UNUSED(prefetchOut); \ 14 | } 15 | #endif 16 | 17 | #ifndef PARPAR_SLIM_GF16 18 | # define PACKED_FUNC_NOTSLIM(suf, vs, il, it) PACKED_FUNC(vs, il, it) 19 | #else 20 | # define PACKED_FUNC_NOTSLIM PACKED_STUB 21 | #endif 22 | -------------------------------------------------------------------------------- /parpar/gf16/gf_add_sse2.c: -------------------------------------------------------------------------------- 1 | #include "gf16_global.h" 2 | #include "../src/platform.h" 3 | #include "gf_add_common.h" 4 | 5 | #define _mword __m128i 6 | #define _MM(f) _mm_ ## f 7 | #define _MMI(f) _mm_ ## f ## _si128 8 | #define _FNSUFFIX _sse2 9 | #ifdef __SSE2__ 10 | # define _AVAILABLE 11 | #endif 12 | 13 | #include "gf_add_x86.h" 14 | 15 | #ifdef _AVAILABLE 16 | # undef _AVAILABLE 17 | #endif 18 | #undef _FNSUFFIX 19 | #undef _MMI 20 | #undef _MM 21 | #undef _mword 22 | 23 | 24 | #ifdef PARPAR_INCLUDE_BASIC_OPS 25 | void gf_add_multi_sse2(unsigned regions, size_t offset, void *HEDLEY_RESTRICT dst, const void* const*HEDLEY_RESTRICT src, size_t len) { 26 | #ifdef __SSE2__ 27 | gf16_muladd_multi((void*)1, &gf_add_x_sse2, 4, regions, offset, dst, src, len, NULL); 28 | #else 29 | UNUSED(regions); UNUSED(offset); UNUSED(dst); UNUSED(src); UNUSED(len); 30 | #endif 31 | } 32 | #endif 33 | 34 | 35 | #ifdef __SSE2__ 36 | # ifdef PARPAR_INCLUDE_BASIC_OPS 37 | # define PACKED_FUNC(vs, il, it) \ 38 | void gf_add_multi_packed_v##vs##i##il##_sse2(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len) { \ 39 | gf16_muladd_multi_packed((void*)vs, &gf_add_x_sse2, il, it, packedRegions, regions, dst, src, len, sizeof(__m128i)*vs, NULL); \ 40 | } \ 41 | void gf_add_multi_packpf_v##vs##i##il##_sse2(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 42 | gf16_muladd_multi_packpf((void*)vs, &gf_add_x_sse2, il, it, packedRegions, regions, dst, src, len, sizeof(__m128i)*vs, NULL, vs>1, prefetchIn, prefetchOut); \ 43 | } 44 | # else 45 | # define PACKED_FUNC(vs, il, it) \ 46 | void gf_add_multi_packpf_v##vs##i##il##_sse2(unsigned packedRegions, unsigned regions, void *HEDLEY_RESTRICT dst, const void* HEDLEY_RESTRICT src, size_t len, const void* HEDLEY_RESTRICT prefetchIn, const void* HEDLEY_RESTRICT prefetchOut) { \ 47 | gf16_muladd_multi_packpf((void*)vs, &gf_add_x_sse2, il, it, packedRegions, regions, dst, src, len, sizeof(__m128i)*vs, NULL, vs>1, prefetchIn, prefetchOut); \ 48 | } 49 | # endif 50 | #else 51 | # define PACKED_FUNC(vs, il, it) PACKED_STUB(sse2, vs, il, it) 52 | #endif 53 | 54 | #ifdef PLATFORM_AMD64 55 | PACKED_FUNC_NOTSLIM(sse2, 1, 6, 18) 56 | PACKED_FUNC(2, 3, 12) 57 | #else 58 | PACKED_FUNC_NOTSLIM(sse2, 1, 2, 8) 59 | #endif 60 | PACKED_FUNC(2, 1, 4) 61 | PACKED_FUNC(16, 1, 4) 62 | 63 | #undef PACKED_FUNC 64 | -------------------------------------------------------------------------------- /parpar/gf16/gf_add_x86.h: -------------------------------------------------------------------------------- 1 | 2 | #include "gf16_muladd_multi.h" 3 | 4 | #ifdef _AVAILABLE 5 | static HEDLEY_ALWAYS_INLINE void _FN(gf_add_x)( 6 | const void *HEDLEY_RESTRICT scratch, uint8_t *HEDLEY_RESTRICT _dst, const unsigned srcScale, 7 | GF16_MULADD_MULTI_SRCLIST, size_t len, 8 | const uint16_t *HEDLEY_RESTRICT coefficients, 9 | const int doPrefetch, const char* _pf 10 | ) { 11 | ASSUME(((uintptr_t)_dst & (sizeof(_mword)-1)) == 0); 12 | ASSUME(len > 0); 13 | 14 | GF16_MULADD_MULTI_SRC_UNUSED(18); 15 | UNUSED(coefficients); 16 | unsigned vecStride = (unsigned)((uintptr_t)scratch); // abuse this otherwise unused variable 17 | ASSUME((len & (sizeof(_mword)*vecStride-1)) == 0); 18 | // vecStride assumed to be a known compile-time constant 19 | 20 | for(intptr_t ptr = -(intptr_t)len; ptr; ptr += sizeof(_mword)*vecStride) { 21 | for(unsigned v=0; v m) \ 28 | data = _MM(ternarylogic_epi32)(data, \ 29 | _MMI(load)((_mword*)(_src##m+ptr*srcScale) + v), \ 30 | _MMI(load)((_mword*)(_src##n+ptr*srcScale) + v), \ 31 | 0x96) 32 | #else 33 | # define ADD_PAIR(m, n) \ 34 | if(srcCount >= m) \ 35 | data = _MMI(xor)(data, _MMI(load)((_mword*)(_src##m+ptr*srcScale) + v)); \ 36 | if(srcCount >= n) \ 37 | data = _MMI(xor)(data, _MMI(load)((_mword*)(_src##n+ptr*srcScale) + v)) 38 | #endif 39 | ADD_PAIR(1, 2); 40 | ADD_PAIR(3, 4); 41 | ADD_PAIR(5, 6); 42 | ADD_PAIR(7, 8); 43 | ADD_PAIR(9, 10); 44 | ADD_PAIR(11, 12); 45 | ADD_PAIR(13, 14); 46 | ADD_PAIR(15, 16); 47 | ADD_PAIR(17, 18); 48 | #undef ADD_PAIR 49 | _MMI(store)((_mword*)(_dst+ptr) + v, data); 50 | } 51 | 52 | if(vecStride == 16) { 53 | // for xor kernels, need to do 4x prefetch 54 | if(doPrefetch) { 55 | const char* pfBase = _pf+(ptr>>1); 56 | if(doPrefetch == 1) { 57 | _mm_prefetch(pfBase, MM_HINT_WT1); 58 | _mm_prefetch(pfBase+64, MM_HINT_WT1); 59 | if(sizeof(_mword) > 16) { 60 | _mm_prefetch(pfBase+128, MM_HINT_WT1); 61 | _mm_prefetch(pfBase+192, MM_HINT_WT1); 62 | } 63 | if(sizeof(_mword) > 32) { 64 | _mm_prefetch(pfBase+256, MM_HINT_WT1); 65 | _mm_prefetch(pfBase+320, MM_HINT_WT1); 66 | _mm_prefetch(pfBase+384, MM_HINT_WT1); 67 | _mm_prefetch(pfBase+448, MM_HINT_WT1); 68 | } 69 | } 70 | if(doPrefetch == 2) { 71 | _mm_prefetch(pfBase, _MM_HINT_T1); 72 | _mm_prefetch(pfBase+64, _MM_HINT_T1); 73 | if(sizeof(_mword) > 16) { 74 | _mm_prefetch(pfBase+128, _MM_HINT_T1); 75 | _mm_prefetch(pfBase+192, _MM_HINT_T1); 76 | } 77 | if(sizeof(_mword) > 32) { 78 | _mm_prefetch(pfBase+256, _MM_HINT_T1); 79 | _mm_prefetch(pfBase+320, _MM_HINT_T1); 80 | _mm_prefetch(pfBase+384, _MM_HINT_T1); 81 | _mm_prefetch(pfBase+448, _MM_HINT_T1); 82 | } 83 | } 84 | } 85 | } else { 86 | if(doPrefetch == 1) 87 | _mm_prefetch(_pf+(ptr/vecStride), MM_HINT_WT1); 88 | if(doPrefetch == 2) 89 | _mm_prefetch(_pf+(ptr/vecStride), _MM_HINT_T1); 90 | } 91 | } 92 | } 93 | #endif 94 | -------------------------------------------------------------------------------- /parpar/gf16/gfmat_coeff.h: -------------------------------------------------------------------------------- 1 | #ifndef GFMAT_COEFF_H 2 | #define GFMAT_COEFF_H 3 | 4 | #include "../src/hedley.h" 5 | #include "../src/stdint.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | void gfmat_init(); 12 | void gfmat_free(); 13 | HEDLEY_CONST uint16_t gfmat_coeff_from_log(uint_fast16_t inputLog, uint_fast16_t recoveryBlock); 14 | HEDLEY_CONST uint16_t gfmat_coeff(uint_fast16_t inputBlock, uint_fast16_t recoveryBlock); 15 | HEDLEY_CONST uint16_t gfmat_input_log(uint_fast16_t inputBlock); 16 | HEDLEY_CONST uint16_t gfmat_coeff_log(uint_fast16_t inputLog, uint_fast16_t recoveryBlock); 17 | HEDLEY_CONST uint16_t gf16_exp(uint_fast16_t v); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /parpar/gf16/gfmat_inv.h: -------------------------------------------------------------------------------- 1 | #ifndef GFMAT_INV_H 2 | #define GFMAT_INV_H 3 | 4 | #include 5 | #include 6 | #include "../src/stdint.h" 7 | 8 | #ifdef PARPAR_INVERT_SUPPORT 9 | #include "../src/platform.h" // for _LE16 10 | const unsigned PP_INVERT_MAX_MULTI_ROWS = 6; // process up to 6 rows in a multi-mul call 11 | 12 | 13 | class Galois16Mul; 14 | class Galois16RecMatrixWorker; 15 | struct Galois16RecMatrixComputeState; 16 | class Galois16RecMatrix { 17 | uint16_t* mat; 18 | unsigned numStripes; 19 | unsigned stripeWidth; 20 | unsigned numRec; 21 | unsigned numThreads; 22 | void Construct(const std::vector& inputValid, unsigned validCount, const std::vector& recovery); 23 | 24 | template 25 | void invertLoop(unsigned stripeStart, unsigned stripeEnd, unsigned recFirst, unsigned recLast, unsigned recSrc, unsigned recSrcCount, uint16_t* rowCoeffs, unsigned coeffWidth, void* (&srcRowsBase)[PP_INVERT_MAX_MULTI_ROWS], Galois16Mul& gf, void* gfScratch, const void* nextPf, unsigned pfFactor); 26 | template 27 | int scaleRows(Galois16RecMatrixComputeState& state, unsigned rec, unsigned recFirst, unsigned recLast); 28 | void fillCoeffs(Galois16RecMatrixComputeState& state, unsigned rows, unsigned recFirst, unsigned recLast, unsigned rec, unsigned coeffWidth); 29 | template 30 | void applyRows(Galois16RecMatrixComputeState& state, unsigned rec, unsigned recCount, unsigned recFirst, unsigned recLast, unsigned coeffWidth, int nextRow); 31 | template 32 | int processRows(Galois16RecMatrixComputeState& state, unsigned& rec, unsigned rowGroupSize, std::function progressCb, uint16_t progressOffset, uint16_t totalProgress); 33 | public: 34 | Galois16RecMatrix(); 35 | ~Galois16RecMatrix(); 36 | void setNumThreads(int threads) { 37 | numThreads = threads; 38 | } 39 | bool Compute(const std::vector& inputValid, unsigned validCount, std::vector& recovery, std::function progressCb = nullptr); 40 | inline uint16_t GetFactor(uint16_t inIdx, uint16_t recIdx) const { 41 | // TODO: check if numStripes==1? consider optimising division? 42 | unsigned sw = stripeWidth/sizeof(uint16_t); 43 | unsigned stripe = inIdx / sw; 44 | return _LE16(mat[stripe * numRec*sw + recIdx * sw + (inIdx % sw)]); 45 | } 46 | 47 | // these should only be queried after Compute has started (i.e. from the progressCb, or after it returns) 48 | /*Galois16Methods*/ int regionMethod; 49 | const char* getPointMulMethodName() const; 50 | }; 51 | 52 | #endif 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /parpar/gf16/opencl-include/readme.txt: -------------------------------------------------------------------------------- 1 | The files in the CL directory are taken from the following: 2 | * https://github.com/KhronosGroup/OpenCL-Headers/releases/tag/v2023.04.17 3 | * https://github.com/KhronosGroup/OpenCL-CLHPP/releases/tag/v2023.04.17 4 | 5 | The OpenCL C++ header has been modified to remove dependency on cl_ext/cl_gl headers, and handle the function pointers introduced in the wrapper below. 6 | 7 | The cl.c/cl.h files here are a wrapper to enable runtime linking of OpenCL. 8 | cl.h will include the OpenCL C headers, and must be included before the C++ header. 9 | * users must include cl.c for compilation, and call load_opencl() before using any OpenCL functionality 10 | -------------------------------------------------------------------------------- /parpar/gf16/suppressions-valgrind.supp: -------------------------------------------------------------------------------- 1 | { 2 | 3 | Memcheck:Leak 4 | fun:malloc 5 | fun:gfmat_init 6 | } 7 | -------------------------------------------------------------------------------- /parpar/hasher/crc_arm.h: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | #include "../src/stdint.h" 3 | 4 | #if defined(_MSC_VER) && !defined(__clang__) 5 | #include 6 | #else 7 | #include 8 | #endif 9 | 10 | // function unused 11 | /* HEDLEY_MALLOC static void* crc_alloc_arm() { 12 | uint32_t* mem = (uint32_t*)malloc(4); 13 | *mem = 0xffffffff; 14 | return mem; 15 | } */ 16 | 17 | static HEDLEY_ALWAYS_INLINE void crc_init_arm(void* crc) { 18 | memset(crc, 0xff, sizeof(uint32_t)); 19 | } 20 | 21 | static HEDLEY_ALWAYS_INLINE void crc_process_block_arm(void* HEDLEY_RESTRICT crc, const void* HEDLEY_RESTRICT src) { 22 | uint32_t* _crc = (uint32_t*)crc; 23 | #ifdef __aarch64__ 24 | for(int i=0; i<8; i++) 25 | *_crc = __crc32d(*_crc, _LE64(read64((uint64_t *)src + i))); 26 | #else 27 | for(int i=0; i<16; i++) 28 | *_crc = __crc32w(*_crc, _LE32(read32((uint32_t *)src + i))); 29 | #endif 30 | } 31 | 32 | static HEDLEY_ALWAYS_INLINE uint32_t crc_finish_arm(void* HEDLEY_RESTRICT state, const void* HEDLEY_RESTRICT src, size_t len) { 33 | uint32_t crc = read32(state); 34 | uint8_t* src_ = (uint8_t*)src; 35 | #ifdef __aarch64__ 36 | while (len >= sizeof(uint64_t)) { 37 | crc = __crc32d(crc, _LE64(read64(src_))); 38 | src_ += sizeof(uint64_t); 39 | len -= sizeof(uint64_t); 40 | } 41 | if (len & sizeof(uint32_t)) { 42 | crc = __crc32w(crc, _LE32(read32(src_))); 43 | src_ += sizeof(uint32_t); 44 | } 45 | #else 46 | while (len >= sizeof(uint32_t)) { 47 | crc = __crc32w(crc, _LE32(read32(src_))); 48 | src_ += sizeof(uint32_t); 49 | len -= sizeof(uint32_t); 50 | } 51 | #endif 52 | if (len & sizeof(uint16_t)) { 53 | crc = __crc32h(crc, _LE16(read16(src_))); 54 | src_ += sizeof(uint16_t); 55 | } 56 | if (len & sizeof(uint8_t)) 57 | crc = __crc32b(crc, *src_); 58 | 59 | return ~crc; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /parpar/hasher/crc_slice4.h: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | #include "../src/stdint.h" 3 | 4 | // function currently unused 5 | /* HEDLEY_MALLOC static void* crc_alloc_slice4() { 6 | uint32_t* mem = (uint32_t*)malloc(4); 7 | *mem = 0xffffffff; 8 | return mem; 9 | } */ 10 | static HEDLEY_ALWAYS_INLINE void crc_init_slice4(void* crc) { 11 | memset(crc, 0xff, sizeof(uint32_t)); 12 | } 13 | 14 | 15 | // this is based off Fast CRC32 slice-by-4: https://create.stephan-brumme.com/crc32/ 16 | extern const uint32_t Crc32Lookup[4][256]; 17 | static HEDLEY_ALWAYS_INLINE uint32_t crc_process_iter_slice4(uint32_t crc, uint32_t current) { 18 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 19 | current ^= (((crc&0xff) << 24) | ((crc&0xff00) << 8) | ((crc>>8) & 0xff00) | ((crc>>24) & 0xff)); 20 | return Crc32Lookup[0][ current & 0xFF] ^ 21 | Crc32Lookup[1][(current>> 8) & 0xFF] ^ 22 | Crc32Lookup[2][(current>>16) & 0xFF] ^ 23 | Crc32Lookup[3][(current>>24) & 0xFF]; 24 | #else 25 | current ^= crc; 26 | return Crc32Lookup[0][(current>>24) & 0xFF] ^ 27 | Crc32Lookup[1][(current>>16) & 0xFF] ^ 28 | Crc32Lookup[2][(current>> 8) & 0xFF] ^ 29 | Crc32Lookup[3][ current & 0xFF]; 30 | #endif 31 | } 32 | 33 | static HEDLEY_ALWAYS_INLINE void crc_process_block_slice4(void* HEDLEY_RESTRICT state, const void* HEDLEY_RESTRICT src) { 34 | uint32_t crc = *(uint32_t*)state; 35 | const uint32_t* current = (uint32_t*)src; 36 | for(int i=0; i<16; i++) 37 | crc = crc_process_iter_slice4(crc, read32(current+i)); 38 | *(uint32_t*)state = crc; 39 | } 40 | 41 | static HEDLEY_ALWAYS_INLINE uint32_t crc_finish_slice4(void* HEDLEY_RESTRICT state, const void* HEDLEY_RESTRICT src, size_t len) { 42 | uint32_t crc = read32(state); 43 | const uint32_t* current = (uint32_t*)src; 44 | for(; len >= 4; len -= 4) 45 | crc = crc_process_iter_slice4(crc, read32(current++)); 46 | const uint8_t* currentChar = (const uint8_t*)current; 47 | while(len--) 48 | crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; 49 | return ~crc; 50 | } 51 | -------------------------------------------------------------------------------- /parpar/hasher/crc_zeropad.c: -------------------------------------------------------------------------------- 1 | #include "../src/hedley.h" 2 | #include "../src/stdint.h" 3 | 4 | // workaround MSVC complaining "unary minus operator applied to unsigned type, result still unsigned" 5 | #define NEGATE(n) (uint32_t)(-((int32_t)(n))) 6 | 7 | static HEDLEY_ALWAYS_INLINE uint32_t crc_multiply(uint32_t a, uint32_t b) { 8 | uint32_t res = 0; 9 | for(int i=0; i<31; i++) { 10 | res ^= NEGATE(b>>31) & a; 11 | a = ((a >> 1) ^ (0xEDB88320 & NEGATE(a&1))); 12 | b <<= 1; 13 | } 14 | res ^= NEGATE(b>>31) & a; 15 | return res; 16 | } 17 | /* clmul version 18 | static HEDLEY_ALWAYS_INLINE uint32_t crc_multiply(uint32_t a, uint32_t b) { 19 | // do the actual multiply 20 | __m128i prod = _mm_clmulepi64_si128(_mm_cvtsi32_si128(a), _mm_cvtsi32_si128(b), 0); 21 | 22 | // prepare product for reduction 23 | prod = _mm_add_epi64(prod, prod); // bit alignment fix, due to CRC32 being bit-reversal 24 | prod = _mm_slli_si128(prod, 4); // straddle low/high halves across 64-bit boundary - this provides automatic truncation during reduction 25 | 26 | // do Barrett reduction back into 32-bit field 27 | const __m128i reduction_const = _mm_set_epi32( 28 | 1, 0xdb710640, // polynomial * 2 29 | 0, 0xf7011641 // 2**63 / polynomial 30 | ); 31 | __m128i t = _mm_clmulepi64_si128(prod, reduction_const, 0); 32 | t = _mm_clmulepi64_si128(t, reduction_const, 0x10); 33 | t = _mm_xor_si128(t, prod); 34 | 35 | return _mm_extract_epi32(t, 2); 36 | } 37 | */ 38 | 39 | static const uint32_t crc_power[] = { // pre-computed 2^(2^n), with first 3 entries removed (saves a shift) 40 | 0x00800000, 0x00008000, 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467, 0xd7bbfe6a, 41 | 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 42 | 0x31fec169, 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37, 0x2e4e5eef, 0x4eaba214, 43 | 0xa8a472c0, 0x429a969e, 0x148d302a, 0xc40ba6d0, 0xc4e22c3c, 0x40000000, 0x20000000, 0x08000000 44 | }; 45 | /* above table can be computed with 46 | int main(void) { 47 | uint32_t k = 0x80000000 >> 1; 48 | for (size_t i = 0; i < 32+3; ++i) { 49 | if(i>2) printf("0x%08x, ", k); 50 | k = crc_multiply(k, k); 51 | } 52 | return 0; 53 | } 54 | */ 55 | uint32_t crc_zeroPad(uint32_t crc, uint64_t zeroPad) { 56 | // multiply by 2^(8n) 57 | unsigned power = 0; 58 | crc = ~crc; 59 | while(zeroPad) { 60 | if(zeroPad & 1) 61 | crc = crc_multiply(crc, crc_power[power]); 62 | zeroPad >>= 1; 63 | power = (power+1) & 31; 64 | } 65 | return ~crc; 66 | } 67 | -------------------------------------------------------------------------------- /parpar/hasher/crc_zeropad.h: -------------------------------------------------------------------------------- 1 | #ifndef __CRC_ZEROPAD_H 2 | #define __CRC_ZEROPAD_H 3 | 4 | #include "../src/stdint.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | #endif 9 | uint32_t crc_zeroPad(uint32_t crc, uint64_t zeroPad); 10 | 11 | #endif /* __CRC_ZEROPAD_H */ 12 | -------------------------------------------------------------------------------- /parpar/hasher/hasher.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASHER_H 2 | #define __HASHER_H 3 | 4 | void setup_hasher(); 5 | 6 | #ifdef PARPAR_ENABLE_HASHER_MD5CRC 7 | #include "hasher_md5crc.h" 8 | #define HASHER_MD5CRC_TYPE_MD5 1 9 | #define HASHER_MD5CRC_TYPE_CRC 2 10 | std::vector hasherMD5CRC_availableMethods(bool checkCpuid, int types=HASHER_MD5CRC_TYPE_MD5|HASHER_MD5CRC_TYPE_CRC); 11 | #endif 12 | 13 | #include "hasher_input.h" 14 | std::vector hasherInput_availableMethods(bool checkCpuid); 15 | 16 | #ifdef PARPAR_ENABLE_HASHER_MULTIMD5 17 | #include "hasher_md5mb.h" 18 | std::vector hasherMD5Multi_availableMethods(bool checkCpuid); 19 | #endif 20 | 21 | 22 | 23 | #endif /* __HASHER_H */ 24 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_armcrc.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | #if defined(PLATFORM_ARM) && defined(_MSC_VER) && defined(__clang__) && !defined(__ARM_FEATURE_CRC32) 4 | // I don't think GYP provides a nice way to detect whether MSVC or clang-cl is being used, but it doesn't use clang-cl by default, so a warning here is probably sufficient 5 | HEDLEY_WARNING("CRC32 acceleration is not enabled under ARM clang-cl by default; add `-march=armv8-a+crc` to additional compiler arguments to enable"); 6 | #endif 7 | 8 | // disable CRC on GCC versions with broken arm_acle.h 9 | #if defined(__ARM_FEATURE_CRC32) && defined(HEDLEY_GCC_VERSION) 10 | # if !defined(__aarch64__) && HEDLEY_GCC_VERSION_CHECK(7,0,0) && !HEDLEY_GCC_VERSION_CHECK(8,1,1) 11 | # undef __ARM_FEATURE_CRC32 12 | HEDLEY_WARNING("CRC32 acceleration has been disabled due to broken arm_acle.h shipped in GCC 7.0 - 8.1 [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81497]. If you need this feature, please use a different compiler or version of GCC"); 13 | # endif 14 | # if defined(__aarch64__) && HEDLEY_GCC_VERSION_CHECK(9,4,0) && !HEDLEY_GCC_VERSION_CHECK(9,5,0) 15 | # undef __ARM_FEATURE_CRC32 16 | HEDLEY_WARNING("CRC32 acceleration has been disabled due to broken arm_acle.h shipped in GCC 9.4 [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100985]. If you need this feature, please use a different compiler or version of GCC"); 17 | # endif 18 | #endif 19 | 20 | #if defined(__ARM_FEATURE_CRC32) && defined(__has_include) 21 | # if !__has_include() 22 | # undef __ARM_FEATURE_CRC32 23 | HEDLEY_WARNING("CRC32 acceleration has been disabled due to missing arm_acle.h"); 24 | # endif 25 | #endif 26 | 27 | #define HasherInput HasherInput_ARMCRC 28 | #define CRC32Impl(n) n##_ARMCRC 29 | #define MD5CRC(f) MD5CRC_##f##_ARMCRC 30 | #define _FNMD5(f) f##_scalar 31 | #define _FNMD5x2(f) f##_scalar 32 | #define _FNCRC(f) f##_arm 33 | 34 | #if defined(__ARM_FEATURE_CRC32) || (defined(_M_ARM64) && !defined(__clang__)) // MSVC doesn't support CRC for ARM32 35 | # include "crc_arm.h" 36 | # include "md5x2-scalar.h" 37 | # include "md5-scalar.h" 38 | # include "hasher_input_base.h" 39 | # include "hasher_md5crc_base.h" 40 | #else 41 | # include "hasher_input_stub.h" 42 | # include "hasher_md5crc_stub.h" 43 | #endif 44 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_avx2.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | 4 | #define MD5Multi MD5Multi_AVX2 5 | #define _FNMD5mb(f) f##_avx2 6 | #define _FNMD5mb2(f) f##_avx2 7 | #define md5mb_base_regions md5mb_regions_avx2 8 | #define md5mb_alignment md5mb_alignment_avx2 9 | #define CLEAR_VEC _mm256_zeroupper() 10 | 11 | 12 | #ifdef __AVX2__ 13 | # include "md5mb-sse.h" 14 | # include "hasher_md5mb_base.h" 15 | #else 16 | # include "hasher_md5mb_stub.h" 17 | #endif 18 | 19 | #undef MD5Multi 20 | #undef _FNMD5mb2 21 | #define MD5Multi MD5Multi2_AVX2 22 | #define _FNMD5mb2(f) f##2_avx2 23 | #define md5mb_interleave 2 24 | 25 | #ifdef __AVX2__ 26 | # include "hasher_md5mb_base.h" 27 | #else 28 | # include "hasher_md5mb_stub.h" 29 | #endif 30 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_avx512.cpp: -------------------------------------------------------------------------------- 1 | // suppress warning spam in GCC 12.0-12.2 (caused by some AVX512 intrinsics) 2 | #include "../src/hedley.h" 3 | #if HEDLEY_GCC_VERSION_CHECK(12,0,0) && !HEDLEY_GCC_VERSION_CHECK(12,3,0) 4 | # pragma GCC diagnostic push 5 | # pragma GCC diagnostic ignored "-Wuninitialized" 6 | # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 7 | #endif 8 | 9 | #include "../src/platform.h" 10 | 11 | 12 | #define MD5Multi MD5Multi_AVX512 13 | #define _FNMD5mb(f) f##_avx512 14 | #define _FNMD5mb2(f) f##_avx512 15 | #define md5mb_base_regions md5mb_regions_avx512 16 | #define md5mb_alignment md5mb_alignment_avx512 17 | #define CLEAR_VEC _mm256_zeroupper() 18 | 19 | #ifdef __AVX512F__ 20 | # include "md5mb-sse.h" 21 | # include "hasher_md5mb_base.h" 22 | #else 23 | # include "hasher_md5mb_stub.h" 24 | #endif 25 | 26 | 27 | #undef MD5Multi 28 | #undef _FNMD5mb2 29 | 30 | #define MD5Multi MD5Multi2_AVX512 31 | #define _FNMD5mb2(f) f##2_avx512 32 | #define md5mb_interleave 2 33 | 34 | #ifdef __AVX512F__ 35 | # include "hasher_md5mb_base.h" 36 | #else 37 | # include "hasher_md5mb_stub.h" 38 | #endif 39 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_avx512vl.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | // despite the name, this does also require AVX512BW 3 | 4 | #define _CRC_USE_AVX512_ 1 5 | #define HasherInput HasherInput_AVX512 6 | #define MD5SingleVer(f) MD5Single_##f##_AVX512 7 | #define MD5CRC(f) MD5CRC_##f##_AVX512 8 | #define _FNMD5(f) f##_avx512 9 | #define _FNMD5x2(f) f##_avx512 10 | #define _FNCRC(f) f##_clmul 11 | 12 | #if defined(__AVX512VL__) && defined(__AVX512BW__) 13 | # include "crc_clmul.h" 14 | # include "md5x2-sse.h" 15 | # include "md5-avx512.h" 16 | # include "hasher_input_base.h" 17 | # include "hasher_md5crc_base.h" 18 | #else 19 | # include "hasher_input_stub.h" 20 | # include "hasher_md5crc_stub.h" 21 | #endif 22 | 23 | 24 | #define MD5Multi MD5Multi_AVX512_128 25 | #define _FNMD5mb(f) f##_avx512_128 26 | #define _FNMD5mb2(f) f##_avx512_128 27 | #define md5mb_base_regions md5mb_regions_avx512_128 28 | #define md5mb_alignment md5mb_alignment_avx512_128 29 | #define CLEAR_VEC (void)0 30 | 31 | #if defined(__AVX512VL__) && defined(__AVX512BW__) 32 | # include "md5mb-sse.h" 33 | # include "hasher_md5mb_base.h" 34 | #else 35 | # include "hasher_md5mb_stub.h" 36 | #endif 37 | 38 | #undef MD5Multi 39 | #undef _FNMD5mb 40 | #undef _FNMD5mb2 41 | #undef md5mb_alignment 42 | #undef CLEAR_VEC 43 | #undef md5mb_base_regions 44 | 45 | #define MD5Multi MD5Multi_AVX512_256 46 | #define _FNMD5mb(f) f##_avx512_256 47 | #define _FNMD5mb2(f) f##_avx512_256 48 | #define md5mb_base_regions md5mb_regions_avx512_256 49 | #define md5mb_alignment md5mb_alignment_avx512_256 50 | #define CLEAR_VEC _mm256_zeroupper() 51 | 52 | #if defined(__AVX512VL__) && defined(__AVX512BW__) 53 | # include "hasher_md5mb_base.h" 54 | #else 55 | # include "hasher_md5mb_stub.h" 56 | #endif 57 | 58 | #if defined(__AVX512VL__) && defined(__AVX512BW__) && !defined(__EVEX512__) && (defined(__AVX10_1__) || defined(__EVEX256__)) 59 | bool hasher_avx10_compatible = true; 60 | #else 61 | bool hasher_avx10_compatible = false; 62 | #endif 63 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_bmi1.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | 4 | #define _MD5_USE_BMI1_ 1 5 | #define HasherInput HasherInput_BMI1 6 | #define MD5SingleVer(f) MD5Single_##f##_BMI1 7 | #define MD5CRC(f) MD5CRC_##f##_BMI1 8 | #define _FNMD5(f) f##_scalar 9 | #define _FNMD5x2(f) f##_scalar 10 | #define _FNCRC(f) f##_clmul 11 | 12 | #if defined(__PCLMUL__) && defined(__AVX__) && defined(__BMI__) 13 | # include "crc_clmul.h" 14 | # include "md5x2-scalar.h" 15 | # include "md5-scalar.h" 16 | # include "hasher_input_base.h" 17 | # include "hasher_md5crc_base.h" 18 | #else 19 | # include "hasher_input_stub.h" 20 | # include "hasher_md5crc_stub.h" 21 | #endif 22 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_clmul.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | #define _FNCRC(f) f##_clmul 4 | 5 | #define HasherInput HasherInput_ClMulSSE 6 | #define _FNMD5x2(f) f##_sse 7 | 8 | #if defined(__PCLMUL__) && defined(__SSSE3__) && defined(__SSE4_1__) 9 | # include "crc_clmul.h" 10 | # include "md5x2-sse.h" 11 | # include "hasher_input_base.h" 12 | #else 13 | # include "hasher_input_stub.h" 14 | #endif 15 | 16 | #undef HasherInput 17 | #undef _FNMD5x2 18 | #define HasherInput HasherInput_ClMulScalar 19 | #define CRC32Impl(n) n##_ClMul 20 | #define MD5CRC(f) MD5CRC_##f##_ClMul 21 | #define _FNMD5(f) f##_scalar 22 | #define _FNMD5x2(f) f##_scalar 23 | 24 | #if defined(__PCLMUL__) && defined(__SSSE3__) && defined(__SSE4_1__) 25 | # include "md5x2-scalar.h" 26 | # include "md5-scalar.h" 27 | # include "hasher_input_base.h" 28 | # include "hasher_md5crc_base.h" 29 | #else 30 | # include "hasher_input_stub.h" 31 | # include "hasher_md5crc_stub.h" 32 | #endif 33 | 34 | #undef MD5CRC 35 | #undef _FNMD5 36 | #undef CRC32Impl 37 | 38 | 39 | #define MD5SingleVer(f) MD5Single_##f##_NoLEA 40 | #define MD5CRC(f) MD5CRC_##f##_NoLEA 41 | #define _FNMD5(f) f##_nolea 42 | 43 | #if defined(__PCLMUL__) && defined(__SSSE3__) && defined(__SSE4_1__) && defined(MD5_HAS_NOLEA) 44 | # include "hasher_md5crc_base.h" 45 | #else 46 | # include "hasher_md5crc_stub.h" 47 | #endif 48 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_input.cpp: -------------------------------------------------------------------------------- 1 | #include "hasher_input.h" 2 | #include 3 | #include "../src/platform.h" 4 | 5 | IHasherInput*(*HasherInput_Create)() = NULL; 6 | HasherInputMethods HasherInput_Method = INHASH_SCALAR; 7 | 8 | bool set_hasherInput(HasherInputMethods method) { 9 | #define SET_HASHER(h, x) if(method == h) { \ 10 | if(!x::isAvailable) return false; \ 11 | HasherInput_Create = &x::create; \ 12 | HasherInput_Method = h; \ 13 | return true; \ 14 | } 15 | 16 | SET_HASHER(INHASH_SCALAR, HasherInput_Scalar) 17 | #ifdef PLATFORM_X86 18 | SET_HASHER(INHASH_SIMD, HasherInput_SSE) 19 | SET_HASHER(INHASH_CRC, HasherInput_ClMulScalar) 20 | SET_HASHER(INHASH_SIMD_CRC, HasherInput_ClMulSSE) 21 | SET_HASHER(INHASH_BMI1, HasherInput_BMI1) 22 | SET_HASHER(INHASH_AVX512, HasherInput_AVX512) 23 | #endif 24 | #ifdef PLATFORM_ARM 25 | SET_HASHER(INHASH_SIMD, HasherInput_NEON) 26 | SET_HASHER(INHASH_CRC, HasherInput_ARMCRC) 27 | SET_HASHER(INHASH_SIMD_CRC, HasherInput_NEONCRC) 28 | #endif 29 | #ifdef __riscv 30 | SET_HASHER(INHASH_CRC, HasherInput_RVZbc) 31 | #endif 32 | #undef SET_HASHER 33 | return false; 34 | } 35 | 36 | const char* hasherInput_methodName(HasherInputMethods m) { 37 | const char* names[] = { 38 | "Scalar+Generic", 39 | #ifdef PLATFORM_X86 40 | "SSE2+Generic", 41 | "Scalar+PCLMUL", 42 | "SSE2+PCLMUL", 43 | #elif defined(PLATFORM_ARM) 44 | "NEON+Generic", 45 | "Scalar+ARMCRC", 46 | "NEON+ARMCRC", 47 | #elif defined(__riscv) 48 | "SIMD+Generic", 49 | "Scalar+Zbc", 50 | "SIMD+Zbc", 51 | #else 52 | "SIMD+Generic", 53 | "Scalar+CRC", 54 | "SIMD+CRC", 55 | #endif 56 | "BMI1+PCLMUL", 57 | "AVX512" 58 | }; 59 | 60 | return names[(int)m]; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_input.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASHER_INPUT_H 2 | #define __HASHER_INPUT_H 3 | 4 | #include "hasher_input_impl.h" 5 | #include 6 | 7 | enum HasherInputMethods { 8 | INHASH_SCALAR, 9 | INHASH_SIMD, 10 | INHASH_CRC, 11 | INHASH_SIMD_CRC, 12 | INHASH_BMI1, 13 | INHASH_AVX512 14 | }; 15 | 16 | bool set_hasherInput(HasherInputMethods method); 17 | extern IHasherInput*(*HasherInput_Create)(); 18 | extern HasherInputMethods HasherInput_Method; 19 | const char* hasherInput_methodName(HasherInputMethods m); 20 | inline const char* hasherInput_methodName() { 21 | return hasherInput_methodName(HasherInput_Method); 22 | } 23 | 24 | #endif /* __HASHER_INPUT_H */ 25 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_input_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASHER_INPUT_IMPL_H 2 | #define __HASHER_INPUT_IMPL_H 3 | 4 | #include "../src/platform.h" 5 | #include "../src/stdint.h" 6 | #include "../src/hedley.h" 7 | #include 8 | #include 9 | 10 | #ifdef PARPAR_ENABLE_HASHER_MD5CRC 11 | #include "hasher_md5crc_impl.h" 12 | #endif 13 | 14 | class IHasherInput { 15 | protected: 16 | uint8_t tmp[128]; 17 | // TODO: merge md5/crc for ASM routines (also prevents a lot of duplication w/ inlining) 18 | ALIGN_TO(16, char md5State[64]); // large enough to handle all implementations of MD5 state (4x16B) 19 | #ifdef PLATFORM_X86 20 | char crcState[64]; // ClMul uses 4x16B state, others use 4B 21 | #elif defined(__riscv) 22 | char crcState[__riscv_xlen/2]; 23 | #else 24 | char crcState[4]; 25 | #endif 26 | uint_fast8_t tmpLen; 27 | uint_fast8_t posOffset; 28 | uint64_t dataLen[2]; 29 | public: 30 | virtual void update(const void* data, size_t len) = 0; 31 | virtual void getBlock(void* md5crc, uint64_t zeroPad) = 0; 32 | virtual void end(void* md5) = 0; 33 | virtual void reset() = 0; 34 | #ifdef PARPAR_ENABLE_HASHER_MD5CRC 35 | virtual void extractFileMD5(MD5Single& outMD5) = 0; 36 | #endif 37 | virtual ~IHasherInput() {} 38 | inline void destroy() { ALIGN_FREE(this); } \ 39 | }; 40 | 41 | #ifdef PARPAR_ENABLE_HASHER_MD5CRC 42 | # define __DECL_HASHERINPUT_EXTRACT void extractFileMD5(MD5Single& outMD5); 43 | #else 44 | # define __DECL_HASHERINPUT_EXTRACT 45 | #endif 46 | #define __DECL_HASHERINPUT(name) \ 47 | class HasherInput_##name : public IHasherInput { \ 48 | HasherInput_##name(); \ 49 | HasherInput_##name(const HasherInput_##name&); \ 50 | HasherInput_##name& operator=(const HasherInput_##name&); \ 51 | public: \ 52 | static const bool isAvailable; \ 53 | static inline HEDLEY_MALLOC IHasherInput* create() { \ 54 | HasherInput_##name* ptr; \ 55 | ALIGN_ALLOC(ptr, sizeof(HasherInput_##name), 16); \ 56 | return new(ptr) HasherInput_##name(); \ 57 | } \ 58 | void update(const void* data, size_t len); \ 59 | void getBlock(void* md5crc, uint64_t zeroPad); \ 60 | void end(void* md5); \ 61 | void reset(); \ 62 | __DECL_HASHERINPUT_EXTRACT \ 63 | } 64 | __DECL_HASHERINPUT(Scalar); 65 | __DECL_HASHERINPUT(SSE); 66 | __DECL_HASHERINPUT(ClMulScalar); 67 | __DECL_HASHERINPUT(ClMulSSE); 68 | __DECL_HASHERINPUT(BMI1); 69 | __DECL_HASHERINPUT(AVX512); 70 | __DECL_HASHERINPUT(ARMCRC); 71 | __DECL_HASHERINPUT(NEON); 72 | __DECL_HASHERINPUT(NEONCRC); 73 | __DECL_HASHERINPUT(RVZbc); 74 | #undef __DECL_HASHERINPUT_EXTRACT 75 | #undef __DECL_HASHERINPUT 76 | 77 | #endif /* __HASHER_INPUT_IMPL_H */ 78 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_input_stub.h: -------------------------------------------------------------------------------- 1 | #include "hasher_input_impl.h" 2 | 3 | #ifdef HasherInput 4 | const bool HasherInput::isAvailable = false; 5 | HasherInput::HasherInput() {} 6 | void HasherInput::reset() {} 7 | void HasherInput::update(const void*, size_t) {} 8 | void HasherInput::getBlock(void*, uint64_t) {} 9 | void HasherInput::end(void*) {} 10 | #ifdef PARPAR_ENABLE_HASHER_MD5CRC 11 | void HasherInput::extractFileMD5(MD5Single&) {} 12 | #endif 13 | #endif 14 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_md5crc.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASHER_MD5CRC_H 2 | #define __HASHER_MD5CRC_H 3 | 4 | #include "hasher_md5crc_impl.h" 5 | #include 6 | 7 | 8 | // single hash instances 9 | extern uint32_t(*CRC32_Calc)(const void*, size_t); 10 | extern MD5CRCMethods CRC32_Method; 11 | extern uint32_t(*MD5CRC_Calc)(const void*, size_t, size_t, void*); 12 | extern MD5CRCMethods MD5CRC_Method; 13 | 14 | bool set_hasherMD5CRC(MD5CRCMethods method); 15 | const char* md5crc_methodName(MD5CRCMethods m); 16 | inline const char* md5crc_methodName() { 17 | return md5crc_methodName(MD5CRC_Method); 18 | } 19 | 20 | 21 | #endif /* __HASHER_MD5CRC_H */ 22 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_md5crc_base.h: -------------------------------------------------------------------------------- 1 | 2 | #ifdef PARPAR_ENABLE_HASHER_MD5CRC 3 | 4 | #include "hasher_md5crc_impl.h" 5 | #include "crc_zeropad.h" 6 | #include 7 | 8 | #ifndef MD5_BLOCKSIZE 9 | # define MD5_BLOCKSIZE 64 10 | #endif 11 | 12 | #ifdef MD5SingleVer 13 | const bool MD5SingleVer(isAvailable) = true; 14 | void MD5SingleVer(update)(uint32_t* md5State, const void* data, size_t blocks) { 15 | const uint8_t* blockPtr[] = {(const uint8_t*)data}; 16 | uint32_t state[4]; 17 | state[0] = md5State[0]; 18 | state[1] = md5State[1]; 19 | state[2] = md5State[2]; 20 | state[3] = md5State[3]; 21 | while(blocks--) { 22 | _FNMD5(md5_process_block)(state, blockPtr, 0); 23 | blockPtr[0] += MD5_BLOCKSIZE; 24 | } 25 | md5State[0] = state[0]; 26 | md5State[1] = state[1]; 27 | md5State[2] = state[2]; 28 | md5State[3] = state[3]; 29 | } 30 | void MD5SingleVer(updateZero)(uint32_t* md5State, size_t blocks) { 31 | uint8_t data[64] = { 0 }; 32 | const uint8_t* blockPtr[] = {data}; 33 | uint32_t state[4]; 34 | state[0] = md5State[0]; 35 | state[1] = md5State[1]; 36 | state[2] = md5State[2]; 37 | state[3] = md5State[3]; 38 | while(blocks--) { 39 | _FNMD5(md5_process_block)(state, blockPtr, 0); 40 | } 41 | md5State[0] = state[0]; 42 | md5State[1] = state[1]; 43 | md5State[2] = state[2]; 44 | md5State[3] = state[3]; 45 | } 46 | #endif 47 | 48 | 49 | #ifdef MD5CRC 50 | #include "md5-final.h" 51 | const bool MD5CRC(isAvailable) = true; 52 | uint32_t MD5CRC(Calc)(const void* data, size_t length, size_t zeroPad, void* md5) { 53 | uint32_t md5State[4] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476}; 54 | #ifdef PLATFORM_X86 55 | ALIGN_TO(16, char crcState[64]); // ClMul uses 4x16B state, others use 4B 56 | #elif defined(__riscv) 57 | ALIGN_TO(8, char crcState[__riscv_xlen/2]); 58 | #else 59 | char crcState[4]; 60 | #endif 61 | const uint8_t* blockPtr[] = {(const uint8_t*)data}; 62 | size_t origLength = length; 63 | 64 | _FNCRC(crc_init)(crcState); 65 | 66 | while(length >= (unsigned)MD5_BLOCKSIZE) { 67 | _FNMD5(md5_process_block)(md5State, blockPtr, 0); 68 | _FNCRC(crc_process_block)(crcState, blockPtr[0]); 69 | blockPtr[0] += MD5_BLOCKSIZE; 70 | length -= MD5_BLOCKSIZE; 71 | } 72 | 73 | md5_final_block(md5State, blockPtr[0], origLength, zeroPad); 74 | memcpy(md5, md5State, 16); 75 | uint32_t crc = _FNCRC(crc_finish)(crcState, blockPtr[0], length); 76 | return crc_zeroPad(crc, zeroPad); 77 | } 78 | #endif 79 | 80 | 81 | #ifdef CRC32Impl 82 | const bool CRC32Impl(CRC32_isAvailable) = true; 83 | uint32_t CRC32Impl(CRC32_Calc)(const void* data, size_t len) { 84 | #ifdef PLATFORM_X86 85 | ALIGN_TO(16, char crcState[64]); // ClMul uses 4x16B state, others use 4B 86 | #elif defined(__riscv) 87 | ALIGN_TO(8, char crcState[__riscv_xlen/2]); 88 | #else 89 | char crcState[4]; 90 | #endif 91 | 92 | _FNCRC(crc_init)(crcState); 93 | const char* data_ = (const char*)data; 94 | 95 | while(len >= (unsigned)MD5_BLOCKSIZE) { 96 | _FNCRC(crc_process_block)(crcState, data_); 97 | data_ += MD5_BLOCKSIZE; 98 | len -= MD5_BLOCKSIZE; 99 | } 100 | 101 | return _FNCRC(crc_finish)(crcState, data_, len); 102 | } 103 | 104 | #endif 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_md5crc_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASHER_MD5CRC_IMPL_H 2 | #define __HASHER_MD5CRC_IMPL_H 3 | 4 | #include "../src/stdint.h" 5 | #include 6 | 7 | 8 | enum MD5CRCMethods { 9 | MD5CRCMETH_SCALAR, 10 | // MD5 11 | MD5CRCMETH_BMI1, 12 | MD5CRCMETH_NOLEA, 13 | MD5CRCMETH_AVX512, 14 | // CRC32 15 | MD5CRCMETH_ARMCRC, 16 | MD5CRCMETH_PCLMUL, 17 | MD5CRCMETH_RVZBC 18 | }; 19 | 20 | class MD5Single { 21 | public: 22 | // private internal state, but set by IHasherInput::extractFileMD5 23 | uint8_t tmp[64]; 24 | uint32_t md5State[4]; 25 | uint64_t dataLen; 26 | 27 | // private, set by setup_hasher 28 | static void(*_update)(uint32_t*, const void*, size_t); 29 | static void(*_updateZero)(uint32_t*, size_t); 30 | static MD5CRCMethods method; // public, read-only 31 | 32 | // public interface 33 | void reset() { 34 | md5State[0] = 0x67452301; 35 | md5State[1] = 0xefcdab89; 36 | md5State[2] = 0x98badcfe; 37 | md5State[3] = 0x10325476; 38 | dataLen = 0; 39 | } 40 | inline MD5Single() { reset(); } 41 | void update(const void* data, size_t len); 42 | void updateZero(size_t len); 43 | void end(void* md5); 44 | }; 45 | 46 | #define __DECL_MD5SINGLE(name) \ 47 | void MD5Single_update_##name(uint32_t*, const void*, size_t); \ 48 | void MD5Single_updateZero_##name(uint32_t*, size_t); \ 49 | extern const bool MD5Single_isAvailable_##name 50 | __DECL_MD5SINGLE(Scalar); 51 | __DECL_MD5SINGLE(NoLEA); 52 | __DECL_MD5SINGLE(BMI1); 53 | __DECL_MD5SINGLE(AVX512); 54 | #undef __DECL_MD5SINGLE 55 | 56 | 57 | #define __DECL_MD5CRC(name) \ 58 | uint32_t MD5CRC_Calc_##name(const void*, size_t, size_t, void*); \ 59 | extern const bool MD5CRC_isAvailable_##name 60 | __DECL_MD5CRC(Scalar); 61 | __DECL_MD5CRC(NoLEA); 62 | __DECL_MD5CRC(ClMul); 63 | __DECL_MD5CRC(BMI1); 64 | __DECL_MD5CRC(AVX512); 65 | __DECL_MD5CRC(ARMCRC); 66 | __DECL_MD5CRC(RVZbc); 67 | #undef __DECL_MD5CRC 68 | 69 | #define __DECL_CRC32(name) \ 70 | uint32_t CRC32_Calc_##name(const void*, size_t); \ 71 | extern const bool CRC32_isAvailable_##name 72 | __DECL_CRC32(Slice4); 73 | __DECL_CRC32(ClMul); 74 | //__DECL_CRC32(VClMul); 75 | __DECL_CRC32(ARMCRC); 76 | __DECL_CRC32(RVZbc); 77 | #undef __DECL_CRC32 78 | 79 | #endif /* __HASHER_MD5CRC_IMPL_H */ 80 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_md5crc_stub.h: -------------------------------------------------------------------------------- 1 | #ifdef PARPAR_ENABLE_HASHER_MD5CRC 2 | 3 | #include "hasher_md5crc_impl.h" 4 | 5 | #ifdef MD5SingleVer 6 | const bool MD5SingleVer(isAvailable) = false; 7 | void MD5SingleVer(update)(uint32_t*, const void*, size_t) {} 8 | void MD5SingleVer(updateZero)(uint32_t*, size_t) {} 9 | #endif 10 | 11 | #ifdef MD5CRC 12 | const bool MD5CRC(isAvailable) = false; 13 | uint32_t MD5CRC(Calc)(const void*, size_t, size_t, void*) { return 0; } 14 | #endif 15 | 16 | #ifdef CRC32Impl 17 | const bool CRC32Impl(CRC32_isAvailable) = false; 18 | uint32_t CRC32Impl(CRC32_Calc)(const void*, size_t) { return 0; } 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_md5mb.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASHER_MULTIMD5_H 2 | #define __HASHER_MULTIMD5_H 3 | 4 | #include "hasher_md5mb_impl.h" 5 | #include 6 | 7 | enum MD5MultiLevels { 8 | MD5MULT_SCALAR, 9 | 10 | MD5MULT_SSE, 11 | MD5MULT_AVX2, 12 | MD5MULT_XOP, 13 | MD5MULT_AVX10, 14 | MD5MULT_AVX512F, 15 | MD5MULT_AVX512VL, 16 | 17 | MD5MULT_NEON, 18 | MD5MULT_SVE2 19 | }; 20 | 21 | void set_hasherMD5MultiLevel(MD5MultiLevels level); 22 | extern MD5MultiLevels HasherMD5Multi_level; 23 | const char* hasherMD5Multi_methodName(MD5MultiLevels l); 24 | inline const char* hasherMD5Multi_methodName() { 25 | return hasherMD5Multi_methodName(HasherMD5Multi_level); 26 | } 27 | 28 | class MD5Multi { 29 | std::vector ctx; 30 | std::vector lastCtxData; 31 | unsigned lastCtxDataDup; 32 | 33 | // disable copy constructor 34 | MD5Multi(const MD5Multi&); 35 | MD5Multi& operator=(const MD5Multi&); 36 | 37 | public: 38 | explicit MD5Multi(int srcCount); 39 | ~MD5Multi(); 40 | void update(const void* const* data, size_t len); 41 | void get1(unsigned index, void* md5); 42 | void get(void* md5s); 43 | inline void end() { 44 | for(unsigned i=0; iend(); 46 | } 47 | inline void reset() { 48 | for(unsigned i=0; ireset(); 50 | } 51 | 52 | inline IMD5Multi* _getFirstCtx() const { // only used for testing 53 | return ctx[0]; 54 | } 55 | }; 56 | 57 | #endif /* __HASHER_MULTIMD5_H */ 58 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_md5mb_base.h: -------------------------------------------------------------------------------- 1 | #ifdef PARPAR_ENABLE_HASHER_MULTIMD5 2 | 3 | #include "hasher_md5mb_impl.h" 4 | #include 5 | 6 | #ifndef MD5_BLOCKSIZE 7 | # define MD5_BLOCKSIZE 64 8 | #endif 9 | 10 | #ifdef MD5Multi 11 | #ifdef md5mb_interleave 12 | # define md5mb_regions md5mb_base_regions*md5mb_interleave 13 | #else 14 | # define md5mb_regions md5mb_base_regions 15 | #endif 16 | 17 | const bool MD5Multi::isAvailable = true; 18 | int MD5Multi::getNumRegions() { 19 | return md5mb_regions; 20 | } 21 | MD5Multi::MD5Multi() : IMD5Multi(md5mb_regions, md5mb_alignment) { 22 | state = _FNMD5mb2(md5_alloc_mb)(); 23 | ALIGN_ALLOC(tmp, MD5_BLOCKSIZE*md5mb_regions, md5mb_alignment); 24 | 25 | tmpPtrs = new const void*[md5mb_regions]; 26 | for(unsigned input=0; input < md5mb_regions; input++) 27 | tmpPtrs[input] = tmp + MD5_BLOCKSIZE*input; 28 | 29 | reset(); 30 | } 31 | MD5Multi::~MD5Multi() { 32 | md5_free(state); 33 | ALIGN_FREE(tmp); 34 | delete[] tmpPtrs; 35 | } 36 | 37 | void MD5Multi::update(const void* const* data, size_t len) { 38 | dataLen += len; 39 | size_t p = 0; 40 | 41 | if(tmpLen) { 42 | uint_fast8_t wanted = MD5_BLOCKSIZE - tmpLen; 43 | uint_fast8_t copy = len < wanted ? len : wanted; 44 | 45 | for(unsigned input=0; input < md5mb_regions; input++) 46 | memcpy(tmp + MD5_BLOCKSIZE*input + tmpLen, data[input], copy); 47 | 48 | if(len < wanted) { 49 | tmpLen += len; 50 | return; 51 | } 52 | // process one block from tmp 53 | _FNMD5mb2(md5_update_block_mb)(state, tmpPtrs, 0); 54 | p = wanted; 55 | } 56 | 57 | for(; p+(MD5_BLOCKSIZE-1) < len; p+=MD5_BLOCKSIZE) { 58 | _FNMD5mb2(md5_update_block_mb)(state, data, p); 59 | } 60 | CLEAR_VEC; 61 | 62 | tmpLen = len - p; 63 | if(tmpLen) { 64 | for(unsigned input=0; input < md5mb_regions; input++) { 65 | memcpy(tmp + MD5_BLOCKSIZE*input, (char*)(data[input]) + p, tmpLen); 66 | } 67 | } 68 | } 69 | 70 | void MD5Multi::end() { 71 | _FNMD5mb2(md5_final_block_mb)(state, tmpPtrs, 0, dataLen); 72 | CLEAR_VEC; 73 | } 74 | 75 | void MD5Multi::get1(unsigned index, void* md5) { 76 | _FNMD5mb(md5_extract_mb)(md5, state, index); 77 | CLEAR_VEC; 78 | } 79 | void MD5Multi::get(void* md5s) { 80 | _FNMD5mb(md5_extract_all_mb)(md5s, state, 0); 81 | #ifdef md5mb_interleave 82 | char* md5_ = (char*)md5s; 83 | for(int i=1; i 6 | #include "../src/hedley.h" 7 | 8 | class IMD5Multi { 9 | public: 10 | virtual void update(const void* const* data, size_t len) = 0; 11 | virtual void get1(unsigned index, void* md5) = 0; 12 | virtual void get(void* md5s) = 0; 13 | virtual void end() = 0; 14 | virtual void reset() = 0; 15 | virtual ~IMD5Multi() {} 16 | const int numRegions; 17 | const unsigned alignment; 18 | protected: 19 | uint8_t* tmp; 20 | const void** tmpPtrs; 21 | uint8_t tmpLen; 22 | uint64_t dataLen; 23 | void* state; 24 | explicit IMD5Multi(int regions, unsigned align) : numRegions(regions), alignment(align) {} 25 | }; 26 | 27 | 28 | #define __DECL_MD5MULTI(name) \ 29 | class MD5Multi##name : public IMD5Multi { \ 30 | MD5Multi##name(const MD5Multi##name&); \ 31 | MD5Multi##name& operator=(const MD5Multi##name&); \ 32 | public: \ 33 | static const bool isAvailable; \ 34 | HEDLEY_CONST static int getNumRegions(); \ 35 | MD5Multi##name(); \ 36 | ~MD5Multi##name(); \ 37 | void update(const void* const* data, size_t len); \ 38 | void get1(unsigned index, void* md5); \ 39 | void get(void* md5s); \ 40 | void end(); \ 41 | void reset(); \ 42 | } 43 | __DECL_MD5MULTI(_Scalar); 44 | __DECL_MD5MULTI(2_Scalar); 45 | __DECL_MD5MULTI(_SSE); 46 | __DECL_MD5MULTI(2_SSE); 47 | __DECL_MD5MULTI(_XOP); 48 | __DECL_MD5MULTI(2_XOP); 49 | __DECL_MD5MULTI(_AVX2); 50 | __DECL_MD5MULTI(2_AVX2); 51 | __DECL_MD5MULTI(_AVX512_128); 52 | __DECL_MD5MULTI(_AVX512_256); 53 | __DECL_MD5MULTI(_AVX512); 54 | __DECL_MD5MULTI(2_AVX512); 55 | __DECL_MD5MULTI(_NEON); 56 | __DECL_MD5MULTI(2_NEON); 57 | __DECL_MD5MULTI(_SVE2); 58 | __DECL_MD5MULTI(2_SVE2); 59 | #undef __DECL_MD5MULTI 60 | 61 | #endif /* __HASHER_MD5MB_IMPL_H */ 62 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_md5mb_stub.h: -------------------------------------------------------------------------------- 1 | #ifdef PARPAR_ENABLE_HASHER_MULTIMD5 2 | 3 | #include "hasher_md5mb_impl.h" 4 | 5 | #ifdef MD5Multi 6 | int MD5Multi::getNumRegions() { return 0; } 7 | const bool MD5Multi::isAvailable = false; 8 | MD5Multi::MD5Multi() : IMD5Multi(0, 1) {} 9 | MD5Multi::~MD5Multi() {} 10 | 11 | void MD5Multi::update(const void* const*, size_t) {} 12 | void MD5Multi::end() {} 13 | void MD5Multi::get1(unsigned, void*) {} 14 | void MD5Multi::get(void*) {} 15 | void MD5Multi::reset() {} 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_neon.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | #include "crc_slice4.h" 3 | 4 | 5 | #define HasherInput HasherInput_NEON 6 | #define _FNMD5x2(f) f##_neon 7 | #define _FNCRC(f) f##_slice4 8 | #define MD5Multi MD5Multi_NEON 9 | #define _FNMD5mb(f) f##_neon 10 | #define _FNMD5mb2(f) f##_neon 11 | #define md5mb_base_regions md5mb_regions_neon 12 | #define md5mb_alignment md5mb_alignment_neon 13 | #define CLEAR_VEC (void)0 14 | 15 | #ifdef __ARM_NEON 16 | # include "md5x2-neon.h" 17 | # include "md5mb-neon.h" 18 | # include "hasher_input_base.h" 19 | # include "hasher_md5mb_base.h" 20 | #else 21 | # include "hasher_input_stub.h" 22 | # include "hasher_md5mb_stub.h" 23 | #endif 24 | 25 | #undef MD5Multi 26 | #undef _FNMD5mb2 27 | #define MD5Multi MD5Multi2_NEON 28 | #define _FNMD5mb2(f) f##2_neon 29 | #define md5mb_interleave 2 30 | 31 | #ifdef __ARM_NEON 32 | # include "hasher_md5mb_base.h" 33 | #else 34 | # include "hasher_md5mb_stub.h" 35 | #endif 36 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_neoncrc.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | // disable CRC on GCC versions with broken arm_acle.h 4 | #if defined(__ARM_FEATURE_CRC32) && defined(HEDLEY_GCC_VERSION) 5 | # if !defined(__aarch64__) && HEDLEY_GCC_VERSION_CHECK(7,0,0) && !HEDLEY_GCC_VERSION_CHECK(8,1,1) 6 | # undef __ARM_FEATURE_CRC32 7 | # endif 8 | # if defined(__aarch64__) && HEDLEY_GCC_VERSION_CHECK(9,4,0) && !HEDLEY_GCC_VERSION_CHECK(9,5,0) 9 | # undef __ARM_FEATURE_CRC32 10 | # endif 11 | #endif 12 | #if defined(__ARM_FEATURE_CRC32) && defined(__has_include) 13 | # if !__has_include() 14 | # undef __ARM_FEATURE_CRC32 15 | # endif 16 | #endif 17 | 18 | 19 | #define HasherInput HasherInput_NEONCRC 20 | #define _FNMD5x2(f) f##_neon 21 | #define _FNCRC(f) f##_arm 22 | 23 | #if (defined(__ARM_FEATURE_CRC32) && defined(__ARM_NEON)) || (defined(_M_ARM64) && !defined(__clang__)) // MSVC doesn't support CRC for ARM32 24 | # include "crc_arm.h" 25 | # include "md5x2-neon.h" 26 | # include "hasher_input_base.h" 27 | #else 28 | # include "hasher_input_stub.h" 29 | #endif 30 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_rvzbc.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | 4 | #define HasherInput HasherInput_RVZbc 5 | #define CRC32Impl(n) n##_RVZbc 6 | #define MD5CRC(f) MD5CRC_##f##_RVZbc 7 | #define _FNMD5(f) f##_scalar 8 | #define _FNMD5x2(f) f##_scalar 9 | #define _FNCRC(f) f##_rvzbc 10 | 11 | #if defined(__riscv) && defined(__GNUC__) && (defined(__riscv_zbkc) || defined(__riscv_zbc)) 12 | # include "crc_rvzbc.h" 13 | # include "md5x2-scalar.h" 14 | # include "md5-scalar.h" 15 | # include "hasher_input_base.h" 16 | # include "hasher_md5crc_base.h" 17 | #else 18 | # include "hasher_input_stub.h" 19 | # include "hasher_md5crc_stub.h" 20 | #endif 21 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_scalar.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | #include "md5-scalar.h" 3 | #include "md5x2-scalar.h" 4 | #include "md5mb-scalar.h" 5 | #include "crc_slice4.h" 6 | 7 | 8 | #define HasherInput HasherInput_Scalar 9 | #define MD5SingleVer(f) MD5Single_##f##_Scalar 10 | #define MD5CRC(f) MD5CRC_##f##_Scalar 11 | #define CRC32Impl(n) n##_Slice4 12 | #define _FNMD5(f) f##_scalar 13 | #define _FNMD5x2(f) f##_scalar 14 | #define _FNCRC(f) f##_slice4 15 | #define MD5Multi MD5Multi_Scalar 16 | #define _FNMD5mb(f) f##_scalar 17 | #define _FNMD5mb2(f) f##_scalar 18 | #define md5mb_base_regions md5mb_regions_scalar 19 | #define md5mb_alignment md5mb_alignment_scalar 20 | #define CLEAR_VEC (void)0 21 | 22 | #include "hasher_input_base.h" 23 | #include "hasher_md5crc_base.h" 24 | #include "hasher_md5mb_base.h" 25 | 26 | 27 | #undef MD5Multi 28 | #undef _FNMD5mb2 29 | #define MD5Multi MD5Multi2_Scalar 30 | #define _FNMD5mb2(f) f##2_scalar 31 | #define md5mb_interleave 2 32 | 33 | #include "hasher_md5mb_base.h" 34 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_sse.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | #include "crc_slice4.h" 3 | 4 | 5 | #define HasherInput HasherInput_SSE 6 | #define _FNMD5x2(f) f##_sse 7 | #define _FNCRC(f) f##_slice4 8 | #define MD5Multi MD5Multi_SSE 9 | #define _FNMD5mb(f) f##_sse 10 | #define _FNMD5mb2(f) f##_sse 11 | #define md5mb_base_regions md5mb_regions_sse 12 | #define md5mb_alignment md5mb_alignment_sse 13 | #define CLEAR_VEC (void)0 14 | 15 | #ifdef __SSE2__ 16 | # include "md5x2-sse.h" 17 | # include "md5mb-sse.h" 18 | # include "hasher_input_base.h" 19 | # include "hasher_md5mb_base.h" 20 | #else 21 | # include "hasher_input_stub.h" 22 | # include "hasher_md5mb_stub.h" 23 | #endif 24 | 25 | #undef MD5Multi 26 | #undef _FNMD5mb2 27 | #define MD5Multi MD5Multi2_SSE 28 | #define _FNMD5mb2(f) f##2_sse 29 | #define md5mb_interleave 2 30 | 31 | #ifdef __SSE2__ 32 | # include "hasher_md5mb_base.h" 33 | #else 34 | # include "hasher_md5mb_stub.h" 35 | #endif 36 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_sve2.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | 4 | #define MD5Multi MD5Multi_SVE2 5 | #define _FNMD5mb(f) f##_sve2 6 | #define _FNMD5mb2(f) f##_sve2 7 | #define md5mb_base_regions md5mb_regions_sve2 8 | #define md5mb_alignment md5mb_alignment_sve2 9 | #define CLEAR_VEC (void)0 10 | 11 | 12 | #ifdef __ARM_FEATURE_SVE2 13 | # include 14 | # include "md5mb-sve2.h" 15 | # include "hasher_md5mb_base.h" 16 | #else 17 | # include "hasher_md5mb_stub.h" 18 | #endif 19 | 20 | #undef MD5Multi 21 | #undef _FNMD5mb2 22 | #define MD5Multi MD5Multi2_SVE2 23 | #define _FNMD5mb2(f) f##2_sve2 24 | #define md5mb_interleave 2 25 | 26 | #ifdef __ARM_FEATURE_SVE2 27 | # include "hasher_md5mb_base.h" 28 | #else 29 | # include "hasher_md5mb_stub.h" 30 | #endif 31 | -------------------------------------------------------------------------------- /parpar/hasher/hasher_xop.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/platform.h" 2 | 3 | 4 | #define MD5Multi MD5Multi_XOP 5 | #define _FNMD5mb(f) f##_xop 6 | #define _FNMD5mb2(f) f##_xop 7 | #define md5mb_base_regions md5mb_regions_xop 8 | #define md5mb_alignment md5mb_alignment_xop 9 | #define CLEAR_VEC (void)0 10 | 11 | 12 | #if defined(_MSC_VER) && !defined(__clang__) && !defined(__XOP__) && defined(__AVX__) 13 | # define __XOP__ 1 14 | #endif 15 | 16 | 17 | #ifdef __XOP__ 18 | # include "md5mb-sse.h" 19 | # include "hasher_md5mb_base.h" 20 | #else 21 | # include "hasher_md5mb_stub.h" 22 | #endif 23 | 24 | #undef MD5Multi 25 | #undef _FNMD5mb2 26 | #define MD5Multi MD5Multi2_XOP 27 | #define _FNMD5mb2(f) f##2_xop 28 | #define md5mb_interleave 2 29 | 30 | #ifdef __XOP__ 31 | # include "hasher_md5mb_base.h" 32 | #else 33 | # include "hasher_md5mb_stub.h" 34 | #endif 35 | -------------------------------------------------------------------------------- /parpar/hasher/md5-avx512.h: -------------------------------------------------------------------------------- 1 | 2 | #if (defined(__GNUC__) || defined(__clang__)) && defined(__AVX512VL__) && defined(PLATFORM_AMD64) 3 | # define MD5_USE_ASM 4 | # include "md5-avx512-asm.h" 5 | #endif 6 | 7 | #define ADD _mm_add_epi32 8 | #define state_word_t uint32_t 9 | #define word_t __m128i 10 | #define ROTATE _mm_rol_epi32 11 | #define LOAD_STATE(state, word) _mm_cvtsi32_si128(state[word]) 12 | // work around missing _mm_storeu_si32: https://stackoverflow.com/questions/58063933/how-can-a-sse2-function-be-missing-from-the-header-it-is-supposed-to-be-in 13 | #define SET_STATE(state, word, val) _mm_store_ss((float*)(state + word), _mm_castsi128_ps(val)) 14 | #define INPUT(k, set, ptr, offs, idx, var) ( \ 15 | idx < 8 ? ( \ 16 | idx < 4 ? ( \ 17 | idx < 2 ? ( \ 18 | idx == 0 ? XX1 : XX2 \ 19 | ) : ( \ 20 | idx == 2 ? _mm_unpackhi_epi64(XX1, XX1) : _mm_unpackhi_epi64(XX2, XX2) \ 21 | ) \ 22 | ) : ( \ 23 | idx < 6 ? ( \ 24 | idx == 4 ? XX5 : XX6 \ 25 | ) : ( \ 26 | idx == 6 ? _mm_unpackhi_epi64(XX5, XX5) : _mm_unpackhi_epi64(XX6, XX6) \ 27 | ) \ 28 | ) \ 29 | ) : ( \ 30 | idx < 12 ? ( \ 31 | idx < 10 ? ( \ 32 | idx == 8 ? XX9 : XX10 \ 33 | ) : ( \ 34 | idx == 10 ? _mm_unpackhi_epi64(XX9, XX9) : _mm_unpackhi_epi64(XX10, XX10) \ 35 | ) \ 36 | ) : ( \ 37 | idx < 14 ? ( \ 38 | idx == 12 ? XX13 : XX14 \ 39 | ) : ( \ 40 | idx == 14 ? _mm_unpackhi_epi64(XX13, XX13) : _mm_unpackhi_epi64(XX14, XX14) \ 41 | ) \ 42 | ) \ 43 | ) \ 44 | ) 45 | #define LOAD INPUT 46 | #define LOAD16(set, ptr, offs, var0, var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15) { \ 47 | var0 = _mm_loadu_si128((__m128i*)(ptr[set])); \ 48 | var4 = _mm_loadu_si128((__m128i*)(ptr[set]) + 1); \ 49 | var8 = _mm_loadu_si128((__m128i*)(ptr[set]) + 2); \ 50 | var12 = _mm_loadu_si128((__m128i*)(ptr[set]) + 3); \ 51 | } 52 | #define ADD16(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15) { \ 53 | var1 = _mm_add_epi32(var0, _mm_set_epi32(k3, k2, k1, k0)); \ 54 | var5 = _mm_add_epi32(var4, _mm_set_epi32(k7, k6, k5, k4)); \ 55 | var9 = _mm_add_epi32(var8, _mm_set_epi32(k11, k10, k9, k8)); \ 56 | var13 = _mm_add_epi32(var12, _mm_set_epi32(k15, k14, k13, k12)); \ 57 | var2 = _mm_srli_epi64(var1, 32); \ 58 | var6 = _mm_srli_epi64(var5, 32); \ 59 | var10 = _mm_srli_epi64(var9, 32); \ 60 | var14 = _mm_srli_epi64(var13, 32); \ 61 | } 62 | 63 | #include 64 | 65 | #define F(b,c,d) _mm_ternarylogic_epi32(d,c,b,0xD8) 66 | #define G(b,c,d) _mm_ternarylogic_epi32(d,c,b,0xAC) 67 | #define H(b,c,d) _mm_ternarylogic_epi32(d,c,b,0x96) 68 | #define I(b,c,d) _mm_ternarylogic_epi32(d,c,b,0x63) 69 | 70 | #define FNB(f) f##_avx512 71 | #include "md5-base.h" 72 | #undef FNB 73 | 74 | 75 | #undef ADD 76 | #undef word_t 77 | // state_word_t undef'd by md5-base.h 78 | #undef ROTATE 79 | #undef LOAD_STATE 80 | #undef SET_STATE 81 | #undef INPUT 82 | #undef LOAD 83 | #undef LOAD16 84 | #undef ADD16 85 | #undef F 86 | #undef G 87 | #undef H 88 | #undef I 89 | 90 | #ifdef MD5_USE_ASM 91 | # undef MD5_USE_ASM 92 | #endif 93 | 94 | -------------------------------------------------------------------------------- /parpar/hasher/md5-final.c: -------------------------------------------------------------------------------- 1 | // single scalar implementation for finishing block 2 | #include "md5-scalar.h" 3 | 4 | void md5_final_block(void* state, const void *HEDLEY_RESTRICT data, uint64_t totalLength, uint64_t zeroPad) { 5 | ALIGN_TO(8, uint8_t block[64]); 6 | const uint8_t* blockPtr[] = {block}; 7 | size_t remaining = totalLength & 63; 8 | memcpy(block, data, remaining); 9 | memset(block + remaining, 0, 64-remaining); 10 | 11 | totalLength += zeroPad; 12 | int loopState = (remaining + zeroPad < 64)*2; 13 | // write this in a funky loop to avoid duplicating the force-inlined process_block function twice 14 | while(1) { 15 | if(loopState == 1 && zeroPad < 64) loopState = 2; 16 | if(loopState == 2) { 17 | remaining = totalLength & 63; 18 | block[remaining++] = 0x80; 19 | 20 | if(remaining <= 64-8) 21 | loopState = 4; 22 | else { 23 | loopState = 3; 24 | remaining = 0; 25 | } 26 | } 27 | 28 | if(loopState == 4) { 29 | memset(block + remaining, 0, 64-8 - remaining); 30 | 31 | totalLength <<= 3; // bytes -> bits 32 | write64(block + 64-8, _LE64(totalLength)); 33 | } 34 | 35 | md5_process_block_scalar((uint32_t*)state, blockPtr, 0); 36 | 37 | if(loopState == 4) break; 38 | else if(loopState == 3) loopState = 4; 39 | else if(loopState == 1) zeroPad -= 64; 40 | else if(loopState == 0) { 41 | memset(block, 0, 64); 42 | zeroPad -= 64-remaining; 43 | loopState = 1; 44 | } 45 | } 46 | 47 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 48 | uint32_t* hash = (uint32_t*)state; 49 | write32(hash+0, _LE32(read32(hash+0))); 50 | write32(hash+1, _LE32(read32(hash+1))); 51 | write32(hash+2, _LE32(read32(hash+2))); 52 | write32(hash+3, _LE32(read32(hash+3))); 53 | #endif 54 | } 55 | 56 | -------------------------------------------------------------------------------- /parpar/hasher/md5-final.h: -------------------------------------------------------------------------------- 1 | #ifndef __MD5_FINAL 2 | #define __MD5_FINAL 3 | 4 | #include "../src/hedley.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | #endif 9 | void md5_final_block(void* state, const void *HEDLEY_RESTRICT data, uint64_t totalLength, uint64_t zeroPad); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /parpar/hasher/md5-scalar-base.h: -------------------------------------------------------------------------------- 1 | #include // memcpy+memset 2 | #include "../src/stdint.h" 3 | #include "../src/platform.h" 4 | 5 | 6 | #define ADD(a, b) (a+b) 7 | #define VAL(k) (k) 8 | #define word_t uint32_t 9 | #define INPUT(k, set, ptr, offs, idx, var) (var + k) 10 | #define LOAD(k, set, ptr, offs, idx, var) (var = _LE32(read32(((char*)(ptr[set])) + offs + idx*4)), var + k) 11 | 12 | 13 | # if defined(_MSC_VER) 14 | # define ROTATE(a,n) _lrotl(a,n) 15 | # elif defined(__ICC) 16 | # define ROTATE(a,n) _rotl(a,n) 17 | # elif defined(__MWERKS__) 18 | # if defined(__POWERPC__) 19 | # define ROTATE(a,n) __rlwinm(a,n,0,31) 20 | # elif defined(__MC68K__) 21 | /* Motorola specific tweak. */ 22 | # define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) ) 23 | # else 24 | # define ROTATE(a,n) __rol(a,n) 25 | # endif 26 | # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) 27 | /* 28 | * Some GNU C inline assembler templates. Note that these are 29 | * rotates by *constant* number of bits! But that's exactly 30 | * what we need here... 31 | * 32 | */ 33 | # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) 34 | # define ROTATE(a,n) ({ unsigned int ret; \ 35 | __asm__ ( \ 36 | "roll %1,%0" \ 37 | : "=r"(ret) \ 38 | : "I"(n), "0"((unsigned int)(a)) \ 39 | : "cc"); \ 40 | ret; \ 41 | }) 42 | # elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ 43 | defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__) 44 | # define ROTATE(a,n) ({ unsigned int ret; \ 45 | __asm__ ( \ 46 | "rlwinm %0,%1,%2,0,31" \ 47 | : "=r"(ret) \ 48 | : "r"(a), "I"(n)); \ 49 | ret; \ 50 | }) 51 | # elif defined(__s390x__) 52 | # define ROTATE(a,n) ({ unsigned int ret; \ 53 | __asm__ ("rll %0,%1,%2" \ 54 | : "=r"(ret) \ 55 | : "r"(a), "I"(n)); \ 56 | ret; \ 57 | }) 58 | # endif 59 | # endif 60 | # ifndef ROTATE 61 | # define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) 62 | # endif 63 | 64 | 65 | 66 | #define F 1 67 | #define G 2 68 | #define H 3 69 | #define I 4 70 | // this is defined to allow a special sequence for the 'G' function - essentially, the usual bitwise OR can be replaced with an ADD, and re-ordering can be done to slightly defer the dependency on the 'b' input 71 | #define ADDF(f,a,b,c,d) ( \ 72 | f==G ? (((~d & c) + a) + (d & b)) : a + ( \ 73 | f==F ? (((c ^ d) & b) ^ d) : ( \ 74 | f==H ? ((d ^ c) ^ b) : \ 75 | ((~d | b) ^ c) \ 76 | ) \ 77 | ) \ 78 | ) 79 | 80 | -------------------------------------------------------------------------------- /parpar/hasher/md5-scalar.h: -------------------------------------------------------------------------------- 1 | 2 | #include // memcpy+memset 3 | #include "../src/platform.h" 4 | #include "../src/stdint.h" 5 | 6 | #if (defined(__GNUC__) || defined(__clang__)) && defined(PLATFORM_X86) && defined(__OPTIMIZE__) && (!defined(HEDLEY_GCC_VERSION) || !defined(HAS_UBSAN)) 7 | # define MD5_USE_ASM 8 | # ifdef PLATFORM_AMD64 9 | # define MD5_HAS_NOLEA 1 10 | # else 11 | # define md5_process_block_nolea md5_process_block_scalar 12 | # endif 13 | # include "md5-x86-asm.h" 14 | #else 15 | # define md5_process_block_nolea md5_process_block_scalar 16 | #endif 17 | #if (defined(__GNUC__) || defined(__clang__)) && defined(PLATFORM_ARM) && defined(__OPTIMIZE__) 18 | # ifdef __aarch64__ 19 | # define MD5_USE_ASM 20 | # include "md5-arm64-asm.h" 21 | # elif (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__) || (defined(__ARM_ARCH) && __ARM_ARCH >= 6) || defined(__armv7__) || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_8A__) || defined(_M_ARM) 22 | // require ARMv6 for big-endian support 23 | # define MD5_USE_ASM 24 | # include "md5-arm-asm.h" 25 | # endif 26 | #endif 27 | 28 | 29 | #include "md5-scalar-base.h" 30 | 31 | #define FNB(f) f##_scalar 32 | #include "md5-base.h" 33 | #undef FNB 34 | 35 | #ifdef MD5_USE_ASM 36 | # undef MD5_USE_ASM 37 | #endif 38 | -------------------------------------------------------------------------------- /parpar/hasher/md5mb-base.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "../src/stdint.h" 4 | 5 | #ifdef MD5X2 6 | # define FNB(f) _FN(f##_mb2) 7 | # define FN_REGIONS(d) _FN(md5mb_##d)*2 8 | #else 9 | # define FNB(f) _FN(f##_mb) 10 | # define FN_REGIONS(d) _FN(md5mb_##d) 11 | #endif 12 | 13 | #include "md5-base.h" 14 | 15 | 16 | static HEDLEY_ALWAYS_INLINE void FNB(md5_update_block)(void* state, const void* const* data, size_t offset) { 17 | FNB(md5_process_block)((word_t*)state, (const uint8_t* const*)data, offset); 18 | } 19 | 20 | static HEDLEY_ALWAYS_INLINE void FNB(md5_final_block)(void* state, const void *HEDLEY_RESTRICT const*HEDLEY_RESTRICT data, size_t offset, uint64_t totalLength) { 21 | ALIGN_TO(_FN(md5mb_alignment), uint8_t block[FN_REGIONS(max_regions)][64]); 22 | const uint8_t* blockPtr[FN_REGIONS(max_regions)]; 23 | size_t remaining = totalLength & 63; 24 | for(unsigned i=0; i bits 39 | 40 | for(unsigned i=0; i // memcpy+memset 2 | #include "../src/platform.h" 3 | #include "../src/stdint.h" 4 | 5 | #if (defined(__GNUC__) || defined(__clang__)) && defined(PLATFORM_AMD64) && defined(__OPTIMIZE__) 6 | # define MD5_USE_ASM 7 | # include "md5x2-x86-asm.h" 8 | #endif 9 | #if (defined(__GNUC__) || defined(__clang__)) && defined(PLATFORM_ARM) && defined(__OPTIMIZE__) \ 10 | && (defined(__aarch64__) || (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__) || (defined(__ARM_ARCH) && __ARM_ARCH >= 6) || defined(__armv7__) || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_8A__) || defined(_M_ARM)) 11 | // disable ASM on ARMv5 or older if big-endian 12 | # define MD5_USE_ASM 13 | # include "md5x2-arm-asm.h" 14 | #endif 15 | 16 | static HEDLEY_ALWAYS_INLINE void md5_init_lane_x2_scalar(void* state, const int idx) { 17 | uint32_t* state_ = (uint32_t*)state; 18 | state_[0 + idx*4] = 0x67452301L; 19 | state_[1 + idx*4] = 0xefcdab89L; 20 | state_[2 + idx*4] = 0x98badcfeL; 21 | state_[3 + idx*4] = 0x10325476L; 22 | } 23 | 24 | #include "md5-scalar-base.h" 25 | 26 | #define _FN(f) f##_scalar 27 | #define MD5X2 28 | 29 | #include "md5x2-base.h" 30 | 31 | #ifdef MD5X2 32 | # undef MD5X2 33 | #endif 34 | 35 | #undef _FN 36 | #undef ROTATE 37 | #undef ADD 38 | #undef VAL 39 | #undef word_t 40 | #undef INPUT 41 | #undef LOAD 42 | 43 | #undef F 44 | #undef G 45 | #undef H 46 | #undef I 47 | #undef ADDF 48 | 49 | #ifdef MD5_USE_ASM 50 | # undef MD5_USE_ASM 51 | #endif 52 | 53 | static HEDLEY_ALWAYS_INLINE void md5_extract_x2_scalar(void* dst, void* state, const int idx) { 54 | memcpy(dst, (uint32_t*)state + idx*4, 16); 55 | } 56 | -------------------------------------------------------------------------------- /parpar/src/platform_warnings.c: -------------------------------------------------------------------------------- 1 | // dummy compilation unit to display platform warnings 2 | #define PP_PLATFORM_SHOW_WARNINGS 3 | #include "platform.h" 4 | -------------------------------------------------------------------------------- /src/creatorpacket.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2003 Peter Brian Clements 5 | // 6 | // par2cmdline is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License as published by 8 | // the Free Software Foundation; either version 2 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // par2cmdline is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program; if not, write to the Free Software 18 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | #include "libpar2internal.h" 21 | 22 | #ifdef _MSC_VER 23 | #ifdef _DEBUG 24 | #undef THIS_FILE 25 | static char THIS_FILE[]=__FILE__; 26 | #define new DEBUG_NEW 27 | #endif 28 | #endif 29 | 30 | // Construct the creator packet. 31 | 32 | // The only external information required to complete construction is 33 | // the set_id_hash (which is normally computed from information in the 34 | // main packet). 35 | 36 | bool CreatorPacket::Create(const MD5Hash &setid) 37 | { 38 | string creator = "Created by " X_PACKAGE " version " X_VERSION "."; 39 | 40 | // Allocate a packet just large enough for creator name 41 | CREATORPACKET *packet = (CREATORPACKET *)AllocatePacket(sizeof(*packet) + (~3 & (3+(u32)creator.size()))); 42 | 43 | // Fill in the details the we know 44 | packet->header.magic = packet_magic; 45 | packet->header.length = packetlength; 46 | //packet->header.hash; // Compute shortly 47 | packet->header.setid = setid; 48 | packet->header.type = creatorpacket_type; 49 | 50 | // Copy the creator description into the packet 51 | memcpy(packet->client, creator.c_str(), creator.size()); 52 | 53 | // Compute the packet hash 54 | MD5Context packetcontext; 55 | packetcontext.Update(&packet->header.setid, packetlength - offsetof(PACKET_HEADER, setid)); 56 | packetcontext.Final(packet->header.hash); 57 | 58 | return true; 59 | } 60 | 61 | // Load the packet from disk. 62 | 63 | bool CreatorPacket::Load(DiskFile *diskfile, u64 offset, PACKET_HEADER &header) 64 | { 65 | // Is the packet long enough 66 | if (header.length <= sizeof(CREATORPACKET)) 67 | { 68 | return false; 69 | } 70 | 71 | // Is the packet too large (what is the longest reasonable creator description) 72 | if (header.length - sizeof(CREATORPACKET) > 100000) 73 | { 74 | return false; 75 | } 76 | 77 | // Allocate the packet (with a little extra so we will have NULLs after the description) 78 | CREATORPACKET *packet = (CREATORPACKET *)AllocatePacket((size_t)header.length, 4); 79 | packet->header = header; 80 | 81 | // Load the rest of the packet from disk 82 | return diskfile->Read(offset + sizeof(PACKET_HEADER), 83 | packet->client, 84 | (size_t)packet->header.length - sizeof(PACKET_HEADER)); 85 | } 86 | -------------------------------------------------------------------------------- /src/creatorpacket.h: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2003 Peter Brian Clements 5 | // 6 | // par2cmdline is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License as published by 8 | // the Free Software Foundation; either version 2 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // par2cmdline is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program; if not, write to the Free Software 18 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | #ifndef __CREATORPACKET_H__ 21 | #define __CREATORPACKET_H__ 22 | 23 | // The creator packet records details as to which PAR2 client 24 | // created a particular recovery file. 25 | 26 | // The PAR 2.0 specification requires the presence of a 27 | // creator packet, but it is not actually needed for the 28 | // verification or recovery of damaged files. 29 | 30 | class CreatorPacket : public CriticalPacket 31 | { 32 | public: 33 | // Construct the packet 34 | CreatorPacket(void) {}; 35 | ~CreatorPacket(void) {}; 36 | 37 | // Create a creator packet for a specified set id hash value 38 | bool Create(const MD5Hash &set_id_hash); 39 | 40 | // Load a creator packet from a specified file 41 | bool Load(DiskFile *diskfile, u64 offset, PACKET_HEADER &header); 42 | }; 43 | 44 | #endif // __CREATORPACKET_H__ 45 | -------------------------------------------------------------------------------- /src/foreach_parallel.h: -------------------------------------------------------------------------------- 1 | #ifndef __FOREACH_PARALLEL_H__ 2 | #define __FOREACH_PARALLEL_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | template 10 | void foreach_parallel(const vector &collection, u32 numThreads, const function &fn) 11 | { 12 | if (numThreads == 1 || collection.size() == 1) 13 | { 14 | for (const auto &item : collection) 15 | fn(item); 16 | } 17 | else if (numThreads >= collection.size()) 18 | { 19 | // spawn a thread for each item 20 | vector> tasks; 21 | tasks.reserve(collection.size()); 22 | for (const auto &item : collection) 23 | tasks.push_back(async(launch::async, bind(fn, ref(item)))); 24 | for (auto &task : tasks) 25 | task.wait(); 26 | } 27 | else 28 | { 29 | atomic itemPos(0); 30 | vector threads; 31 | threads.reserve(numThreads); 32 | for (unsigned thread = 0; thread < numThreads; thread++) 33 | { 34 | threads.emplace_back([&itemPos, &collection, &fn]() 35 | { 36 | while (1) 37 | { 38 | unsigned i = itemPos.fetch_add(1, memory_order_relaxed); 39 | if (i >= collection.size()) break; 40 | fn(collection.at(i)); 41 | } 42 | }); 43 | } 44 | for (auto &thread : threads) 45 | thread.join(); 46 | } 47 | } 48 | 49 | #endif // __FOREACH_PARALLEL_H__ 50 | -------------------------------------------------------------------------------- /src/galois.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2003 Peter Brian Clements 5 | // 6 | // par2cmdline is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License as published by 8 | // the Free Software Foundation; either version 2 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // par2cmdline is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program; if not, write to the Free Software 18 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | #include "libpar2internal.h" 21 | 22 | #ifdef _MSC_VER 23 | #ifdef _DEBUG 24 | #undef THIS_FILE 25 | static char THIS_FILE[]=__FILE__; 26 | #define new DEBUG_NEW 27 | #endif 28 | #endif 29 | -------------------------------------------------------------------------------- /src/hasher.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASHER_H__ 2 | #define __HASHER_H__ 3 | 4 | // Wrapper for ParPar's InputHasher 5 | 6 | #include "../parpar/hasher/hasher.h" 7 | inline u32 HasherGetBlock(IHasherInput* hasher, MD5Hash& blockhash, u64 zeropad = 0) 8 | { 9 | u8 md5crc[20]; 10 | hasher->getBlock(md5crc, zeropad); 11 | memcpy(blockhash.hash, md5crc, 16); 12 | return md5crc[16] | (md5crc[17] << 8) | (md5crc[18] << 16) | (md5crc[19] << 24); 13 | } 14 | 15 | #endif // __HASHER_H__ 16 | -------------------------------------------------------------------------------- /src/md5.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2003 Peter Brian Clements 5 | // Copyright (c) 2019 Michael D. Nahas 6 | // 7 | // par2cmdline is free software; you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation; either version 2 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // par2cmdline is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program; if not, write to the Free Software 19 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | #include "libpar2internal.h" 22 | 23 | #ifdef _MSC_VER 24 | #ifdef _DEBUG 25 | #undef THIS_FILE 26 | static char THIS_FILE[]=__FILE__; 27 | #define new DEBUG_NEW 28 | #endif 29 | #endif 30 | 31 | // Convert hash values to hex 32 | 33 | ostream& operator<<(ostream &result, const MD5Hash &h) 34 | { 35 | char buffer[33]; 36 | 37 | sprintf(buffer, 38 | "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 39 | h.hash[15], h.hash[14], h.hash[13], h.hash[12], 40 | h.hash[11], h.hash[10], h.hash[9], h.hash[8], 41 | h.hash[7], h.hash[6], h.hash[5], h.hash[4], 42 | h.hash[3], h.hash[2], h.hash[1], h.hash[0]); 43 | 44 | return result << buffer; 45 | } 46 | 47 | string MD5Hash::print(void) const 48 | { 49 | char buffer[33]; 50 | 51 | sprintf(buffer, 52 | "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 53 | hash[15], hash[14], hash[13], hash[12], 54 | hash[11], hash[10], hash[9], hash[8], 55 | hash[7], hash[6], hash[5], hash[4], 56 | hash[3], hash[2], hash[1], hash[0]); 57 | 58 | return buffer; 59 | } 60 | -------------------------------------------------------------------------------- /src/par1fileformat.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2003 Peter Brian Clements 5 | // 6 | // par2cmdline is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License as published by 8 | // the Free Software Foundation; either version 2 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // par2cmdline is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program; if not, write to the Free Software 18 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | #include "libpar2internal.h" 21 | 22 | PAR1MAGIC par1_magic = {{'P', 'A', 'R', '\0', '\0', '\0', '\0', '\0'}}; 23 | -------------------------------------------------------------------------------- /src/par1fileformat.h: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2003 Peter Brian Clements 5 | // Copyright (c) 2019 Michael D. Nahas 6 | // 7 | // par2cmdline is free software; you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation; either version 2 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // par2cmdline is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program; if not, write to the Free Software 19 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | #ifndef __PAR1FILEFORMAT_H__ 22 | #define __PAR1FILEFORMAT_H__ 23 | 24 | #ifdef _WIN32 25 | #pragma pack(push, 1) 26 | #define PACKED 27 | #else 28 | #define PACKED __attribute__ ((packed)) 29 | #endif 30 | 31 | #ifdef _MSC_VER 32 | #pragma warning(disable:4200) 33 | #endif 34 | 35 | struct PAR1MAGIC {u8 magic[8];}PACKED; 36 | 37 | struct PAR1FILEHEADER 38 | { 39 | PAR1MAGIC magic; 40 | leu32 fileversion; 41 | leu32 programversion; 42 | MD5Hash controlhash; 43 | MD5Hash sethash; 44 | leu64 volumenumber; 45 | leu64 numberoffiles; 46 | leu64 filelistoffset; 47 | leu64 filelistsize; 48 | leu64 dataoffset; 49 | leu64 datasize; 50 | }PACKED; 51 | 52 | struct PAR1FILEENTRY 53 | { 54 | leu64 entrysize; 55 | leu64 status; 56 | leu64 filesize; 57 | MD5Hash hashfull; 58 | MD5Hash hash16k; 59 | leu16 name[]; 60 | }PACKED; 61 | 62 | enum FILEENTRYSTATUS 63 | { 64 | INPARITYVOLUME = 1, 65 | CHECKED = 2, 66 | }; 67 | 68 | #ifdef _MSC_VER 69 | #pragma warning(default:4200) 70 | #endif 71 | 72 | #ifdef _WIN32 73 | #pragma pack(pop) 74 | #endif 75 | #undef PACKED 76 | 77 | // Operators for comparing the MAGIC values 78 | 79 | inline bool operator == (const PAR1MAGIC &left, const PAR1MAGIC &right) 80 | { 81 | return (0==memcmp(&left, &right, sizeof(left))); 82 | } 83 | 84 | inline bool operator != (const PAR1MAGIC &left, const PAR1MAGIC &right) 85 | { 86 | return !operator==(left, right); 87 | } 88 | 89 | extern PAR1MAGIC par1_magic; 90 | 91 | #endif //__PAR1FILEFORMAT_H__ 92 | -------------------------------------------------------------------------------- /src/par1repairersourcefile.h: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2003 Peter Brian Clements 5 | // Copyright (c) 2019 Michael D. Nahas 6 | // 7 | // par2cmdline is free software; you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation; either version 2 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // par2cmdline is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program; if not, write to the Free Software 19 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | #ifndef __PAR1REPAIRERSOURCEFILE_H__ 22 | #define __PAR1REPAIRERSOURCEFILE_H__ 23 | 24 | // The Par1RepairerSourceFile object is used during verification and repair 25 | // to record details about a particular source file and the data blocks 26 | // for that file. 27 | 28 | class Par1RepairerSourceFile 29 | { 30 | public: 31 | // Construct the object and set the description and verification packets 32 | Par1RepairerSourceFile(std::ostream &sout, 33 | std::ostream &serr, 34 | const NoiseLevel noiselevel, 35 | PAR1FILEENTRY *fileentry, 36 | const string &searchpath); 37 | ~Par1RepairerSourceFile(void); 38 | 39 | string FileName(void) const {return filename;} 40 | u64 FileSize(void) const {return filesize;} 41 | const MD5Hash& HashFull(void) const {return hashfull;} 42 | const MD5Hash& Hash16k(void) const {return hash16k;} 43 | 44 | // Set/Get which DiskFile will contain the final repaired version of the file 45 | void SetTargetFile(DiskFile *diskfile); 46 | DiskFile* GetTargetFile(void) const; 47 | 48 | // Set/Get whether or not the target file actually exists 49 | void SetTargetExists(bool exists); 50 | bool GetTargetExists(void) const; 51 | 52 | // Set/Get which DiskFile contains a full undamaged version of the source file 53 | void SetCompleteFile(DiskFile *diskfile); 54 | DiskFile* GetCompleteFile(void) const; 55 | 56 | void SetTargetBlock(DiskFile *diskfile); 57 | 58 | DataBlock* SourceBlock(void) {return &sourceblock;} 59 | DataBlock* TargetBlock(void) {return &targetblock;} 60 | 61 | 62 | protected: 63 | string filename; 64 | u64 filesize; 65 | MD5Hash hashfull; 66 | MD5Hash hash16k; 67 | 68 | DataBlock sourceblock; 69 | DataBlock targetblock; 70 | 71 | bool targetexists; // Whether the target file exists 72 | DiskFile *targetfile; // The final version of the file 73 | DiskFile *completefile; // A complete version of the file 74 | 75 | 76 | }; 77 | 78 | 79 | #endif // __PAR1REPAIRERSOURCEFILE_H__ 80 | -------------------------------------------------------------------------------- /src/par2fileformat.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2003 Peter Brian Clements 5 | // 6 | // par2cmdline is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License as published by 8 | // the Free Software Foundation; either version 2 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // par2cmdline is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program; if not, write to the Free Software 18 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | #include "libpar2internal.h" 21 | 22 | MAGIC packet_magic = {{'P', 'A', 'R', '2', '\0','P', 'K', 'T'}}; 23 | PACKETTYPE fileverificationpacket_type = {{'P', 'A', 'R', ' ', '2', '.', '0', '\0', 'I', 'F', 'S', 'C', '\0','\0','\0','\0'}}; 24 | PACKETTYPE filedescriptionpacket_type = {{'P', 'A', 'R', ' ', '2', '.', '0', '\0', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c' }}; 25 | PACKETTYPE mainpacket_type = {{'P', 'A', 'R', ' ', '2', '.', '0', '\0', 'M', 'a', 'i', 'n', '\0','\0','\0','\0'}}; 26 | PACKETTYPE recoveryblockpacket_type = {{'P', 'A', 'R', ' ', '2', '.', '0', '\0', 'R', 'e', 'c', 'v', 'S', 'l', 'i', 'c' }}; 27 | PACKETTYPE creatorpacket_type = {{'P', 'A', 'R', ' ', '2', '.', '0', '\0', 'C', 'r', 'e', 'a', 't', 'o', 'r', '\0'}}; 28 | -------------------------------------------------------------------------------- /src/utf8.h: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See https://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2024-2025 Denis 5 | // 6 | // par2cmdline is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License as published by 8 | // the Free Software Foundation; either version 2 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // par2cmdline is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program; if not, write to the Free Software 18 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | #ifndef __UTF8_H__ 21 | #define __UTF8_H__ 22 | 23 | #include 24 | #include 25 | 26 | namespace utf8 27 | { 28 | extern const int MAX_ARGS; 29 | extern const size_t MAX_DIR_PATH; 30 | extern std::wstring_convert> UTF8_CONVERTER; 31 | 32 | std::wstring Utf8ToWide(const std::string& str); 33 | std::string WideToUtf8(const std::wstring& str); 34 | 35 | class WideToUtf8ArgsAdapter final 36 | { 37 | public: 38 | WideToUtf8ArgsAdapter(int argc, wchar_t* argv_[]) noexcept(false); 39 | 40 | const char* const* GetUtf8Args() const noexcept; 41 | 42 | WideToUtf8ArgsAdapter() = delete; 43 | WideToUtf8ArgsAdapter(const WideToUtf8ArgsAdapter&) = delete; 44 | WideToUtf8ArgsAdapter(WideToUtf8ArgsAdapter&&) = delete; 45 | WideToUtf8ArgsAdapter& operator=(const WideToUtf8ArgsAdapter&) = delete; 46 | WideToUtf8ArgsAdapter& operator=(WideToUtf8ArgsAdapter&&) = delete; 47 | 48 | ~WideToUtf8ArgsAdapter(); 49 | 50 | private: 51 | char** m_argv; 52 | int m_argc; 53 | }; 54 | } 55 | 56 | #endif // __UTF8_H__ 57 | -------------------------------------------------------------------------------- /src/verificationpacket.h: -------------------------------------------------------------------------------- 1 | // This file is part of par2cmdline (a PAR 2.0 compatible file verification and 2 | // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0. 3 | // 4 | // Copyright (c) 2003 Peter Brian Clements 5 | // Copyright (c) 2019 Michael D. Nahas 6 | // 7 | // par2cmdline is free software; you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation; either version 2 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // par2cmdline is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program; if not, write to the Free Software 19 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | #ifndef __VERIFICATIONPACKET_H__ 22 | #define __VERIFICATIONPACKET_H__ 23 | 24 | // The file verification packet stores details that allow individual blocks 25 | // of valid data within a damaged file to be identified. 26 | 27 | class VerificationPacket : public CriticalPacket 28 | { 29 | public: 30 | // Construct the packet 31 | VerificationPacket(void) 32 | : blockcount(0) 33 | { 34 | } 35 | ~VerificationPacket(void) {} 36 | 37 | // Create a packet large enough for the specified number of blocks 38 | bool Create(u32 blockcount); 39 | 40 | // Set the fileid (computed from the file description packet). 41 | void FileId(const MD5Hash &fileid); 42 | 43 | // Set the block hash and block crc for a specific data block. 44 | void SetBlockHashAndCRC(u32 blocknumber, const MD5Hash &hash, u32 crc); 45 | 46 | // Load a verification packet from a specified file 47 | bool Load(DiskFile *diskfile, u64 offset, PACKET_HEADER &header); 48 | 49 | // Get the FileId 50 | const MD5Hash& FileId(void) const; 51 | 52 | // Get the block count 53 | u32 BlockCount(void) const; 54 | 55 | // Get a specific verification entry 56 | const FILEVERIFICATIONENTRY* VerificationEntry(u32 blocknumber) const; 57 | 58 | protected: 59 | u32 blockcount; 60 | }; 61 | 62 | inline const MD5Hash& VerificationPacket::FileId(void) const 63 | { 64 | assert(packetdata != 0); 65 | 66 | return ((FILEVERIFICATIONPACKET*)packetdata)->fileid; 67 | } 68 | 69 | inline u32 VerificationPacket::BlockCount(void) const 70 | { 71 | assert(packetdata != 0); 72 | 73 | return blockcount; 74 | } 75 | 76 | inline const FILEVERIFICATIONENTRY* VerificationPacket::VerificationEntry(u32 blocknumber) const 77 | { 78 | assert(packetdata != 0); 79 | 80 | // return &((FILEVERIFICATIONPACKET*)packetdata)->entries()[blocknumber]; 81 | return &((FILEVERIFICATIONPACKET*)packetdata)->entries[blocknumber]; 82 | } 83 | 84 | 85 | #endif // __VERIFICATIONPACKET_H__ 86 | -------------------------------------------------------------------------------- /stamp-h.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/stamp-h.in -------------------------------------------------------------------------------- /tests/100blocks.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/100blocks.tar.gz -------------------------------------------------------------------------------- /tests/bug128-parfiles.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/bug128-parfiles.tar.gz -------------------------------------------------------------------------------- /tests/bug190.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/bug190.tar.gz -------------------------------------------------------------------------------- /tests/bug44.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/bug44.tar.gz -------------------------------------------------------------------------------- /tests/flatdata-par1files.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/flatdata-par1files.tar.gz -------------------------------------------------------------------------------- /tests/flatdata-par2files.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/flatdata-par2files.tar.gz -------------------------------------------------------------------------------- /tests/flatdata.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/flatdata.tar.gz -------------------------------------------------------------------------------- /tests/par2-0.6.8-crash.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/par2-0.6.8-crash.tar.gz -------------------------------------------------------------------------------- /tests/readbeyondeof.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/readbeyondeof.tar.gz -------------------------------------------------------------------------------- /tests/smallsubdirdata-par2files.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/smallsubdirdata-par2files.tar.gz -------------------------------------------------------------------------------- /tests/smallsubdirdata.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/smallsubdirdata.tar.gz -------------------------------------------------------------------------------- /tests/subdirdata-par2files-unix.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/subdirdata-par2files-unix.tar.gz -------------------------------------------------------------------------------- /tests/subdirdata-par2files-win.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/subdirdata-par2files-win.tar.gz -------------------------------------------------------------------------------- /tests/subdirdata.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/subdirdata.tar.gz -------------------------------------------------------------------------------- /tests/test1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" 2>&1 || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | tar -xzf "$TESTDATA/flatdata-par1files.tar.gz" 2>&1 || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 36 | 37 | banner="Verifying using PAR 1.0 data" 38 | dashes=`echo "$banner" | sed s/./-/g` 39 | 40 | echo $dashes 41 | echo $banner 42 | echo $dashes 43 | 44 | $PARBINARY v testdata.par || { echo "ERROR: Initial PAR 1.0 verification failed" ; exit 1; } >&2 45 | 46 | cd "$TESTROOT" 47 | rm -rf "run$testname" 48 | 49 | exit 0 50 | -------------------------------------------------------------------------------- /tests/test10: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/smallsubdirdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | tar -xzf "$TESTDATA/smallsubdirdata-par2files.tar.gz" || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 36 | 37 | banner="Repairing deleted subdir using PAR 2.0 data" 38 | dashes=`echo "$banner" | sed s/./-/g` 39 | 40 | echo $dashes 41 | echo $banner 42 | echo $dashes 43 | 44 | cp subdir1/test-0.data ./test-0.data.orig 45 | rm -rf subdir1 46 | 47 | $PARBINARY r testdata.par2 || { echo "ERROR: Reconstruction of two files using PAR 2.0 failed" ; exit 1; } >&2 48 | cmp -s subdir1/test-0.data test-0.data.orig || { echo "ERROR: Repaired files do not match originals" ; exit 1; } >&2 49 | 50 | cd "$TESTROOT" 51 | rm -rf "run$testname" 52 | 53 | exit 0 54 | -------------------------------------------------------------------------------- /tests/test11: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/100blocks.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="create par2files using 100 blocks" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | $PARBINARY c -b100 testdata.par2 * || { echo "ERROR: construction of files using PAR 2.0 failed" ; exit 1; } >&2 44 | 45 | banner="repair 5% of 100 blocks par2files removing 3 files" 46 | dashes=`echo "$banner" | sed s/./-/g` 47 | 48 | echo $dashes 49 | echo $banner 50 | echo $dashes 51 | 52 | rm file file1 file3 53 | 54 | $PARBINARY r testdata.par2 * || { echo "ERROR: construction of files using PAR 2.0 failed" ; exit 1; } >&2 55 | 56 | banner="repair 5% of 100 blocks par2files removing 1 files" 57 | dashes=`echo "$banner" | sed s/./-/g` 58 | 59 | echo $dashes 60 | echo $banner 61 | echo $dashes 62 | 63 | rm file5 64 | 65 | $PARBINARY r testdata.par2 * || { echo "ERROR: construction of files using PAR 2.0 failed" ; exit 1; } >&2 66 | 67 | cd "$TESTROOT" 68 | rm -rf "run$testname" 69 | 70 | exit 0 71 | -------------------------------------------------------------------------------- /tests/test12: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/readbeyondeof.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="repair files where the filesize got changed" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | mv test.data test.data-correct 44 | dd if=test.data-correct bs=113579 count=1 of=test.data 45 | 46 | $PARBINARY r test.par2 || { echo "ERROR: repair files using PAR 2.0 failed" ; exit 1; } >&2 47 | 48 | cd "$TESTROOT" 49 | rm -rf "run$testname" 50 | 51 | exit 0 52 | -------------------------------------------------------------------------------- /tests/test13: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="create 5% recovery files" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | $PARBINARY c testdata.par2 *.data || { echo "ERROR: creating repair files using PAR 2.0 failed" ; exit 1; } >&2 44 | 45 | banner="repair files where 1 byte got removed at the end of a file" 46 | dashes=`echo "$banner" | sed s/./-/g` 47 | 48 | echo $dashes 49 | echo $banner 50 | echo $dashes 51 | 52 | mv test-1.data test-1.data-correct 53 | dd if=test-1.data-correct bs=177173 count=1 of=test-1.data 54 | 55 | $PARBINARY r testdata.par2 || { echo "ERROR: repair files using PAR 2.0 failed" ; exit 1; } >&2 56 | 57 | cd "$TESTROOT" 58 | rm -rf "run$testname" 59 | 60 | exit 0 61 | -------------------------------------------------------------------------------- /tests/test14: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="create 5% recovery files" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | $PARBINARY c testdata.par2 *.data || { echo "ERROR: creating repair files using PAR 2.0 failed" ; exit 1; } >&2 44 | 45 | banner="repair files where 1 byte got removed at the beginning of a file" 46 | dashes=`echo "$banner" | sed s/./-/g` 47 | 48 | echo $dashes 49 | echo $banner 50 | echo $dashes 51 | 52 | mv test-1.data test-1.data-correct 53 | tail -c 177173 test-1.data-correct > test-1.data 54 | 55 | $PARBINARY r testdata.par2 || { echo "ERROR: repair files using PAR 2.0 failed" ; exit 1; } >&2 56 | 57 | cd "$TESTROOT" 58 | rm -rf "run$testname" 59 | 60 | exit 0 61 | -------------------------------------------------------------------------------- /tests/test15: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/par2-0.6.8-crash.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="repair files should succeed, (issue #35)" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | cd par2-0.6.8-crash 44 | $PARBINARY r pack-ea5f7f848340980493ed39f5b7173d956c680e43.par2 || { echo "ERROR: repair files using PAR 2.0 failed" ; exit 1; } >&2 45 | 46 | cd "$TESTROOT" 47 | rm -rf "run$testname" 48 | 49 | exit 0 50 | -------------------------------------------------------------------------------- /tests/test16: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ###### 4 | # This test was 'wrong', it should test if there are data files outside the 5 | # basepath 6 | ###### 7 | 8 | execdir="$PWD" 9 | 10 | # valgrind tests memory usage. 11 | # wine allow for windows testing on linux 12 | if [ -n "${PARVALGRINDOPTS+set}" ] 13 | then 14 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 15 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 16 | then 17 | PARBINARY="wine $execdir/par2.exe" 18 | else 19 | PARBINARY="$execdir/par2" 20 | fi 21 | 22 | 23 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 24 | srcdir="$PWD" 25 | TESTDATA="$srcdir/tests" 26 | else 27 | srcdir="$PWD/$srcdir" 28 | TESTDATA="$srcdir/tests" 29 | fi 30 | 31 | TESTROOT="$PWD" 32 | 33 | testname=$(basename $0) 34 | rm -f "$testname.log" 35 | rm -rf "run$testname" 36 | 37 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 38 | 39 | tar -xzf "$TESTDATA/subdirdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 40 | 41 | banner="don't allow files outside par2 basedir, (issue #34, #36)" 42 | dashes=`echo "$banner" | sed s/./-/g` 43 | 44 | echo $dashes 45 | echo $banner 46 | echo $dashes 47 | 48 | cd subdir1 49 | 50 | $PARBINARY c -r2 test.par2 *.data ../subdir2/*.data > $testname.log || { echo "ERROR: creating files using PAR 2.0 failed" ; exit 1; } >&2 51 | 52 | # check if there were ignored files 53 | grep 'Ignoring' "$testname.log" || { echo "ERROR: there were no files ignored"; exit 1; } >&2 54 | 55 | rm "$testname.log" 56 | 57 | cd "$TESTROOT" 58 | rm -rf "run$testname" 59 | 60 | exit 0 61 | -------------------------------------------------------------------------------- /tests/test17: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/bug44.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="remove subdir structure and repair, see #44" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | rm -rf subdir1 40 | 41 | echo $dashes 42 | echo $banner 43 | echo $dashes 44 | 45 | $PARBINARY r recovery.par2 || { echo "ERROR: reparation of files using PAR 2.0 failed" ; exit 1; } >&2 46 | 47 | cd "$TESTROOT" 48 | rm -rf "run$testname" 49 | 50 | exit 0 51 | -------------------------------------------------------------------------------- /tests/test18: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | cp "$TESTDATA/flatdata.tar.gz" ./ || { echo "ERROR: Could not copy data test files" ; exit 1; } >&2 35 | 36 | banner="Creating PAR 2.0 recovery data" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | $PARBINARY c recovery flatdata.tar.gz || { echo "ERROR: Creating PAR 2.0 data failed" ; exit 1; } >&2 44 | 45 | banner="Verifying using PAR 2.0 data" 46 | dashes=`echo "$banner" | sed s/./-/g` 47 | 48 | echo $dashes 49 | echo $banner 50 | echo $dashes 51 | 52 | mv flatdata.tar.gz flatdata.tar.gz-orig 53 | dd if=flatdata.tar.gz-orig bs=1983 count=1 of=flatdata.tar.gz 54 | rm -f flatdata.tar.gz-orig 55 | 56 | $PARBINARY r recovery.par2 ./* || { echo "ERROR: PAR 2.0 repair failed" ; exit 1; } >&2 57 | 58 | cd "$TESTROOT" 59 | rm -rf "run$testname" 60 | 61 | exit 0 62 | -------------------------------------------------------------------------------- /tests/test19: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | banner="Creating 1024 byte test data file" 35 | dashes=`echo "$banner" | sed s/./-/g` 36 | 37 | echo $dashes 38 | echo $banner 39 | echo $dashes 40 | 41 | dd if=/dev/urandom of=datafile bs=1024 count=1 || { echo "ERROR: Unable to create test data file" ; exit 1; } >&2 42 | ls -l 43 | 44 | banner="Creating PAR 2.0 recovery data (block size 200)" 45 | dashes=`echo "$banner" | sed s/./-/g` 46 | 47 | echo $dashes 48 | echo $banner 49 | echo $dashes 50 | 51 | $PARBINARY c -s200 -c1 recovery datafile || { echo "ERROR: Creating PAR 2.0 data failed" ; exit 1; } >&2 52 | ls -l 53 | 54 | banner="Damaging data file (trim first 100 bytes)" 55 | dashes=`echo "$banner" | sed s/./-/g` 56 | 57 | echo $dashes 58 | echo $banner 59 | echo $dashes 60 | 61 | mv datafile datafile.orig 62 | dd if=datafile.orig of=datafile bs=100 skip=1 || { echo "ERROR: Unable to create damaged data file" ; exit 1; } >&2 63 | rm datafile.orig 64 | ls -l 65 | 66 | banner="Repairing using PAR 2.0 data (with skip leaway 99 - should fail)" 67 | dashes=`echo "$banner" | sed s/./-/g` 68 | 69 | echo $dashes 70 | echo $banner 71 | echo $dashes 72 | 73 | $PARBINARY r -N -S99 -vv recovery.par2 && { echo "ERROR: Repair should not be possible with skip leaway set to 99" ; exit 1; } >&2 74 | ls -l 75 | 76 | banner="Repairing using PAR 2.0 data (with skip leaway 100 - should succeed)" 77 | dashes=`echo "$banner" | sed s/./-/g` 78 | 79 | echo $dashes 80 | echo $banner 81 | echo $dashes 82 | 83 | $PARBINARY r -N -S100 -vv recovery.par2 || { echo "ERROR: Repair should be possible with skip leaway set to 100" ; exit 1; } >&2 84 | ls -l 85 | 86 | cd "$TESTROOT" 87 | rm -rf "run$testname" 88 | 89 | exit 0 90 | -------------------------------------------------------------------------------- /tests/test2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | tar -xzf "$TESTDATA/flatdata-par2files.tar.gz" || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 36 | 37 | banner="Verifying using PAR 2.0 data" 38 | dashes=`echo "$banner" | sed s/./-/g` 39 | 40 | echo $dashes 41 | echo $banner 42 | echo $dashes 43 | 44 | $PARBINARY v testdata.par2 || { echo "ERROR: Initial PAR 2.0 verification failed" ; exit 1; } >&2 45 | 46 | cd "$TESTROOT" 47 | rm -rf "run$testname" 48 | 49 | exit 0 50 | -------------------------------------------------------------------------------- /tests/test20: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | banner="generate datafile with 2000 random bytes" 35 | dashes=`echo "$banner" | sed s/./-/g` 36 | 37 | echo $dashes 38 | echo $banner 39 | echo $dashes 40 | 41 | dd bs=1000 count=2 if=/dev/urandom of=myfile.dat 42 | 43 | banner="Creating PAR 2.0 recovery data" 44 | dashes=`echo "$banner" | sed s/./-/g` 45 | 46 | echo $dashes 47 | echo $banner 48 | echo $dashes 49 | 50 | $PARBINARY c -s1000 -c0 recovery myfile.dat || { echo "ERROR: Creating PAR 2.0 data failed" ; exit 1; } >&2 51 | 52 | banner="split files" 53 | dashes=`echo "$banner" | sed s/./-/g` 54 | 55 | echo $dashes 56 | echo $banner 57 | echo $dashes 58 | 59 | dd bs=1000 count=1 if=myfile.dat of=myfile.dat.001 60 | dd bs=1000 count=1 skip=1 if=myfile.dat of=myfile.dat.002 61 | 62 | rm myfile.dat 63 | 64 | banner="Repairing using PAR 2.0 data" 65 | dashes=`echo "$banner" | sed s/./-/g` 66 | 67 | echo $dashes 68 | echo $banner 69 | echo $dashes 70 | 71 | $PARBINARY r recovery.par2 ./* || { echo "ERROR: PAR 2.0 repair failed" ; exit 1; } >&2 72 | 73 | cd "$TESTROOT" 74 | rm -rf "run$testname" 75 | 76 | exit 0 77 | -------------------------------------------------------------------------------- /tests/test21: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | banner="save parfiles outside of basedirectory" 35 | dashes=`echo "$banner" | sed s/./-/g` 36 | 37 | echo $dashes 38 | echo $banner 39 | echo $dashes 40 | 41 | mkdir parfiles 42 | mkdir datafiles 43 | 44 | banner="Creating PAR 2.0 recovery data" 45 | dashes=`echo "$banner" | sed s/./-/g` 46 | 47 | echo $dashes 48 | echo $banner 49 | echo $dashes 50 | 51 | cd datafiles 52 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 53 | 54 | $PARBINARY c -B ./ ../parfiles/recovery * || { echo "ERROR: Creating PAR 2.0 data failed" ; exit 1; } >&2 55 | 56 | banner="Verifying PAR 2.0 recovery data" 57 | dashes=`echo "$banner" | sed s/./-/g` 58 | 59 | echo $dashes 60 | echo $banner 61 | echo $dashes 62 | 63 | $PARBINARY v -B ./ ../parfiles/recovery.par2 || { echo "ERROR: Verifying PAR 2.0 data failed" ; exit 1; } >&2 64 | 65 | cd "$TESTROOT" 66 | rm -rf "run$testname" 67 | 68 | exit 0 69 | -------------------------------------------------------------------------------- /tests/test22: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | faraway="$TESTROOT/run$testname/in/a/folder/far/far/away" 35 | 36 | mkdir -p "$faraway" || { echo "ERROR: Could not create fancy folder" ; exit 1; } >&2 37 | mkdir rundir 38 | 39 | tar -xzf "$TESTDATA/flatdata.tar.gz" -C "$faraway" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 40 | 41 | banner="par2 can be run from any starting dir" 42 | dashes=`echo "$banner" | sed s/./-/g` 43 | 44 | echo $dashes 45 | echo $banner 46 | echo $dashes 47 | 48 | cd rundir 49 | 50 | $PARBINARY c -r2 -B"$faraway" "$faraway"/test.par2 "$faraway"/*.data || { echo "ERROR: create of PAR 2.0 files failed" ; exit 1; } >&2 51 | 52 | cd "$TESTROOT" 53 | rm -rf "run$testname" 54 | 55 | exit 0 56 | -------------------------------------------------------------------------------- /tests/test23: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | faraway="$TESTROOT/run$testname/in/a/folder/far/far/away" 35 | 36 | mkdir -p "$faraway" || { echo "ERROR: Could not create fancy folder" ; exit 1; } >&2 37 | mkdir rundir 38 | 39 | tar -xzf "$TESTDATA/flatdata.tar.gz" -C "$faraway" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 40 | tar -xzf "$TESTDATA/flatdata-par2files.tar.gz" -C "$faraway" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 41 | 42 | banner="par2 can be run from any starting dir" 43 | dashes=`echo "$banner" | sed s/./-/g` 44 | 45 | echo $dashes 46 | echo $banner 47 | echo $dashes 48 | 49 | cd rundir 50 | 51 | $PARBINARY v -B "$faraway" "$faraway"/testdata.par2 || { echo "ERROR: verify of PAR 2.0 files failed" ; exit 1; } >&2 52 | 53 | cd "$TESTROOT" 54 | rm -rf "run$testname" 55 | 56 | exit 0 57 | -------------------------------------------------------------------------------- /tests/test24: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | faraway="$TESTROOT/run$testname/in/a/folder/far/far/away" 35 | 36 | mkdir -p "$faraway" || { echo "ERROR: Could not create fancy folder" ; exit 1; } >&2 37 | mkdir rundir 38 | 39 | tar -xzf "$TESTDATA/flatdata.tar.gz" -C "$faraway" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 40 | tar -xzf "$TESTDATA/flatdata-par2files.tar.gz" -C "$faraway" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 41 | 42 | cp "$faraway"/test-0.data "$faraway"/test-0.data.orig 43 | cp "$faraway"/test-1.data "$faraway"/test-1.data.orig 44 | cp "$faraway"/test-2.data "$faraway"/test-2.data.orig 45 | cp "$faraway"/test-3.data "$faraway"/test-3.data.orig 46 | cp "$faraway"/test-4.data "$faraway"/test-4.data.orig 47 | cp "$faraway"/test-5.data "$faraway"/test-5.data.orig 48 | cp "$faraway"/test-6.data "$faraway"/test-6.data.orig 49 | cp "$faraway"/test-7.data "$faraway"/test-7.data.orig 50 | cp "$faraway"/test-8.data "$faraway"/test-8.data.orig 51 | cp "$faraway"/test-9.data "$faraway"/test-9.data.orig 52 | 53 | banner="par2 can be run from any starting dir" 54 | dashes=`echo "$banner" | sed s/./-/g` 55 | 56 | echo $dashes 57 | echo $banner 58 | echo $dashes 59 | 60 | cd rundir 61 | 62 | rm -f "$faraway"/test-1.data "$faraway"/test-3.data 63 | $PARBINARY r -B"$faraway" "$faraway"/testdata.par2 || { echo "ERROR: repair of PAR 2.0 files failed" ; exit 1; } >&2 64 | cmp -s "$faraway"/test-1.data "$faraway"/test-1.data.orig && cmp -s "$faraway"/test-3.data "$faraway"/test-3.data.orig || { echo "ERROR: Repaired files do not match originals" ; exit 1; } >&2 65 | 66 | cd "$TESTROOT" 67 | rm -rf "run$testname" 68 | 69 | exit 0 70 | -------------------------------------------------------------------------------- /tests/test25: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | banner="par2 with full path" 35 | dashes=`echo "$banner" | sed s/./-/g` 36 | 37 | echo $dashes 38 | echo $banner 39 | echo $dashes 40 | 41 | echo "file contents" > some-file 42 | $PARBINARY create "$(pwd)"/some-file || { echo "ERROR: Failed to create parchive"; exit1; } >&2 43 | echo "corrupted contents" > some-file 44 | $PARBINARY repair some-file || { echo "ERROR: Failed to repair"; exit 1; } >&2 45 | 46 | cd "$TESTROOT" 47 | rm -rf "run$testname" 48 | 49 | exit 0 50 | -------------------------------------------------------------------------------- /tests/test26: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | banner="par2 with full path and creation and repair in subfolder" 35 | dashes=`echo "$banner" | sed s/./-/g` 36 | 37 | echo $dashes 38 | echo $banner 39 | echo $dashes 40 | 41 | mkdir subfolder 42 | 43 | echo "file contents" > subfolder/some-file 44 | $PARBINARY create "$(pwd)"/subfolder/some-file || { echo "ERROR: Failed to create parchive"; exit1; } >&2 45 | echo "corrupted contents" > subfolder/some-file 46 | $PARBINARY repair subfolder/some-file || { echo "ERROR: Failed to repair"; exit 1; } >&2 47 | 48 | cd "$TESTROOT" 49 | rm -rf "run$testname" 50 | 51 | exit 0 52 | -------------------------------------------------------------------------------- /tests/test27: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | banner="par2 with full path" 35 | dashes=`echo "$banner" | sed s/./-/g` 36 | 37 | echo $dashes 38 | echo $banner 39 | echo $dashes 40 | 41 | mkdir -p folder/subfolder 42 | ln -s folder/subfolder tmp 43 | 44 | cd tmp 45 | 46 | echo "file contents" > some-file 47 | $PARBINARY create "$(pwd)"/some-file || { echo "ERROR: Failed to create parchive"; exit1; } >&2 48 | echo "corrupted contents" > some-file 49 | $PARBINARY repair some-file || { echo "ERROR: Failed to repair"; exit 1; } >&2 50 | 51 | cd "$TESTROOT" 52 | rm -rf "run$testname" 53 | 54 | exit 0 55 | -------------------------------------------------------------------------------- /tests/test28: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="Ensuring silent noise level" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | $PARBINARY c -a newtest -qq test-*.data >stdout || { echo "ERROR: create failed" ; exit 1; } >&2 44 | test ! -s stdout || { echo "ERROR: create with -qq produced output to stdout" ; exit 1; } >&2 45 | $PARBINARY v -qq newtest test-*.data >stdout || { echo "ERROR: verify failed" ; exit 1; } >&2 46 | test ! -s stdout || { echo "ERROR: verify with -qq produced output to stdout" ; exit 1; } >&2 47 | $PARBINARY r -qq newtest test-*.data >stdout || { echo "ERROR: repair failed" ; exit 1; } >&2 48 | test ! -s stdout || { echo "ERROR: repair with -qq produced output to stdout" ; exit 1; } >&2 49 | 50 | $PARBINARY c -a newtest -qq test-*.data >stdout 2>stderr && { echo "ERROR: second create succeeded but shouldn't have" ; exit 1; } >&2 51 | test ! -s stdout || { echo "ERROR: second create with -qq produced output to stdout" ; exit 1; } >&2 52 | test -s stderr || { echo "ERROR: second create with -qq did not produce output to stderr" ; exit 1; } >&2 53 | 54 | cd "$TESTROOT" 55 | rm -rf "run$testname" 56 | 57 | exit 0 58 | -------------------------------------------------------------------------------- /tests/test29: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/bug190.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="Issue 190, 1 bitflip can't be repaired" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | ##### TESTDATA generated with: 44 | # # fill with zeros 45 | # dd if=/dev/zero bs=1MB count=9 | tr '\000' '\377' > ./9MBones_crc_ok_bad 46 | # # replace one bit 47 | # printf "\xFF" | dd of=9MBones_crc_ok_bad bs=1 seek=20000 count=1 conv=notrunc 48 | # # store original 49 | # cp 9MBones_crc_ok_bad 9MBones_crc_ok_orig 50 | # # replace 1 bit (1->0) 51 | # printf "\xFE" | dd of="9MBones_crc_ok_bad" bs=1 seek=20000 count=1 conv=notrunc 52 | ##### END TESTDATA 53 | 54 | # generate par2 from orig good file, copy that first 55 | cp 9MBones_crc_ok_orig 9MBones_crc_ok || { echo "ERROR: good copy failed" ; exit 1; } >&2 56 | # Create PAR2 files 57 | $PARBINARY c -m500 -r30 -n1 -v '9MBones_crc_ok' || { echo "ERROR: create failed" ; exit 1; } >&2 58 | 59 | # replace with bitflipped bad copy 60 | cp 9MBones_crc_ok_bad 9MBones_crc_ok || { echo "ERROR: bad copy failed" ; exit 1; } >&2 61 | # Repair bitflip 62 | $PARBINARY repair '9MBones_crc_ok.par2' || { echo "ERROR: bitflip repair failed" ; exit 1; } >&2 63 | 64 | cd "$TESTROOT" 65 | rm -rf "run$testname" 66 | 67 | exit 0 68 | -------------------------------------------------------------------------------- /tests/test3: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | tar -xzf "$TESTDATA/flatdata-par1files.tar.gz" || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 36 | 37 | cp test-0.data test-0.data.orig 38 | cp test-1.data test-1.data.orig 39 | cp test-2.data test-2.data.orig 40 | cp test-3.data test-3.data.orig 41 | cp test-4.data test-4.data.orig 42 | cp test-5.data test-5.data.orig 43 | cp test-6.data test-6.data.orig 44 | cp test-7.data test-7.data.orig 45 | cp test-8.data test-8.data.orig 46 | cp test-9.data test-9.data.orig 47 | 48 | banner="Repairing two files using PAR 1.0 data" 49 | dashes=`echo "$banner" | sed s/./-/g` 50 | 51 | echo $dashes 52 | echo $banner 53 | echo $dashes 54 | 55 | rm -f test-1.data test-3.data 56 | $PARBINARY r testdata.par || { echo "ERROR: Reconstruction of two files using PAR 1.0 failed" ; exit 1; } >&2 57 | cmp -s test-1.data test-1.data.orig && cmp -s test-3.data test-3.data.orig || { echo "ERROR: Repaired files do not match originals" ; exit 1; } >&2 58 | 59 | cd "$TESTROOT" 60 | rm -rf "run$testname" 61 | 62 | exit 0 63 | -------------------------------------------------------------------------------- /tests/test30: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | tar -xzf "$TESTDATA/bug128-parfiles.tar.gz" || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 36 | 37 | banner="Issue 128, 0 byte files cause issue" 38 | dashes=`echo "$banner" | sed s/./-/g` 39 | 40 | echo $dashes 41 | echo $banner 42 | echo $dashes 43 | 44 | # check par2 with one 0 byte file 45 | touch test-a.data 46 | 47 | # Verify with 0 byte file 48 | $PARBINARY verify recovery.par2 || { echo "ERROR: 0 byte file verify failed" ; exit 1; } >&2 49 | 50 | rm test-a.data 51 | 52 | # Repair with 0 byte file 53 | $PARBINARY repair recovery.par2 || { echo "ERROR: 0 byte file repair failed" ; exit 1; } >&2 54 | 55 | cd "$TESTROOT" 56 | rm -rf "run$testname" 57 | 58 | exit 0 59 | -------------------------------------------------------------------------------- /tests/test31: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/smallsubdirdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="Bug 150, Files in rootfolder are not used with recursion" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | # before the subdirs 44 | echo "file in rootpath" > aaaa-test.data 45 | # after the subdirs 46 | echo "another file in rootpath" > test-a.data 47 | 48 | ###### 49 | # BEFORE: 50 | # 51 | # $ tree 52 | # . 53 | # ├── aaaa-test.data 54 | # ├── subdir1 55 | # │   └── test-0.data 56 | # ├── subdir2 57 | # │   ├── test-1.data 58 | # │   ├── test-2.data 59 | # │   ├── test-3.data 60 | # │   ├── test-4.data 61 | # │   ├── test-5.data 62 | # │   ├── test-6.data 63 | # │   ├── test-7.data 64 | # │   ├── test-8.data 65 | # │   └── test-9.data 66 | # └── test-a.data 67 | # 68 | # 3 directories, 12 files 69 | ###### 70 | 71 | $PARBINARY create -R * || { echo "ERROR: Recursive creation of PAR 2.0 files failed" ; exit 1; } >&2 72 | 73 | ###### 74 | # AFTER: 75 | # 76 | # tree 77 | # . 78 | # ├── aaaa-test.data 79 | # ├── aaaa-test.data.par2 80 | # ├── aaaa-test.data.vol000+01.par2 81 | # ├── aaaa-test.data.vol001+02.par2 82 | # ├── aaaa-test.data.vol003+04.par2 83 | # ├── aaaa-test.data.vol007+08.par2 84 | # ├── aaaa-test.data.vol015+16.par2 85 | # ├── aaaa-test.data.vol031+32.par2 86 | # ├── aaaa-test.data.vol063+37.par2 87 | # ├── subdir1 88 | # │   └── test-0.data 89 | # ├── subdir2 90 | # │   ├── test-1.data 91 | # │   ├── test-2.data 92 | # │   ├── test-3.data 93 | # │   ├── test-4.data 94 | # │   ├── test-5.data 95 | # │   ├── test-6.data 96 | # │   ├── test-7.data 97 | # │   ├── test-8.data 98 | # │   └── test-9.data 99 | # └── test-a.data 100 | # 101 | # 3 directories, 20 files 102 | ###### 103 | 104 | # The first file in the wildcard expansion is used ad parfilename so not 105 | # covered for repair 106 | rm aaaa-test.data 107 | 108 | $PARBINARY verify aaaa-test.data.par2 || { echo "ERROR: verify of rootpath inclusion failed" ; exit 1; } >&2 109 | 110 | cd "$TESTROOT" 111 | rm -rf "run$testname" 112 | 113 | exit 0 114 | -------------------------------------------------------------------------------- /tests/test32: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/subdirdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="Bug 205, Files already exist so no par2 is created" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | mkdir par2 44 | 45 | $PARBINARY create -vv -a par2/disk1.par2 -b32768 -n31 -R -v -B./ * || { echo "ERROR: Recursive creation of PAR 2.0 files failed" ; exit 1; } >&2 46 | 47 | $PARBINARY verify -B./ par2/disk1.par2 || { echo "ERROR: verify failed" ; exit 1; } >&2 48 | 49 | cd "$TESTROOT" 50 | rm -rf "run$testname" 51 | 52 | exit 0 53 | -------------------------------------------------------------------------------- /tests/test4: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | tar -xzf "$TESTDATA/flatdata-par2files.tar.gz" || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 36 | 37 | cp test-0.data test-0.data.orig 38 | cp test-1.data test-1.data.orig 39 | cp test-2.data test-2.data.orig 40 | cp test-3.data test-3.data.orig 41 | cp test-4.data test-4.data.orig 42 | cp test-5.data test-5.data.orig 43 | cp test-6.data test-6.data.orig 44 | cp test-7.data test-7.data.orig 45 | cp test-8.data test-8.data.orig 46 | cp test-9.data test-9.data.orig 47 | 48 | banner="Repairing two files using PAR 2.0 data" 49 | dashes=`echo "$banner" | sed s/./-/g` 50 | 51 | echo $dashes 52 | echo $banner 53 | echo $dashes 54 | 55 | rm -f test-1.data test-3.data 56 | $PARBINARY r testdata.par2 || { echo "ERROR: Reconstruction of two files using PAR 2.0 failed" ; exit 1; } >&2 57 | cmp -s test-1.data test-1.data.orig && cmp -s test-3.data test-3.data.orig || { echo "ERROR: Repaired files do not match originals" ; exit 1; } >&2 58 | 59 | cd "$TESTROOT" 60 | rm -rf "run$testname" 61 | 62 | exit 0 63 | -------------------------------------------------------------------------------- /tests/test5: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | banner="Creating 100% PAR 2.0 recovery data" 37 | dashes=`echo "$banner" | sed s/./-/g` 38 | 39 | echo $dashes 40 | echo $banner 41 | echo $dashes 42 | 43 | $PARBINARY c -r100 -b190 -a newtest test-*.data || { echo "ERROR: Creating PAR 2.0 data failed" ; exit 1; } >&2 44 | 45 | cp test-0.data test-0.data.orig 46 | cp test-1.data test-1.data.orig 47 | cp test-2.data test-2.data.orig 48 | cp test-3.data test-3.data.orig 49 | cp test-4.data test-4.data.orig 50 | cp test-5.data test-5.data.orig 51 | cp test-6.data test-6.data.orig 52 | cp test-7.data test-7.data.orig 53 | cp test-8.data test-8.data.orig 54 | cp test-9.data test-9.data.orig 55 | 56 | rm -f test-*.data 57 | 58 | banner="Repairing 100% loss using PAR 2.0 data" 59 | dashes=`echo "$banner" | sed s/./-/g` 60 | 61 | echo $dashes 62 | echo $banner 63 | echo $dashes 64 | 65 | rm -f test-*.data 66 | 67 | $PARBINARY r newtest.par2 || { echo "ERROR: Full Repair using PAR 2.0 failed" ; exit 1; } >&2 68 | 69 | cmp -s test-0.data test-0.data.orig && cmp -s test-1.data test-1.data.orig && cmp -s test-2.data test-2.data.orig && cmp -s test-3.data test-3.data.orig && cmp -s test-4.data test-4.data.orig && cmp -s test-5.data test-5.data.orig && cmp -s test-6.data test-6.data.orig && cmp -s test-7.data test-7.data.orig && cmp -s test-8.data test-8.data.orig && cmp -s test-9.data test-9.data.orig || { echo "ERROR: Repaired files do not match originals" ; exit 1 ; } >&2 70 | 71 | cd "$TESTROOT" 72 | rm -rf "run$testname" 73 | 74 | exit 0 75 | -------------------------------------------------------------------------------- /tests/test6: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/subdirdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | tar -xzf "$TESTDATA/subdirdata-par2files-unix.tar.gz" || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 36 | 37 | banner="Repairing two files in subdirs using PAR 2.0 data" 38 | dashes=`echo "$banner" | sed s/./-/g` 39 | 40 | echo $dashes 41 | echo $banner 42 | echo $dashes 43 | 44 | cp subdir1/test-2.data subdir1/test-2.data.orig 45 | cp subdir2/test-7.data subdir2/test-7.data.orig 46 | 47 | rm -f subdir1/test-2.data subdir2/test-7.data 48 | $PARBINARY r testdata.par2 || { echo "ERROR: Reconstruction of two files using PAR 2.0 failed" ; exit 1; } >&2 49 | cmp -s subdir1/test-2.data subdir1/test-2.data.orig && cmp -s subdir2/test-7.data subdir2/test-7.data.orig || { echo "ERROR: Repaired files do not match originals" ; exit 1; } >&2 50 | 51 | cd "$TESTROOT" 52 | rm -rf "run$testname" 53 | 54 | exit 0 55 | -------------------------------------------------------------------------------- /tests/test7: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/subdirdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | tar -xzf "$TESTDATA/subdirdata-par2files-win.tar.gz" || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 36 | 37 | banner="Repairing two files in subdirs using PAR 2.0 data generated on windows" 38 | dashes=`echo "$banner" | sed s/./-/g` 39 | 40 | echo $dashes 41 | echo $banner 42 | echo $dashes 43 | 44 | cp subdir1/test-2.data subdir1/test-2.data.orig 45 | cp subdir2/test-7.data subdir2/test-7.data.orig 46 | 47 | rm -f subdir1/test-2.data subdir2/test-7.data 48 | $PARBINARY r testdata.par2 || { echo "ERROR: Reconstruction of two files using PAR 2.0 failed" ; exit 1; } >&2 49 | cmp -s subdir1/test-2.data subdir1/test-2.data.orig && cmp -s subdir2/test-7.data subdir2/test-7.data.orig || { echo "ERROR: Repaired files do not match originals" ; exit 1; } >&2 50 | 51 | cd "$TESTROOT" 52 | rm -rf "run$testname" 53 | 54 | exit 0 55 | -------------------------------------------------------------------------------- /tests/test8: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/subdirdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | 36 | mkdir source1 && mv subdir1 subdir2 source1 37 | 38 | cd source1 39 | 40 | banner="create par2files on subdir" 41 | dashes=`echo "$banner" | sed s/./-/g` 42 | 43 | echo $dashes 44 | echo $banner 45 | echo $dashes 46 | 47 | $PARBINARY c -R testdata.par2 * || { echo "ERROR: construction of files using PAR 2.0 failed" ; exit 1; } >&2 48 | 49 | cd .. 50 | mv source1 source2 51 | 52 | cd source2 53 | 54 | banner="verify par2files on subdir, moved source folder" 55 | dashes=`echo "$banner" | sed s/./-/g` 56 | 57 | echo $dashes 58 | echo $banner 59 | echo $dashes 60 | 61 | $PARBINARY v testdata.par2 || { echo "ERROR: verification of files using PAR 2.0 failed" ; exit 1; } >&2 62 | 63 | cd "$TESTROOT" 64 | rm -rf "run$testname" 65 | 66 | exit 0 67 | -------------------------------------------------------------------------------- /tests/test9: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | # valgrind tests memory usage. 6 | # wine allow for windows testing on linux 7 | if [ -n "${PARVALGRINDOPTS+set}" ] 8 | then 9 | PARBINARY="valgrind $PARVALGRINDOPTS $execdir/par2" 10 | elif [ "`which wine`" != "" ] && [ -f "$execdir/par2.exe" ] 11 | then 12 | PARBINARY="wine $execdir/par2.exe" 13 | else 14 | PARBINARY="$execdir/par2" 15 | fi 16 | 17 | 18 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 19 | srcdir="$PWD" 20 | TESTDATA="$srcdir/tests" 21 | else 22 | srcdir="$PWD/$srcdir" 23 | TESTDATA="$srcdir/tests" 24 | fi 25 | 26 | TESTROOT="$PWD" 27 | 28 | testname=$(basename $0) 29 | rm -f "$testname.log" 30 | rm -rf "run$testname" 31 | 32 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 33 | 34 | tar -xzf "$TESTDATA/flatdata.tar.gz" || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 35 | tar -xzf "$TESTDATA/flatdata-par2files.tar.gz" || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 36 | 37 | banner="rename using PAR 2.0 data" 38 | dashes=`echo "$banner" | sed s/./-/g` 39 | 40 | echo $dashes 41 | echo $banner 42 | echo $dashes 43 | 44 | mv test-1.data rename4 45 | mv test-2.data rename5 46 | mv test-3.data rename6 47 | mv test-4.data rename7 48 | mv test-5.data rename9 49 | mv test-6.data rename8 50 | mv test-7.data rename3 51 | mv test-8.data rename1 52 | mv test-9.data rename2 53 | 54 | $PARBINARY r testdata.par2 rename* || { echo "ERROR: Initial PAR 2.0 verification and rename failed" ; exit 1; } >&2 55 | test -e test-1.data || { echo "ERROR: rename failed" ; exit 1; } >&2 56 | test -e test-2.data || { echo "ERROR: rename failed" ; exit 1; } >&2 57 | test -e test-3.data || { echo "ERROR: rename failed" ; exit 1; } >&2 58 | test -e test-4.data || { echo "ERROR: rename failed" ; exit 1; } >&2 59 | test -e test-5.data || { echo "ERROR: rename failed" ; exit 1; } >&2 60 | test -e test-6.data || { echo "ERROR: rename failed" ; exit 1; } >&2 61 | test -e test-7.data || { echo "ERROR: rename failed" ; exit 1; } >&2 62 | test -e test-8.data || { echo "ERROR: rename failed" ; exit 1; } >&2 63 | test -e test-9.data || { echo "ERROR: rename failed" ; exit 1; } >&2 64 | 65 | cd "$TESTROOT" 66 | rm -rf "run$testname" 67 | 68 | exit 0 69 | -------------------------------------------------------------------------------- /tests/testMem: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | if [ -z "$srcdir" ] || [ "." = "$srcdir" ]; then 6 | srcdir="$PWD" 7 | TESTDATA="$srcdir/tests" 8 | else 9 | srcdir="$PWD/$srcdir" 10 | TESTDATA="$srcdir/tests" 11 | fi 12 | 13 | TESTROOT=$PWD 14 | 15 | testname=$(basename $0) 16 | rm -f "$testname.log" 17 | rm -rf "run$testname" 18 | 19 | mkdir "run$testname" && cd "run$testname" || { echo "ERROR: Could not change to test directory" ; exit 1; } >&2 20 | 21 | tar -xzf $TESTDATA/subdirdata.tar.gz || { echo "ERROR: Could not extract data test files" ; exit 1; } >&2 22 | tar -xzf $TESTDATA/subdirdata-par2files-unix.tar.gz || { echo "ERROR: Could not extract par test files" ; exit 1; } >&2 23 | 24 | rm -f subdir1/test-2.data subdir2/test-7.data 25 | valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all $execdir/par2 r testdata.par2 26 | 27 | cd $TESTROOT 28 | rm -rf run$testname 29 | 30 | exit 0 31 | -------------------------------------------------------------------------------- /tests/testcollision/2mb_0s.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/testcollision/2mb_0s.bin -------------------------------------------------------------------------------- /tests/testcollision/2mb_0s.bin.par2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/testcollision/2mb_0s.bin.par2 -------------------------------------------------------------------------------- /tests/testcollision/2mb_col.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/testcollision/2mb_col.bin -------------------------------------------------------------------------------- /tests/testcollision/2mb_col.bin.par2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/testcollision/2mb_col.bin.par2 -------------------------------------------------------------------------------- /tests/testcollision/pattern16.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/testcollision/pattern16.bin -------------------------------------------------------------------------------- /tests/testcollision/pattern16.bin.par2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animetosho/par2cmdline-turbo/468b88363f7f4e8d438db7574432b2e934f033d9/tests/testcollision/pattern16.bin.par2 -------------------------------------------------------------------------------- /tests/unit_tests: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | execdir="$PWD" 4 | 5 | for f in $execdir/tests/*_test 6 | do 7 | # check that the filename exists. If there are no files, 8 | # Bourne shell will treat $execdir/tests/*_test like a 9 | # literal string! 10 | [ -f "$f" ] || continue 11 | 12 | echo "------------------------------------------------------" 13 | echo "Running unit tests from file $f" 14 | echo "------------------------------------------------------" 15 | 16 | if [ -n "${PARVALGRINDOPTS+set}" ] 17 | then 18 | PARBINARY="valgrind $PARVALGRINDOPTS $f" 19 | else 20 | PARBINARY="$f" 21 | fi 22 | 23 | $PARBINARY || { echo "ERROR: $f failed." ; exit 1; } >&2 24 | 25 | echo "------------------------------------------------------" 26 | echo "Unit test complete for file $f" 27 | echo "------------------------------------------------------" 28 | done 29 | 30 | for f in $execdir/tests/*_test.exe 31 | do 32 | # check that the filename exists. If there are no files, 33 | # Bourne shell will treat $execdir/tests/*_test like a 34 | # literal string! 35 | [ -f "$f" ] || continue 36 | 37 | echo "------------------------------------------------------" 38 | echo "Running unit tests from file $f" 39 | echo "------------------------------------------------------" 40 | 41 | wine $f || { echo "ERROR: $f failed." ; exit 1; } >&2 42 | 43 | echo "------------------------------------------------------" 44 | echo "Unit test complete for file $f" 45 | echo "------------------------------------------------------" 46 | done 47 | 48 | exit 0 49 | --------------------------------------------------------------------------------