pax_global_header00006660000000000000000000000064143530566720014525gustar00rootroot0000000000000052 comment=efdec30137b7f3ef107fa9d3818fd9a4744e259b python-xxhash-3.2.0/000077500000000000000000000000001435305667200143515ustar00rootroot00000000000000python-xxhash-3.2.0/.github/000077500000000000000000000000001435305667200157115ustar00rootroot00000000000000python-xxhash-3.2.0/.github/workflows/000077500000000000000000000000001435305667200177465ustar00rootroot00000000000000python-xxhash-3.2.0/.github/workflows/build.yml000066400000000000000000000053171435305667200215760ustar00rootroot00000000000000name: Build and upload to PyPI on: [push] jobs: build_wheels: name: Build ${{ matrix.archs }} ${{ matrix.build }} wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-20.04] archs: ["x86_64, i686", "aarch64", "ppc64le", "s390x"] build: ["manylinux", "musllinux"] include: - os: windows-2019 archs: "AMD64" - os: windows-2019 archs: "x86" - os: macos-10.15 archs: "x86_64, arm64" steps: - name: Disable git autocrlf run: | git config --global core.autocrlf false git config --global core.eol lf - uses: actions/checkout@v3 with: fetch-depth: 0 submodules: recursive - name: Set up QEMU uses: docker/setup-qemu-action@v1.2.0 if: runner.os == 'Linux' - name: Build wheels uses: pypa/cibuildwheel@v2.11.2 env: CIBW_ARCHS: "${{ matrix.archs }}" CIBW_BUILD: "${{ matrix.build && '*-' || ''}}${{ matrix.build }}*" CIBW_PRERELEASE_PYTHONS: "${{ !startsWith(github.ref, 'refs/tags/v') }}" - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl build_sdist: name: Build sdist runs-on: ubuntu-20.04 strategy: matrix: python-version: ['3.10'] steps: - uses: actions/checkout@v3 with: fetch-depth: 0 submodules: recursive - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: python -m pip install -U pip 'setuptools>=45' 'setuptools-scm>=6.2' - name: Build sdist run: python setup.py build sdist - uses: actions/upload-artifact@v2 with: path: dist/*.tar.gz upload_pypi: name: Upload to (Test) PyPI needs: [build_wheels, build_sdist] runs-on: ubuntu-20.04 if: github.event_name == 'push' && github.repository == 'ifduyue/python-xxhash' steps: - uses: actions/download-artifact@v2 with: name: artifact path: dist - name: Upload to Test PyPI uses: pypa/gh-action-pypi-publish@v1.4.2 with: user: __token__ password: ${{ secrets.PYPI_TEST_TOKEN }} skip_existing: true repository_url: https://test.pypi.org/legacy/ - name: Upload to PyPI if: startsWith(github.ref, 'refs/tags/v') uses: pypa/gh-action-pypi-publish@v1.4.2 with: user: __token__ password: ${{ secrets.PYPI_TOKEN }} skip_existing: true python-xxhash-3.2.0/.github/workflows/test.yml000066400000000000000000000013431435305667200214510ustar00rootroot00000000000000name: test on: [push] jobs: build: runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', '3.11'] steps: - uses: actions/checkout@v3 with: fetch-depth: 0 submodules: recursive - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: python -m pip install -U pip 'setuptools>=45' 'setuptools-scm>=6.2' - name: Run tests run: | python setup.py build_ext --inplace python -m unittest discover -vv tests ./bench.sh python-xxhash-3.2.0/.gitignore000066400000000000000000000001261435305667200163400ustar00rootroot00000000000000*.py[co] *.so *.o __pycache__/ build /xxhash.egg-info/ /xxhash/version.py .dmypy.json python-xxhash-3.2.0/.gitmodules000066400000000000000000000001271435305667200165260ustar00rootroot00000000000000[submodule "xxhash"] path = deps/xxhash url = https://github.com/Cyan4973/xxHash.git python-xxhash-3.2.0/CHANGELOG.rst000066400000000000000000000066461435305667200164060ustar00rootroot00000000000000CHANGELOG ----------- v3.2.0 2022-12-28 ~~~~~~~~~~~~~~~~~ This is the last version to support Python 3.6 - Build Python 3.11 wheels. - Remove setup.py test_suites, call unittest directly v3.1.0 2022-10-19 ~~~~~~~~~~~~~~~~~ - Type annotations. - Enabled muslinux wheels building. v3.0.0 2022-02-25 ~~~~~~~~~~~~~~~~~ - New set `algorithms_available` lists all implemented algorithms in `xxhash` package. - Upgrade xxHash to v0.8.1. - Drop support for EOL Python versions, require python >= 3.6 from now on. - Migrate to github actions and build arm64 wheels for macOS. - Always release GIL. v2.0.2 2021-04-15 ~~~~~~~~~~~~~~~~~ - Fix Travis CI OSX dpl python2.7 get-pip.py error v2.0.1 2021-04-15 ~~~~~~~~~~~~~~~~~ - Only to trigger Python 3.9 wheels building. v2.0.0 2020-08-03 ~~~~~~~~~~~~~~~~~ - **Require xxHash version >= v0.8.0** - Upgrade xxHash to v0.8.0 - XXH3 hashes: `xxh3_64`, `xxh3_128`, and their oneshot functions v1.4.4 2020-06-20 ~~~~~~~~~~~~~~~~~ - Upgrade xxHash to v0.7.3 - Stop using PEP393 deprecated APIs - Use XXH(32|64)_canonicalFromHash to replace u2bytes and ull2bytes v1.4.3 2019-11-12 ~~~~~~~~~~~~~~~~~ - Upgrade xxHash to v0.7.2 - Python 3.8 wheels v1.4.2 2019-10-13 ~~~~~~~~~~~~~~~~~ - Fixed: setup.py fails when reading README.rst and the default encoding is not UTF-8 v1.4.1 2019-08-27 ~~~~~~~~~~~~~~~~~ - Fixed: xxh3.h in missing from source tarball v1.4.0 2019-08-25 ~~~~~~~~~~~~~~~~~ - Upgrade xxHash to v0.7.1 v1.3.0 2018-10-21 ~~~~~~~~~~~~~~~~~ - Wheels are now built automatically - Split CFFI variant into a separate package `ifduyue/python-xxhash-cffi `_ v1.2.0 2018-07-13 ~~~~~~~~~~~~~~~~~ - Add oneshot functions xxh{32,64}_{,int,hex}digest v1.1.0 2018-07-05 ~~~~~~~~~~~~~~~~~ - Allow input larger than 2GB - Release the GIL on sufficiently large input - Drop support for Python 3.2 v1.0.1 2017-03-02 ~~~~~~~~~~~~~~~~~~ - Free state actively, instead of delegating it to ffi.gc v1.0.0 2017-02-10 ~~~~~~~~~~~~~~~~~~ - Fixed copy() segfault - Added CFFI variant v0.6.3 2017-02-10 ~~~~~~~~~~~~~~~~~~ - Fixed copy() segfault v0.6.2 2017-02-10 ~~~~~~~~~~~~~~~~~~ - Upgrade xxHash to v0.6.2 v0.6.1 2016-06-26 ~~~~~~~~~~~~~~~~~~ - Upgrade xxHash to v0.6.1 v0.5.0 2016-03-02 ~~~~~~~~~~~~~~~~~~ - Upgrade xxHash to v0.5.0 v0.4.3 2015-08-21 ~~~~~~~~~~~~~~~~~~ - Upgrade xxHash to r42 v0.4.1 2015-08-16 ~~~~~~~~~~~~~~~~~~ - Upgrade xxHash to r41 v0.4.0 2015-08-05 ~~~~~~~~~~~~~~~~~~ - Added method reset - Upgrade xxHash to r40 v0.3.2 2015-01-27 ~~~~~~~~~~~~~~~~~~ - Fixed some typos in docstrings v0.3.1 2015-01-24 ~~~~~~~~~~~~~~~~~~ - Upgrade xxHash to r39 v0.3.0 2014-11-11 ~~~~~~~~~~~~~~~~~~ - Change digest() from little-endian representation to big-endian representation of the integer digest. This change breaks compatibility (digest() results are different). v0.2.0 2014-10-25 ~~~~~~~~~~~~~~~~~~ - Make this package hashlib-compliant v0.1.3 2014-10-23 ~~~~~~~~~~~~~~~~~~ - Update xxHash to r37 v0.1.2 2014-10-19 ~~~~~~~~~~~~~~~~~~ - Improve: Check XXHnn_init() return value. - Update xxHash to r36 v0.1.1 2014-08-07 ~~~~~~~~~~~~~~~~~~ - Improve: Can now be built with Visual C++ Compiler. v0.1.0 2014-08-05 ~~~~~~~~~~~~~~~~~~ - New: XXH32 and XXH64 type, which support partially update. - Fix: build under Python 3.4 v0.0.2 2014-08-03 ~~~~~~~~~~~~~~~~~~ - NEW: Support Python 3 v0.0.1 2014-07-30 ~~~~~~~~~~~~~~~~~~ - NEW: xxh32 and xxh64 python-xxhash-3.2.0/LICENSE000066400000000000000000000024411435305667200153570ustar00rootroot00000000000000Copyright (c) 2014-2020, Yue Du All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. python-xxhash-3.2.0/MANIFEST.in000066400000000000000000000004261435305667200161110ustar00rootroot00000000000000include README.rst include CHANGELOG.rst include LICENSE include deps/xxhash/xxh3.h include deps/xxhash/xxhash.h include deps/xxhash/xxhash.c include deps/xxhash/LICENSE graft tests global-exclude __pycache__ global-exclude *.py[co] prune .github exclude .gitignore .gitmodules python-xxhash-3.2.0/Pipfile000066400000000000000000000002251435305667200156630ustar00rootroot00000000000000[[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] [dev-packages] mypy = "*" [requires] python_version = "3.9" python-xxhash-3.2.0/Pipfile.lock000066400000000000000000000071541435305667200166220ustar00rootroot00000000000000{ "_meta": { "hash": { "sha256": "83fe814f67b2b1c52cb7d081ab85c1e9b530407e5c77e345af86192075ea0a82" }, "pipfile-spec": 6, "requires": { "python_version": "3.9" }, "sources": [ { "name": "pypi", "url": "https://pypi.org/simple", "verify_ssl": true } ] }, "default": {}, "develop": { "mypy": { "hashes": [ "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9", "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a", "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9", "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e", "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2", "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212", "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b", "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885", "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150", "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703", "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072", "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457", "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e", "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0", "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb", "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97", "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8", "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811", "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6", "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de", "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504", "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921", "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d" ], "index": "pypi", "version": "==0.910" }, "mypy-extensions": { "hashes": [ "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" ], "version": "==0.4.3" }, "toml": { "hashes": [ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" ], "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", "version": "==0.10.2" }, "typing-extensions": { "hashes": [ "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed", "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9" ], "markers": "python_version >= '3.6'", "version": "==4.0.0" } } } python-xxhash-3.2.0/README.rst000066400000000000000000000171471435305667200160520ustar00rootroot00000000000000python-xxhash ============= .. image:: https://github.com/ifduyue/python-xxhash/actions/workflows/test.yml/badge.svg :target: https://github.com/ifduyue/python-xxhash/actions/workflows/test.yml :alt: Github Actions Status .. image:: https://img.shields.io/pypi/v/xxhash.svg :target: https://pypi.org/project/xxhash/ :alt: Latest Version .. image:: https://img.shields.io/pypi/pyversions/xxhash.svg :target: https://pypi.org/project/xxhash/ :alt: Supported Python versions .. image:: https://img.shields.io/pypi/l/xxhash.svg :target: https://pypi.org/project/xxhash/ :alt: License .. _HMAC: http://en.wikipedia.org/wiki/Hash-based_message_authentication_code .. _xxHash: https://github.com/Cyan4973/xxHash .. _Cyan4973: https://github.com/Cyan4973 xxhash is a Python binding for the xxHash_ library by `Yann Collet`__. __ Cyan4973_ Installation ------------ .. code-block:: bash $ pip install xxhash You can also install using conda: .. code-block:: bash $ conda install -c conda-forge python-xxhash Installing From Source ~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash $ pip install --no-binary xxhash xxhash Prerequisites ++++++++++++++ On Debian/Ubuntu: .. code-block:: bash $ apt-get install python-dev gcc On CentOS/Fedora: .. code-block:: bash $ yum install python-devel gcc redhat-rpm-config Linking to libxxhash.so ~~~~~~~~~~~~~~~~~~~~~~~~ By default python-xxhash will use bundled xxHash, we can change this by specifying ENV var ``XXHASH_LINK_SO``: .. code-block:: bash $ XXHASH_LINK_SO=1 pip install --no-binary xxhash xxhash Usage -------- Module version and its backend xxHash library version can be retrieved using the module properties ``VERSION`` AND ``XXHASH_VERSION`` respectively. .. code-block:: python >>> import xxhash >>> xxhash.VERSION '2.0.0' >>> xxhash.XXHASH_VERSION '0.8.0' This module is hashlib-compliant, which means you can use it in the same way as ``hashlib.md5``. | update() -- update the current digest with an additional string | digest() -- return the current digest value | hexdigest() -- return the current digest as a string of hexadecimal digits | intdigest() -- return the current digest as an integer | copy() -- return a copy of the current xxhash object | reset() -- reset state md5 digest returns bytes, but the original xxh32 and xxh64 C APIs return integers. While this module is made hashlib-compliant, ``intdigest()`` is also provided to get the integer digest. Constructors for hash algorithms provided by this module are ``xxh32()`` and ``xxh64()``. For example, to obtain the digest of the byte string ``b'Nobody inspects the spammish repetition'``: .. code-block:: python >>> import xxhash >>> x = xxhash.xxh32() >>> x.update(b'Nobody inspects') >>> x.update(b' the spammish repetition') >>> x.digest() b'\xe2);/' >>> x.digest_size 4 >>> x.block_size 16 More condensed: .. code-block:: python >>> xxhash.xxh32(b'Nobody inspects the spammish repetition').hexdigest() 'e2293b2f' >>> xxhash.xxh32(b'Nobody inspects the spammish repetition').digest() == x.digest() True An optional seed (default is 0) can be used to alter the result predictably: .. code-block:: python >>> import xxhash >>> xxhash.xxh64('xxhash').hexdigest() '32dd38952c4bc720' >>> xxhash.xxh64('xxhash', seed=20141025).hexdigest() 'b559b98d844e0635' >>> x = xxhash.xxh64(seed=20141025) >>> x.update('xxhash') >>> x.hexdigest() 'b559b98d844e0635' >>> x.intdigest() 13067679811253438005 Be careful that xxh32 takes an unsigned 32-bit integer as seed, while xxh64 takes an unsigned 64-bit integer. Although unsigned integer overflow is defined behavior, it's better not to make it happen: .. code-block:: python >>> xxhash.xxh32('I want an unsigned 32-bit seed!', seed=0).hexdigest() 'f7a35af8' >>> xxhash.xxh32('I want an unsigned 32-bit seed!', seed=2**32).hexdigest() 'f7a35af8' >>> xxhash.xxh32('I want an unsigned 32-bit seed!', seed=1).hexdigest() 'd8d4b4ba' >>> xxhash.xxh32('I want an unsigned 32-bit seed!', seed=2**32+1).hexdigest() 'd8d4b4ba' >>> >>> xxhash.xxh64('I want an unsigned 64-bit seed!', seed=0).hexdigest() 'd4cb0a70a2b8c7c1' >>> xxhash.xxh64('I want an unsigned 64-bit seed!', seed=2**64).hexdigest() 'd4cb0a70a2b8c7c1' >>> xxhash.xxh64('I want an unsigned 64-bit seed!', seed=1).hexdigest() 'ce5087f12470d961' >>> xxhash.xxh64('I want an unsigned 64-bit seed!', seed=2**64+1).hexdigest() 'ce5087f12470d961' ``digest()`` returns bytes of the **big-endian** representation of the integer digest: .. code-block:: python >>> import xxhash >>> h = xxhash.xxh64() >>> h.digest() b'\xefF\xdb7Q\xd8\xe9\x99' >>> h.intdigest().to_bytes(8, 'big') b'\xefF\xdb7Q\xd8\xe9\x99' >>> h.hexdigest() 'ef46db3751d8e999' >>> format(h.intdigest(), '016x') 'ef46db3751d8e999' >>> h.intdigest() 17241709254077376921 >>> int(h.hexdigest(), 16) 17241709254077376921 Besides xxh32/xxh64 mentioned above, oneshot functions are also provided, so we can avoid allocating XXH32/64 state on heap: | xxh32_digest(bytes, seed=0) | xxh32_intdigest(bytes, seed=0) | xxh32_hexdigest(bytes, seed=0) | xxh64_digest(bytes, seed=0) | xxh64_intdigest(bytes, seed=0) | xxh64_hexdigest(bytes, seed=0) .. code-block:: python >>> import xxhash >>> xxhash.xxh64('a').digest() == xxhash.xxh64_digest('a') True >>> xxhash.xxh64('a').intdigest() == xxhash.xxh64_intdigest('a') True >>> xxhash.xxh64('a').hexdigest() == xxhash.xxh64_hexdigest('a') True >>> xxhash.xxh64_hexdigest('xxhash', seed=20141025) 'b559b98d844e0635' >>> xxhash.xxh64_intdigest('xxhash', seed=20141025) 13067679811253438005L >>> xxhash.xxh64_digest('xxhash', seed=20141025) '\xb5Y\xb9\x8d\x84N\x065' .. code-block:: python In [1]: import xxhash In [2]: %timeit xxhash.xxh64_hexdigest('xxhash') 268 ns ± 24.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) In [3]: %timeit xxhash.xxh64('xxhash').hexdigest() 416 ns ± 17.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) XXH3 hashes are available since v2.0.0 (xxHash v0.8.0), they are: Streaming classes: | xxh3_64 | xxh3_128 Oneshot functions: | xxh3_64_digest(bytes, seed=0) | xxh3_64_intdigest(bytes, seed=0) | xxh3_64_hexdigest(bytes, seed=0) | xxh3_128_digest(bytes, seed=0) | xxh3_128_intdigest(bytes, seed=0) | xxh3_128_hexdigest(bytes, seed=0) And aliases: | xxh128 = xxh3_128 | xxh128_digest = xxh3_128_digest | xxh128_intdigest = xxh3_128_intdigest | xxh128_hexdigest = xxh3_128_hexdigest Caveats ------- SEED OVERFLOW ~~~~~~~~~~~~~~ xxh32 takes an unsigned 32-bit integer as seed, and xxh64 takes an unsigned 64-bit integer as seed. Make sure that the seed is greater than or equal to ``0``. ENDIANNESS ~~~~~~~~~~~ As of python-xxhash 0.3.0, ``digest()`` returns bytes of the **big-endian** representation of the integer digest. It used to be little-endian. DONT USE XXHASH IN HMAC ~~~~~~~~~~~~~~~~~~~~~~~ Though you can use xxhash as an HMAC_ hash function, but it's highly recommended not to. xxhash is **NOT** a cryptographic hash function, it is a non-cryptographic hash algorithm aimed at speed and quality. Do not put xxhash in any position where cryptographic hash functions are required. Copyright and License --------------------- Copyright (c) 2014-2020 Yue Du - https://github.com/ifduyue Licensed under `BSD 2-Clause License `_ python-xxhash-3.2.0/bench.sh000077500000000000000000000054171435305667200157760ustar00rootroot00000000000000#!/bin/bash PYTHON=${PYTHON-`which python`} echo Benchmarking ... echo -n " xxh32_intdigest 1000B: " $PYTHON -mtimeit -s 'from xxhash import xxh32_intdigest' \ -s 'import os' \ -s 'import random' \ -s 'seed = random.randint(0, 0xffffffff)' \ -s 'data = os.urandom(1000)' \ 'xxh32_intdigest(data, seed=seed)' echo -n " xxh32_intdigest 10000B: " $PYTHON -mtimeit -s 'from xxhash import xxh32_intdigest' \ -s 'import os' \ -s 'import random' \ -s 'seed = random.randint(0, 0xffffffff)' \ -s 'data = os.urandom(10000)' \ 'xxh32_intdigest(data, seed=seed)' echo -n " xxh64_intdigest 1000B: " $PYTHON -mtimeit -s 'from xxhash import xxh64_intdigest' \ -s 'import os' \ -s 'import random' \ -s 'seed = random.randint(0, 0xffffffffffffffff)' \ -s 'data = os.urandom(1000)' \ 'xxh64_intdigest(data, seed=seed)' echo -n " xxh64_intdigest 10000B: " $PYTHON -mtimeit -s 'from xxhash import xxh64_intdigest' \ -s 'import os' \ -s 'import random' \ -s 'seed = random.randint(0, 0xffffffffffffffff)' \ -s 'data = os.urandom(10000)' \ 'xxh64_intdigest(data, seed=seed)' echo -n " xxh3_64_intdigest 1000B: " $PYTHON -mtimeit -s 'from xxhash import xxh3_64_intdigest' \ -s 'import os' \ -s 'import random' \ -s 'seed = random.randint(0, 0xffffffffffffffff)' \ -s 'data = os.urandom(1000)' \ 'xxh3_64_intdigest(data, seed=seed)' echo -n " xxh3_64_intdigest 10000B: " $PYTHON -mtimeit -s 'from xxhash import xxh3_64_intdigest' \ -s 'import os' \ -s 'import random' \ -s 'seed = random.randint(0, 0xffffffffffffffff)' \ -s 'data = os.urandom(10000)' \ 'xxh3_64_intdigest(data, seed=seed)' echo -n " xxh3_128_intdigest 1000B: " $PYTHON -mtimeit -s 'from xxhash import xxh3_128_intdigest' \ -s 'import os' \ -s 'import random' \ -s 'seed = random.randint(0, 0xffffffffffffffff)' \ -s 'data = os.urandom(1000)' \ 'xxh3_128_intdigest(data, seed=seed)' echo -n " xxh3_128_intdigest 10000B: " $PYTHON -mtimeit -s 'from xxhash import xxh3_128_intdigest' \ -s 'import os' \ -s 'import random' \ -s 'seed = random.randint(0, 0xffffffffffffffff)' \ -s 'data = os.urandom(10000)' \ 'xxh3_128_intdigest(data, seed=seed)' python-xxhash-3.2.0/deps/000077500000000000000000000000001435305667200153045ustar00rootroot00000000000000python-xxhash-3.2.0/deps/xxhash/000077500000000000000000000000001435305667200166075ustar00rootroot00000000000000python-xxhash-3.2.0/mypy.ini000066400000000000000000000010051435305667200160440ustar00rootroot00000000000000[mypy] warn_unused_configs = True disallow_any_generics = True disallow_subclassing_any = True disallow_untyped_calls = True # disallow_untyped_defs = True disallow_incomplete_defs = True check_untyped_defs = True disallow_untyped_decorators = True no_implicit_optional = True warn_redundant_casts = True warn_unused_ignores = True warn_return_any = True implicit_reexport = False strict_equality = True # Options above stolen from # mypy --help | grep -A 9 -- '--strict ' pretty = True error_summary = False python-xxhash-3.2.0/pyproject.toml000066400000000000000000000003661435305667200172720ustar00rootroot00000000000000[build-system] requires = ["setuptools>=45", "wheel", "setuptools_scm>=6.2"] [tool.setuptools_scm] write_to = "xxhash/version.py" local_scheme = "no-local-version" write_to_template = "VERSION = \"{version}\"\nVERSION_TUPLE = {version_tuple}\n" python-xxhash-3.2.0/setup.py000066400000000000000000000033711435305667200160670ustar00rootroot00000000000000#!/usr/bin/env python from setuptools import setup, Extension import os import codecs if os.getenv('XXHASH_LINK_SO'): libraries = ['xxhash'] source = ['src/_xxhash.c'] include_dirs = [] else: libraries = [] source = ['src/_xxhash.c', 'deps/xxhash/xxhash.c'] include_dirs = ['deps/xxhash'] ext_modules = [ Extension( '_xxhash', source, include_dirs=include_dirs, libraries=libraries, ) ] def readfile(filename): with codecs.open(filename, encoding='utf-8', mode='r') as f: return f.read() long_description = readfile('README.rst') + '\n' + readfile('CHANGELOG.rst') setup( name='xxhash', description="Python binding for xxHash", long_description=long_description, long_description_content_type="text/x-rst", author='Yue Du', author_email='ifduyue@gmail.com', url='https://github.com/ifduyue/python-xxhash', license='BSD', packages=['xxhash'], ext_package='xxhash', classifiers=[ 'Development Status :: 5 - Production/Stable', 'License :: OSI Approved :: BSD License', 'Intended Audience :: Developers', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: Implementation :: CPython', ], python_requires=">=3.6", ext_modules=ext_modules, package_data={"xxhash": ["py.typed", "**.pyi"]}, ) python-xxhash-3.2.0/src/000077500000000000000000000000001435305667200151405ustar00rootroot00000000000000python-xxhash-3.2.0/src/_xxhash.c000066400000000000000000001406321435305667200167540ustar00rootroot00000000000000/* * Copyright (c) 2014-2020, Yue Du * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* This module provides an interface to xxhash, an extremely fast non-cryptographic hash algorithm algorithm */ #include #include #include "xxhash.h" #define TOSTRING(x) #x #define VALUE_TO_STRING(x) TOSTRING(x) #define XXHASH_VERSION XXH_VERSION_MAJOR.XXH_VERSION_MINOR.XXH_VERSION_RELEASE #define XXH32_DIGESTSIZE 4 #define XXH32_BLOCKSIZE 16 #define XXH64_DIGESTSIZE 8 #define XXH64_BLOCKSIZE 32 #define XXH128_DIGESTSIZE 16 #define XXH128_BLOCKSIZE 64 /***************************************************************************** * Module Functions *********************************************************** ****************************************************************************/ /* XXH32 */ static PyObject *xxh32_digest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH32_hash_t seed = 0; XXH32_hash_t intdigest; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; char retbuf[XXH32_DIGESTSIZE]; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|I:xxh32_digest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH32(buf.buf, buf.len, seed); PyBuffer_Release(&buf); XXH32_canonicalFromHash((XXH32_canonical_t *)retbuf, intdigest); return PyBytes_FromStringAndSize(retbuf, sizeof(retbuf)); } static PyObject *xxh32_intdigest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH32_hash_t seed = 0; XXH32_hash_t intdigest; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|I:xxh32_intdigest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH32(buf.buf, buf.len, seed); PyBuffer_Release(&buf); return Py_BuildValue("I", intdigest); } static PyObject *xxh32_hexdigest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH32_hash_t seed = 0; XXH32_hash_t intdigest; char digest[XXH32_DIGESTSIZE]; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; char retbuf[XXH32_DIGESTSIZE * 2]; int i, j; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|I:xxh32_hexdigest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH32(buf.buf, buf.len, seed); PyBuffer_Release(&buf); XXH32_canonicalFromHash((XXH32_canonical_t *)digest, intdigest); for (i = j = 0; i < XXH32_DIGESTSIZE; i++) { unsigned char c; c = (digest[i] >> 4) & 0xf; c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; c = (digest[i] & 0xf); c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; } return PyUnicode_FromStringAndSize(retbuf, sizeof(retbuf)); } /* XXH64 */ static PyObject *xxh64_digest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; XXH64_hash_t intdigest; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; char retbuf[XXH64_DIGESTSIZE]; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|K:xxh64_digest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH64(buf.buf, buf.len, seed); PyBuffer_Release(&buf); XXH64_canonicalFromHash((XXH64_canonical_t *)retbuf, intdigest); return PyBytes_FromStringAndSize(retbuf, sizeof(retbuf)); } static PyObject *xxh64_intdigest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; XXH64_hash_t intdigest; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|K:xxh64_intdigest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH64(buf.buf, buf.len, seed); PyBuffer_Release(&buf); return Py_BuildValue("K", intdigest); } static PyObject *xxh64_hexdigest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; XXH64_hash_t intdigest; char digest[XXH64_DIGESTSIZE]; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; char retbuf[XXH64_DIGESTSIZE * 2]; int i, j; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|K:xxh64_hexdigest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH64(buf.buf, buf.len, seed); PyBuffer_Release(&buf); XXH64_canonicalFromHash((XXH64_canonical_t *)digest, intdigest); for (i = j = 0; i < XXH64_DIGESTSIZE; i++) { unsigned char c; c = (digest[i] >> 4) & 0xf; c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; c = (digest[i] & 0xf); c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; } return PyUnicode_FromStringAndSize(retbuf, sizeof(retbuf)); } /* XXH3_64 */ static PyObject *xxh3_64_digest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; XXH64_hash_t intdigest = 0; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; char retbuf[XXH64_DIGESTSIZE]; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|K:xxh3_64_digest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH3_64bits_withSeed(buf.buf, buf.len, seed); PyBuffer_Release(&buf); XXH64_canonicalFromHash((XXH64_canonical_t *)retbuf, intdigest); return PyBytes_FromStringAndSize(retbuf, sizeof(retbuf)); } static PyObject *xxh3_64_intdigest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; XXH64_hash_t intdigest = 0; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|K:xxh3_64_intdigest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH3_64bits_withSeed(buf.buf, buf.len, seed); PyBuffer_Release(&buf); return Py_BuildValue("K", intdigest); } static PyObject *xxh3_64_hexdigest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; XXH64_hash_t intdigest; char digest[XXH64_DIGESTSIZE]; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; char retbuf[XXH64_DIGESTSIZE * 2]; int i, j; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|K:xxh3_64_hexdigest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH3_64bits_withSeed(buf.buf, buf.len, seed); PyBuffer_Release(&buf); XXH64_canonicalFromHash((XXH64_canonical_t *)digest, intdigest); for (i = j = 0; i < XXH64_DIGESTSIZE; i++) { unsigned char c; c = (digest[i] >> 4) & 0xf; c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; c = (digest[i] & 0xf); c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; } return PyUnicode_FromStringAndSize(retbuf, sizeof(retbuf)); } /* XXH3_128 */ static PyObject *xxh3_128_digest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; XXH128_hash_t intdigest; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; char retbuf[XXH128_DIGESTSIZE]; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|K:xxh3_128_digest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH3_128bits_withSeed(buf.buf, buf.len, seed); PyBuffer_Release(&buf); XXH128_canonicalFromHash((XXH128_canonical_t *)retbuf, intdigest); return PyBytes_FromStringAndSize(retbuf, sizeof(retbuf)); } static PyObject *xxh3_128_intdigest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; XXH128_hash_t intdigest; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; PyObject *result, *low, *high, *sixtyfour; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|K:xxh3_128_intdigest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH3_128bits_withSeed(buf.buf, buf.len, seed); PyBuffer_Release(&buf); sixtyfour = PyLong_FromLong(64); low = PyLong_FromUnsignedLongLong(intdigest.low64); high = PyLong_FromUnsignedLongLong(intdigest.high64); result = PyNumber_Lshift(high, sixtyfour); Py_DECREF(high); high = result; result = PyNumber_Add(high, low); Py_DECREF(high); Py_DECREF(low); Py_DECREF(sixtyfour); return result; } static PyObject *xxh3_128_hexdigest(PyObject *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; XXH128_hash_t intdigest; char digest[XXH128_DIGESTSIZE]; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; char retbuf[XXH128_DIGESTSIZE * 2]; int i, j; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|K:xxh3_128_hexdigest", keywords, &buf, &seed)) { return NULL; } intdigest = XXH3_128bits_withSeed(buf.buf, buf.len, seed); PyBuffer_Release(&buf); XXH128_canonicalFromHash((XXH128_canonical_t *)digest, intdigest); for (i = j = 0; i < XXH128_DIGESTSIZE; i++) { unsigned char c; c = (digest[i] >> 4) & 0xf; c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; c = (digest[i] & 0xf); c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; } return PyUnicode_FromStringAndSize(retbuf, sizeof(retbuf)); } /***************************************************************************** * Module Types *************************************************************** ****************************************************************************/ /* XXH32 */ typedef struct { PyObject_HEAD /* Type-specific fields go here. */ XXH32_state_t *xxhash_state; XXH32_hash_t seed; } PYXXH32Object; static PyTypeObject PYXXH32Type; static void PYXXH32_dealloc(PYXXH32Object *self) { XXH32_freeState(self->xxhash_state); PyObject_Del(self); } static void PYXXH32_do_update(PYXXH32Object *self, Py_buffer *buf) { Py_BEGIN_ALLOW_THREADS XXH32_update(self->xxhash_state, buf->buf, buf->len); Py_END_ALLOW_THREADS PyBuffer_Release(buf); } /* XXH32 methods */ static PyObject *PYXXH32_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PYXXH32Object *self; if ((self = PyObject_New(PYXXH32Object, &PYXXH32Type)) == NULL) { return NULL; } if ((self->xxhash_state = XXH32_createState()) == NULL) { return NULL; } return (PyObject *)self; } static int PYXXH32_init(PYXXH32Object *self, PyObject *args, PyObject *kwargs) { XXH32_hash_t seed = 0; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s*I:__init__", keywords, &buf, &seed)) { return -1; } self->seed = seed; XXH32_reset(self->xxhash_state, seed); if (buf.buf) { PYXXH32_do_update(self, &buf); } return 0; } PyDoc_STRVAR( PYXXH32_update_doc, "update (input)\n\n" "Update the xxh32 object with the string input. Repeated calls are\n" "equivalent to a single call with the concatenation of all the arguments."); static PyObject *PYXXH32_update(PYXXH32Object *self, PyObject *args) { Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTuple(args, "s*:update", &buf)) { return NULL; } PYXXH32_do_update(self, &buf); Py_RETURN_NONE; } PyDoc_STRVAR( PYXXH32_digest_doc, "digest() -> string\n\n" "Return the digest of the strings passed to the update() method so\n" "far. This is a 4-byte string which may contain non-ASCII characters,\n" "including null bytes."); static PyObject *PYXXH32_digest(PYXXH32Object *self) { char retbuf[XXH32_DIGESTSIZE]; XXH32_hash_t intdigest; intdigest = XXH32_digest(self->xxhash_state); XXH32_canonicalFromHash((XXH32_canonical_t *)retbuf, intdigest); return PyBytes_FromStringAndSize(retbuf, sizeof(retbuf)); } PyDoc_STRVAR( PYXXH32_hexdigest_doc, "hexdigest() -> string\n\n" "Like digest(), but returns the digest as a string of hexadecimal digits."); static PyObject *PYXXH32_hexdigest(PYXXH32Object *self) { XXH32_hash_t intdigest; char digest[XXH32_DIGESTSIZE]; char retbuf[XXH32_DIGESTSIZE * 2]; int i, j; intdigest = XXH32_digest(self->xxhash_state); XXH32_canonicalFromHash((XXH32_canonical_t *)digest, intdigest); for (i = j = 0; i < XXH32_DIGESTSIZE; i++) { unsigned char c; c = (digest[i] >> 4) & 0xf; c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; c = (digest[i] & 0xf); c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; } return PyUnicode_FromStringAndSize(retbuf, sizeof(retbuf)); } PyDoc_STRVAR( PYXXH32_intdigest_doc, "intdigest() -> int\n\n" "Like digest(), but returns the digest as an integer, which is the integer\n" "returned by xxhash C API"); static PyObject *PYXXH32_intdigest(PYXXH32Object *self) { XXH32_hash_t digest = XXH32_digest(self->xxhash_state); return Py_BuildValue("I", digest); } PyDoc_STRVAR( PYXXH32_copy_doc, "copy() -> xxh32 object\n\n" "Return a copy (``clone'') of the xxh32 object."); static PyObject *PYXXH32_copy(PYXXH32Object *self) { PYXXH32Object *p; if ((p = PyObject_New(PYXXH32Object, &PYXXH32Type)) == NULL) { return NULL; } if ((p->xxhash_state = XXH32_createState()) == NULL) { return NULL; } p->seed = self->seed; XXH32_copyState(p->xxhash_state, self->xxhash_state); return (PyObject *)p; } PyDoc_STRVAR( PYXXH32_reset_doc, "reset()\n\n" "Reset state."); static PyObject *PYXXH32_reset(PYXXH32Object *self) { XXH32_reset(self->xxhash_state, self->seed); Py_RETURN_NONE; } static PyMethodDef PYXXH32_methods[] = { {"update", (PyCFunction)PYXXH32_update, METH_VARARGS, PYXXH32_update_doc}, {"digest", (PyCFunction)PYXXH32_digest, METH_NOARGS, PYXXH32_digest_doc}, {"hexdigest", (PyCFunction)PYXXH32_hexdigest, METH_NOARGS, PYXXH32_hexdigest_doc}, {"intdigest", (PyCFunction)PYXXH32_intdigest, METH_NOARGS, PYXXH32_intdigest_doc}, {"copy", (PyCFunction)PYXXH32_copy, METH_NOARGS, PYXXH32_copy_doc}, {"reset", (PyCFunction)PYXXH32_reset, METH_NOARGS, PYXXH32_reset_doc}, {NULL, NULL, 0, NULL} }; static PyObject *PYXXH32_get_block_size(PYXXH32Object *self, void *closure) { return PyLong_FromLong(XXH32_BLOCKSIZE); } static PyObject * PYXXH32_get_digest_size(PYXXH32Object *self, void *closure) { return PyLong_FromLong(XXH32_DIGESTSIZE); } static PyObject * PYXXH32_get_name(PYXXH32Object *self, void *closure) { return PyUnicode_FromStringAndSize("XXH32", strlen("XXH32")); } static PyObject * PYXXH32_get_seed(PYXXH32Object *self, void *closure) { return Py_BuildValue("I", self->seed); } static PyGetSetDef PYXXH32_getseters[] = { { "digest_size", (getter)PYXXH32_get_digest_size, NULL, "Digest size.", NULL }, { "block_size", (getter)PYXXH32_get_block_size, NULL, "Block size.", NULL }, { "name", (getter)PYXXH32_get_name, NULL, "Name. Always XXH32.", NULL }, { "digestsize", (getter)PYXXH32_get_digest_size, NULL, "Digest size.", NULL }, { "seed", (getter)PYXXH32_get_seed, NULL, "Seed.", NULL }, {NULL} /* Sentinel */ }; PyDoc_STRVAR( PYXXH32Type_doc, "An xxh32 represents the object used to calculate the XXH32 hash of a\n" "string of information.\n" "\n" "Methods:\n" "\n" "update(input) -- updates the current digest with the provided string.\n" "digest() -- return the current digest value\n" "hexdigest() -- return the current digest as a string of hexadecimal digits\n" "intdigest() -- return the current digest as an integer\n" "copy() -- return a copy of the current xxh32 object"); static PyTypeObject PYXXH32Type = { PyVarObject_HEAD_INIT(NULL, 0) "xxhash.xxh32", /* tp_name */ sizeof(PYXXH32Object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)PYXXH32_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ PYXXH32Type_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PYXXH32_methods, /* tp_methods */ 0, /* tp_members */ PYXXH32_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)PYXXH32_init, /* tp_init */ 0, /* tp_alloc */ PYXXH32_new, /* tp_new */ }; /* XXH64 */ typedef struct { PyObject_HEAD /* Type-specific fields go here. */ XXH64_state_t *xxhash_state; XXH64_hash_t seed; } PYXXH64Object; static PyTypeObject PYXXH64Type; static void PYXXH64_dealloc(PYXXH64Object *self) { XXH64_freeState(self->xxhash_state); PyObject_Del(self); } static void PYXXH64_do_update(PYXXH64Object *self, Py_buffer *buf) { Py_BEGIN_ALLOW_THREADS XXH64_update(self->xxhash_state, buf->buf, buf->len); Py_END_ALLOW_THREADS PyBuffer_Release(buf); } static PyObject *PYXXH64_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PYXXH64Object *self; if ((self = PyObject_New(PYXXH64Object, &PYXXH64Type)) == NULL) { return NULL; } if ((self->xxhash_state = XXH64_createState()) == NULL) { return NULL; } return (PyObject *)self; } static int PYXXH64_init(PYXXH64Object *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s*K:__init__", keywords, &buf, &seed)) { return -1; } self->seed = seed; XXH64_reset(self->xxhash_state, seed); if (buf.buf) { PYXXH64_do_update(self, &buf); } return 0; } PyDoc_STRVAR( PYXXH64_update_doc, "update (input)\n\n" "Update the xxh64 object with the string input. Repeated calls are\n" "equivalent to a single call with the concatenation of all the arguments."); static PyObject *PYXXH64_update(PYXXH64Object *self, PyObject *args) { Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTuple(args, "s*:update", &buf)) { return NULL; } PYXXH64_do_update(self, &buf); Py_RETURN_NONE; } PyDoc_STRVAR( PYXXH64_digest_doc, "digest() -> string\n\n" "Return the digest of the strings passed to the update() method so\n" "far. This is a 8-byte string which may contain non-ASCII characters,\n" "including null bytes."); static PyObject *PYXXH64_digest(PYXXH64Object *self) { char retbuf[XXH64_DIGESTSIZE]; XXH64_hash_t intdigest; intdigest = XXH64_digest(self->xxhash_state); XXH64_canonicalFromHash((XXH64_canonical_t *)retbuf, intdigest); return PyBytes_FromStringAndSize(retbuf, sizeof(retbuf)); } PyDoc_STRVAR( PYXXH64_hexdigest_doc, "hexdigest() -> string\n\n" "Like digest(), but returns the digest as a string of hexadecimal digits."); static PyObject *PYXXH64_hexdigest(PYXXH64Object *self) { XXH64_hash_t intdigest; char digest[XXH64_DIGESTSIZE]; char retbuf[XXH64_DIGESTSIZE * 2]; int i, j; intdigest = XXH64_digest(self->xxhash_state); XXH64_canonicalFromHash((XXH64_canonical_t *)digest, intdigest); for (i = j = 0; i < XXH64_DIGESTSIZE; i++) { unsigned char c; c = (digest[i] >> 4) & 0xf; c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; c = (digest[i] & 0xf); c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; } return PyUnicode_FromStringAndSize(retbuf, sizeof(retbuf)); } PyDoc_STRVAR( PYXXH64_intdigest_doc, "intdigest() -> int\n\n" "Like digest(), but returns the digest as an integer, which is the integer\n" "returned by xxhash C API"); static PyObject *PYXXH64_intdigest(PYXXH64Object *self) { XXH64_hash_t digest = XXH64_digest(self->xxhash_state); return Py_BuildValue("K", digest); } PyDoc_STRVAR( PYXXH64_copy_doc, "copy() -> xxh64 object\n\n" "Return a copy (``clone'') of the xxh64 object."); static PyObject *PYXXH64_copy(PYXXH64Object *self) { PYXXH64Object *p; if ((p = PyObject_New(PYXXH64Object, &PYXXH64Type)) == NULL) { return NULL; } if ((p->xxhash_state = XXH64_createState()) == NULL) { return NULL; } p->seed = self->seed; XXH64_copyState(p->xxhash_state, self->xxhash_state); return (PyObject *)p; } PyDoc_STRVAR( PYXXH64_reset_doc, "reset()\n\n" "Reset state."); static PyObject *PYXXH64_reset(PYXXH64Object *self) { XXH64_reset(self->xxhash_state, self->seed); Py_RETURN_NONE; } static PyMethodDef PYXXH64_methods[] = { {"update", (PyCFunction)PYXXH64_update, METH_VARARGS, PYXXH64_update_doc}, {"digest", (PyCFunction)PYXXH64_digest, METH_NOARGS, PYXXH64_digest_doc}, {"hexdigest", (PyCFunction)PYXXH64_hexdigest, METH_NOARGS, PYXXH64_hexdigest_doc}, {"intdigest", (PyCFunction)PYXXH64_intdigest, METH_NOARGS, PYXXH64_intdigest_doc}, {"copy", (PyCFunction)PYXXH64_copy, METH_NOARGS, PYXXH64_copy_doc}, {"reset", (PyCFunction)PYXXH64_reset, METH_NOARGS, PYXXH64_reset_doc}, {NULL, NULL, 0, NULL} }; static PyObject *PYXXH64_get_block_size(PYXXH64Object *self, void *closure) { return PyLong_FromLong(XXH64_BLOCKSIZE); } static PyObject * PYXXH64_get_digest_size(PYXXH64Object *self, void *closure) { return PyLong_FromLong(XXH64_DIGESTSIZE); } static PyObject * PYXXH64_get_name(PYXXH64Object *self, void *closure) { return PyUnicode_FromStringAndSize("XXH64", strlen("XXH64")); } static PyObject * PYXXH64_get_seed(PYXXH64Object *self, void *closure) { return Py_BuildValue("K", self->seed); } static PyGetSetDef PYXXH64_getseters[] = { { "digest_size", (getter)PYXXH64_get_digest_size, NULL, "Digest size.", NULL }, { "block_size", (getter)PYXXH64_get_block_size, NULL, "Block size.", NULL }, { "name", (getter)PYXXH64_get_name, NULL, "Name. Always XXH64.", NULL }, { "digestsize", (getter)PYXXH64_get_digest_size, NULL, "Digest size.", NULL }, { "seed", (getter)PYXXH64_get_seed, NULL, "Seed.", NULL }, {NULL} /* Sentinel */ }; PyDoc_STRVAR( PYXXH64Type_doc, "An xxh64 represents the object used to calculate the XXH64 hash of a\n" "string of information.\n" "\n" "Methods:\n" "\n" "update(input) -- updates the current digest with an additional string\n" "digest() -- return the current digest value\n" "hexdigest() -- return the current digest as a string of hexadecimal digits\n" "intdigest() -- return the current digest as an integer\n" "copy() -- return a copy of the current xxh64 object"); static PyTypeObject PYXXH64Type = { PyVarObject_HEAD_INIT(NULL, 0) "xxhash.xxh64", /* tp_name */ sizeof(PYXXH64Object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)PYXXH64_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ PYXXH64Type_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PYXXH64_methods, /* tp_methods */ 0, /* tp_members */ PYXXH64_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)PYXXH64_init, /* tp_init */ 0, /* tp_alloc */ PYXXH64_new, /* tp_new */ }; /* XXH3_64 */ typedef struct { PyObject_HEAD /* Type-specific fields go here. */ XXH3_state_t *xxhash_state; XXH64_hash_t seed; } PYXXH3_64Object; static PyTypeObject PYXXH3_64Type; static void PYXXH3_64_dealloc(PYXXH3_64Object *self) { XXH3_freeState(self->xxhash_state); PyObject_Del(self); } static void PYXXH3_64_do_update(PYXXH3_64Object *self, Py_buffer *buf) { Py_BEGIN_ALLOW_THREADS XXH3_64bits_update(self->xxhash_state, buf->buf, buf->len); Py_END_ALLOW_THREADS PyBuffer_Release(buf); } static PyObject *PYXXH3_64_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PYXXH3_64Object *self; if ((self = PyObject_New(PYXXH3_64Object, &PYXXH3_64Type)) == NULL) { return NULL; } if ((self->xxhash_state = XXH3_createState()) == NULL) { return NULL; } XXH3_64bits_reset_withSeed(self->xxhash_state, 0); return (PyObject *)self; } static int PYXXH3_64_init(PYXXH3_64Object *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s*K:__init__", keywords, &buf, &seed)) { return -1; } self->seed = seed; XXH3_64bits_reset_withSeed(self->xxhash_state, seed); if (buf.buf) { PYXXH3_64_do_update(self, &buf); } return 0; } PyDoc_STRVAR( PYXXH3_64_update_doc, "update (input)\n\n" "Update the xxh3_64 object with the string input. Repeated calls are\n" "equivalent to a single call with the concatenation of all the arguments."); static PyObject *PYXXH3_64_update(PYXXH3_64Object *self, PyObject *args) { Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTuple(args, "s*:update", &buf)) { return NULL; } PYXXH3_64_do_update(self, &buf); Py_RETURN_NONE; } PyDoc_STRVAR( PYXXH3_64_digest_doc, "digest() -> string\n\n" "Return the digest of the strings passed to the update() method so\n" "far. This is a 8-byte string which may contain non-ASCII characters,\n" "including null bytes."); static PyObject *PYXXH3_64_digest(PYXXH3_64Object *self) { char retbuf[XXH64_DIGESTSIZE]; XXH64_hash_t intdigest; intdigest = XXH3_64bits_digest(self->xxhash_state); XXH64_canonicalFromHash((XXH64_canonical_t *)retbuf, intdigest); return PyBytes_FromStringAndSize(retbuf, sizeof(retbuf)); } PyDoc_STRVAR( PYXXH3_64_hexdigest_doc, "hexdigest() -> string\n\n" "Like digest(), but returns the digest as a string of hexadecimal digits."); static PyObject *PYXXH3_64_hexdigest(PYXXH3_64Object *self) { XXH64_hash_t intdigest; char digest[XXH64_DIGESTSIZE]; char retbuf[XXH64_DIGESTSIZE * 2]; int i, j; intdigest = XXH3_64bits_digest(self->xxhash_state); XXH64_canonicalFromHash((XXH64_canonical_t *)digest, intdigest); for (i = j = 0; i < XXH64_DIGESTSIZE; i++) { unsigned char c; c = (digest[i] >> 4) & 0xf; c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; c = (digest[i] & 0xf); c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; } return PyUnicode_FromStringAndSize(retbuf, sizeof(retbuf)); } PyDoc_STRVAR( PYXXH3_64_intdigest_doc, "intdigest() -> int\n\n" "Like digest(), but returns the digest as an integer, which is the integer\n" "returned by xxhash C API"); static PyObject *PYXXH3_64_intdigest(PYXXH3_64Object *self) { XXH64_hash_t intdigest = XXH3_64bits_digest(self->xxhash_state); return Py_BuildValue("K", intdigest); } PyDoc_STRVAR( PYXXH3_64_copy_doc, "copy() -> xxh64 object\n\n" "Return a copy (``clone'') of the xxh64 object."); static PyObject *PYXXH3_64_copy(PYXXH3_64Object *self) { PYXXH3_64Object *p; if ((p = PyObject_New(PYXXH3_64Object, &PYXXH3_64Type)) == NULL) { return NULL; } if ((p->xxhash_state = XXH3_createState()) == NULL) { return NULL; } p->seed = self->seed; XXH3_copyState(p->xxhash_state, self->xxhash_state); #if XXH_VERSION_NUMBER < 704 // v0.7.3 and earlier have a bug where states reset with a seed // will have a wild pointer to the original state when copied, // causing a use-after-free if the original is freed. if (p->xxhash_state->secret == &self->xxhash_state->customSecret[0]) p->xxhash_state->secret = &p->xxhash_state->customSecret[0]; #endif return (PyObject *)p; } PyDoc_STRVAR( PYXXH3_64_reset_doc, "reset()\n\n" "Reset state."); static PyObject *PYXXH3_64_reset(PYXXH3_64Object *self) { XXH3_64bits_reset_withSeed(self->xxhash_state, self->seed); Py_RETURN_NONE; } static PyMethodDef PYXXH3_64_methods[] = { {"update", (PyCFunction)PYXXH3_64_update, METH_VARARGS, PYXXH3_64_update_doc}, {"digest", (PyCFunction)PYXXH3_64_digest, METH_NOARGS, PYXXH3_64_digest_doc}, {"hexdigest", (PyCFunction)PYXXH3_64_hexdigest, METH_NOARGS, PYXXH3_64_hexdigest_doc}, {"intdigest", (PyCFunction)PYXXH3_64_intdigest, METH_NOARGS, PYXXH3_64_intdigest_doc}, {"copy", (PyCFunction)PYXXH3_64_copy, METH_NOARGS, PYXXH3_64_copy_doc}, {"reset", (PyCFunction)PYXXH3_64_reset, METH_NOARGS, PYXXH3_64_reset_doc}, {NULL, NULL, 0, NULL} }; static PyObject *PYXXH3_64_get_block_size(PYXXH3_64Object *self, void *closure) { return PyLong_FromLong(XXH64_BLOCKSIZE); } static PyObject * PYXXH3_64_get_digest_size(PYXXH3_64Object *self, void *closure) { return PyLong_FromLong(XXH64_DIGESTSIZE); } static PyObject * PYXXH3_64_get_name(PYXXH3_64Object *self, void *closure) { return PyUnicode_FromStringAndSize("XXH3_64", strlen("XXH3_64")); } static PyObject * PYXXH3_64_get_seed(PYXXH3_64Object *self, void *closure) { return Py_BuildValue("K", self->seed); } static PyGetSetDef PYXXH3_64_getseters[] = { { "digest_size", (getter)PYXXH3_64_get_digest_size, NULL, "Digest size.", NULL }, { "block_size", (getter)PYXXH3_64_get_block_size, NULL, "Block size.", NULL }, { "name", (getter)PYXXH3_64_get_name, NULL, "Name. Always XXH3_64.", NULL }, { "digestsize", (getter)PYXXH3_64_get_digest_size, NULL, "Digest size.", NULL }, { "seed", (getter)PYXXH3_64_get_seed, NULL, "Seed.", NULL }, {NULL} /* Sentinel */ }; PyDoc_STRVAR( PYXXH3_64Type_doc, "An xxh3_64 represents the object used to calculate the XXH3_64 hash of a\n" "string of information.\n" "\n" "Methods:\n" "\n" "update(input) -- updates the current digest with an additional string\n" "digest() -- return the current digest value\n" "hexdigest() -- return the current digest as a string of hexadecimal digits\n" "intdigest() -- return the current digest as an integer\n" "copy() -- return a copy of the current xxh64 object"); static PyTypeObject PYXXH3_64Type = { PyVarObject_HEAD_INIT(NULL, 0) "xxhash.xxh3_64", /* tp_name */ sizeof(PYXXH3_64Object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)PYXXH3_64_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ PYXXH3_64Type_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PYXXH3_64_methods, /* tp_methods */ 0, /* tp_members */ PYXXH3_64_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)PYXXH3_64_init, /* tp_init */ 0, /* tp_alloc */ PYXXH3_64_new, /* tp_new */ }; /* XXH3_128 */ typedef struct { PyObject_HEAD /* Type-specific fields go here. */ XXH3_state_t *xxhash_state; XXH64_hash_t seed; } PYXXH3_128Object; static PyTypeObject PYXXH3_128Type; static void PYXXH3_128_dealloc(PYXXH3_128Object *self) { XXH3_freeState(self->xxhash_state); PyObject_Del(self); } static void PYXXH3_128_do_update(PYXXH3_128Object *self, Py_buffer *buf) { Py_BEGIN_ALLOW_THREADS XXH3_128bits_update(self->xxhash_state, buf->buf, buf->len); Py_END_ALLOW_THREADS PyBuffer_Release(buf); } static PyObject *PYXXH3_128_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PYXXH3_128Object *self; if ((self = PyObject_New(PYXXH3_128Object, &PYXXH3_128Type)) == NULL) { return NULL; } if ((self->xxhash_state = XXH3_createState()) == NULL) { return NULL; } self->seed = 0; XXH3_128bits_reset_withSeed(self->xxhash_state, 0); return (PyObject *)self; } static int PYXXH3_128_init(PYXXH3_128Object *self, PyObject *args, PyObject *kwargs) { XXH64_hash_t seed = 0; char *keywords[] = {"input", "seed", NULL}; Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s*K:__init__", keywords, &buf, &seed)) { return -1; } self->seed = seed; XXH3_128bits_reset_withSeed(self->xxhash_state, seed); if (buf.buf) { PYXXH3_128_do_update(self, &buf); } return 0; } PyDoc_STRVAR( PYXXH3_128_update_doc, "update (input)\n\n" "Update the xxh3_128 object with the string input. Repeated calls are\n" "equivalent to a single call with the concatenation of all the arguments."); static PyObject *PYXXH3_128_update(PYXXH3_128Object *self, PyObject *args) { Py_buffer buf; buf.buf = buf.obj = NULL; if (!PyArg_ParseTuple(args, "s*:update", &buf)) { return NULL; } PYXXH3_128_do_update(self, &buf); Py_RETURN_NONE; } PyDoc_STRVAR( PYXXH3_128_digest_doc, "digest() -> string\n\n" "Return the digest of the strings passed to the update() method so\n" "far. This is a 8-byte string which may contain non-ASCII characters,\n" "including null bytes."); static PyObject *PYXXH3_128_digest(PYXXH3_128Object *self) { char retbuf[XXH128_DIGESTSIZE]; XXH128_hash_t intdigest; intdigest = XXH3_128bits_digest(self->xxhash_state); XXH128_canonicalFromHash((XXH128_canonical_t *)retbuf, intdigest); return PyBytes_FromStringAndSize(retbuf, sizeof(retbuf)); } PyDoc_STRVAR( PYXXH3_128_hexdigest_doc, "hexdigest() -> string\n\n" "Like digest(), but returns the digest as a string of hexadecimal digits."); static PyObject *PYXXH3_128_hexdigest(PYXXH3_128Object *self) { XXH128_hash_t intdigest; char digest[XXH128_DIGESTSIZE]; char retbuf[XXH128_DIGESTSIZE * 2]; int i, j; intdigest = XXH3_128bits_digest(self->xxhash_state); XXH128_canonicalFromHash((XXH128_canonical_t *)digest, intdigest); for (i = j = 0; i < XXH128_DIGESTSIZE; i++) { unsigned char c; c = (digest[i] >> 4) & 0xf; c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; c = (digest[i] & 0xf); c = (c > 9) ? c + 'a' - 10 : c + '0'; retbuf[j++] = c; } return PyUnicode_FromStringAndSize(retbuf, sizeof(retbuf)); } PyDoc_STRVAR( PYXXH3_128_intdigest_doc, "intdigest() -> int\n\n" "Like digest(), but returns the digest as an integer, which is the integer\n" "returned by xxhash C API"); static PyObject *PYXXH3_128_intdigest(PYXXH3_128Object *self) { XXH128_hash_t intdigest; PyObject *result, *high, *low, *sixtyfour; intdigest = XXH3_128bits_digest(self->xxhash_state); sixtyfour = PyLong_FromLong(64); low = PyLong_FromUnsignedLongLong(intdigest.low64); high = PyLong_FromUnsignedLongLong(intdigest.high64); result = PyNumber_Lshift(high, sixtyfour); Py_DECREF(high); high = result; result = PyNumber_Add(high, low); Py_DECREF(high); Py_DECREF(low); Py_DECREF(sixtyfour); return result; } PyDoc_STRVAR( PYXXH3_128_copy_doc, "copy() -> xxh3_128 object\n\n" "Return a copy (``clone'') of the xxh3_128 object."); static PyObject *PYXXH3_128_copy(PYXXH3_128Object *self) { PYXXH3_128Object *p; if ((p = PyObject_New(PYXXH3_128Object, &PYXXH3_128Type)) == NULL) { return NULL; } if ((p->xxhash_state = XXH3_createState()) == NULL) { return NULL; } p->seed = self->seed; XXH3_copyState(p->xxhash_state, self->xxhash_state); #if XXH_VERSION_NUMBER < 704 // v0.7.3 and earlier have a bug where states reset with a seed // will have a wild pointer to the original state when copied, // causing a use-after-free if the original is freed. if (p->xxhash_state->secret == &self->xxhash_state->customSecret[0]) p->xxhash_state->secret = &p->xxhash_state->customSecret[0]; #endif return (PyObject *)p; } PyDoc_STRVAR( PYXXH3_128_reset_doc, "reset()\n\n" "Reset state."); static PyObject *PYXXH3_128_reset(PYXXH3_128Object *self) { XXH3_128bits_reset_withSeed(self->xxhash_state, self->seed); Py_RETURN_NONE; } static PyMethodDef PYXXH3_128_methods[] = { {"update", (PyCFunction)PYXXH3_128_update, METH_VARARGS, PYXXH3_128_update_doc}, {"digest", (PyCFunction)PYXXH3_128_digest, METH_NOARGS, PYXXH3_128_digest_doc}, {"hexdigest", (PyCFunction)PYXXH3_128_hexdigest, METH_NOARGS, PYXXH3_128_hexdigest_doc}, {"intdigest", (PyCFunction)PYXXH3_128_intdigest, METH_NOARGS, PYXXH3_128_intdigest_doc}, {"copy", (PyCFunction)PYXXH3_128_copy, METH_NOARGS, PYXXH3_128_copy_doc}, {"reset", (PyCFunction)PYXXH3_128_reset, METH_NOARGS, PYXXH3_128_reset_doc}, {NULL, NULL, 0, NULL} }; static PyObject *PYXXH3_128_get_block_size(PYXXH3_128Object *self, void *closure) { return PyLong_FromLong(XXH128_BLOCKSIZE); } static PyObject * PYXXH3_128_get_digest_size(PYXXH3_128Object *self, void *closure) { return PyLong_FromLong(XXH128_DIGESTSIZE); } static PyObject * PYXXH3_128_get_name(PYXXH3_128Object *self, void *closure) { return PyUnicode_FromStringAndSize("XXH3_128", strlen("XXH3_128")); } static PyObject * PYXXH3_128_get_seed(PYXXH3_128Object *self, void *closure) { return Py_BuildValue("K", self->seed); } static PyGetSetDef PYXXH3_128_getseters[] = { { "digest_size", (getter)PYXXH3_128_get_digest_size, NULL, "Digest size.", NULL }, { "block_size", (getter)PYXXH3_128_get_block_size, NULL, "Block size.", NULL }, { "name", (getter)PYXXH3_128_get_name, NULL, "Name. Always XXH3_128.", NULL }, { "digestsize", (getter)PYXXH3_128_get_digest_size, NULL, "Digest size.", NULL }, { "seed", (getter)PYXXH3_128_get_seed, NULL, "Seed.", NULL }, {NULL} /* Sentinel */ }; PyDoc_STRVAR( PYXXH3_128Type_doc, "An xxh3_128 represents the object used to calculate the XXH3_128 hash of a\n" "string of information.\n" "\n" "Methods:\n" "\n" "update(input) -- updates the current digest with an additional string\n" "digest() -- return the current digest value\n" "hexdigest() -- return the current digest as a string of hexadecimal digits\n" "intdigest() -- return the current digest as an integer\n" "copy() -- return a copy of the current xxh3_128 object"); static PyTypeObject PYXXH3_128Type = { PyVarObject_HEAD_INIT(NULL, 0) "xxhash.xxh3_128", /* tp_name */ sizeof(PYXXH3_128Object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)PYXXH3_128_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ PYXXH3_128Type_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PYXXH3_128_methods, /* tp_methods */ 0, /* tp_members */ PYXXH3_128_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)PYXXH3_128_init, /* tp_init */ 0, /* tp_alloc */ PYXXH3_128_new, /* tp_new */ }; /***************************************************************************** * Module Init **************************************************************** ****************************************************************************/ /* ref: https://docs.python.org/2/howto/cporting.html */ static PyMethodDef methods[] = { {"xxh32_digest", (PyCFunction)xxh32_digest, METH_VARARGS | METH_KEYWORDS, "xxh32_digest"}, {"xxh32_intdigest", (PyCFunction)xxh32_intdigest, METH_VARARGS | METH_KEYWORDS, "xxh32_intdigest"}, {"xxh32_hexdigest", (PyCFunction)xxh32_hexdigest, METH_VARARGS | METH_KEYWORDS, "xxh32_hexdigest"}, {"xxh64_digest", (PyCFunction)xxh64_digest, METH_VARARGS | METH_KEYWORDS, "xxh64_digest"}, {"xxh64_intdigest", (PyCFunction)xxh64_intdigest, METH_VARARGS | METH_KEYWORDS, "xxh64_intdigest"}, {"xxh64_hexdigest", (PyCFunction)xxh64_hexdigest, METH_VARARGS | METH_KEYWORDS, "xxh64_hexdigest"}, {"xxh3_64_digest", (PyCFunction)xxh3_64_digest, METH_VARARGS | METH_KEYWORDS, "xxh3_64_digest"}, {"xxh3_64_intdigest", (PyCFunction)xxh3_64_intdigest, METH_VARARGS | METH_KEYWORDS, "xxh3_64_intdigest"}, {"xxh3_64_hexdigest", (PyCFunction)xxh3_64_hexdigest, METH_VARARGS | METH_KEYWORDS, "xxh3_64_hexdigest"}, {"xxh3_128_digest", (PyCFunction)xxh3_128_digest, METH_VARARGS | METH_KEYWORDS, "xxh3_128_digest"}, {"xxh3_128_intdigest", (PyCFunction)xxh3_128_intdigest, METH_VARARGS | METH_KEYWORDS, "xxh3_128_intdigest"}, {"xxh3_128_hexdigest", (PyCFunction)xxh3_128_hexdigest, METH_VARARGS | METH_KEYWORDS, "xxh3_128_hexdigest"}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_xxhash", NULL, -1, methods, NULL, NULL, NULL, NULL }; #define INITERROR return NULL PyObject *PyInit__xxhash(void) { PyObject *module; module = PyModule_Create(&moduledef); if (module == NULL) { INITERROR; } /* xxh32 */ if (PyType_Ready(&PYXXH32Type) < 0) { INITERROR; } Py_INCREF(&PYXXH32Type); PyModule_AddObject(module, "xxh32", (PyObject *)&PYXXH32Type); /* xxh64 */ if (PyType_Ready(&PYXXH64Type) < 0) { INITERROR; } Py_INCREF(&PYXXH64Type); PyModule_AddObject(module, "xxh64", (PyObject *)&PYXXH64Type); /* xxh3_64 */ if (PyType_Ready(&PYXXH3_64Type) < 0) { INITERROR; } Py_INCREF(&PYXXH3_64Type); PyModule_AddObject(module, "xxh3_64", (PyObject *)&PYXXH3_64Type); /* xxh3_128 */ if (PyType_Ready(&PYXXH3_128Type) < 0) { INITERROR; } Py_INCREF(&PYXXH3_128Type); PyModule_AddObject(module, "xxh3_128", (PyObject *)&PYXXH3_128Type); /* version */ PyModule_AddStringConstant(module, "XXHASH_VERSION", VALUE_TO_STRING(XXHASH_VERSION)); return module; } python-xxhash-3.2.0/tests/000077500000000000000000000000001435305667200155135ustar00rootroot00000000000000python-xxhash-3.2.0/tests/__init__.py000066400000000000000000000000001435305667200176120ustar00rootroot00000000000000python-xxhash-3.2.0/tests/test.py000066400000000000000000000034631435305667200170520ustar00rootroot00000000000000import array import os import unittest import random import struct import sys from typing import Union, List, TYPE_CHECKING import xxhash if TYPE_CHECKING: InputType = Union[str, bytes, bytearray, memoryview, array.ArrayType[int]] else: InputType = None def getrefcount(obj): if hasattr(sys, "getrefcount"): return sys.getrefcount(obj) else: # Non-CPython implementation return 0 class TestXXH(unittest.TestCase): def test_version(self): self.assertTrue(xxhash.VERSION) self.assertTrue(xxhash.XXHASH_VERSION) def test_buffer_types(self): # Various buffer-like objects are accepted, and they give similar values args: List[InputType] = [ b'ab\x00c', bytearray(b'ab\x00c'), array.array('b', b'ab\x00c'), ] # An array object with non-1 itemsize a = array.array('i', struct.unpack('i', b'ab\x00c')) assert a.itemsize == 4 args.append(a) # A memoryview, where supported if sys.version_info >= (2, 7): args.append(memoryview(b'ab\x00c')) for func in [xxhash.xxh32, xxhash.xxh64, xxhash.xxh3_64, xxhash.xxh3_128]: old_refcounts = list(map(getrefcount, args)) # With constructor values = set(func(arg).hexdigest() for arg in args) self.assertEqual(len(values), 1, values) # With update() values = set() for arg in args: x = func() x.update(arg) values.add(x.hexdigest()) self.assertEqual(len(values), 1, values) # No reference leak in CPython extension del arg self.assertEqual(list(map(getrefcount, args)), old_refcounts) if __name__ == '__main__': unittest.main() python-xxhash-3.2.0/tests/test_algorithms_available.py000066400000000000000000000012161435305667200232750ustar00rootroot00000000000000import xxhash import unittest class TestAlgorithmExists(unittest.TestCase): def test_xxh32(self): xxhash.xxh32 assert "xxh32" in xxhash.algorithms_available def test_xxh64(self): xxhash.xxh64 assert "xxh64" in xxhash.algorithms_available def test_xxh3_64(self): xxhash.xxh3_64 assert "xxh3_64" in xxhash.algorithms_available def test_xxh128(self): xxhash.xxh128 assert "xxh128" in xxhash.algorithms_available def test_xxh3_128(self): xxhash.xxh3_128 assert "xxh3_128" in xxhash.algorithms_available if __name__ == '__main__': unittest.main() python-xxhash-3.2.0/tests/test_name.py000066400000000000000000000010701435305667200200420ustar00rootroot00000000000000import os import unittest import random import xxhash class TestName(unittest.TestCase): def test_xxh32(self): self.assertEqual(xxhash.xxh32().name, "XXH32") def test_xxh64(self): self.assertEqual(xxhash.xxh64().name, "XXH64") def test_xxh3_64(self): self.assertEqual(xxhash.xxh3_64().name, "XXH3_64") def test_xxh128(self): self.assertEqual(xxhash.xxh128().name, "XXH3_128") def test_xxh3_128(self): self.assertEqual(xxhash.xxh3_128().name, "XXH3_128") if __name__ == '__main__': unittest.main() python-xxhash-3.2.0/tests/test_xxh32.py000066400000000000000000000132271435305667200201050ustar00rootroot00000000000000import os import unittest import random import xxhash class TestXXH(unittest.TestCase): def test_xxh32(self): self.assertEqual(xxhash.xxh32('a').intdigest(), 1426945110) self.assertEqual(xxhash.xxh32('a', 0).intdigest(), 1426945110) self.assertEqual(xxhash.xxh32('a', 1).intdigest(), 4111757423) self.assertEqual(xxhash.xxh32('a', 2**32-1).intdigest(), 3443684653) def test_xxh32_intdigest(self): self.assertEqual(xxhash.xxh32_intdigest('a'), 1426945110) self.assertEqual(xxhash.xxh32_intdigest('a', 0), 1426945110) self.assertEqual(xxhash.xxh32_intdigest('a', 1), 4111757423) self.assertEqual(xxhash.xxh32_intdigest('a', 2**32-1), 3443684653) def test_xxh32_update(self): x = xxhash.xxh32() x.update('a') self.assertEqual(xxhash.xxh32('a').digest(), x.digest()) self.assertEqual(xxhash.xxh32_digest('a'), x.digest()) x.update('b') self.assertEqual(xxhash.xxh32('ab').digest(), x.digest()) self.assertEqual(xxhash.xxh32_digest('ab'), x.digest()) x.update('c') self.assertEqual(xxhash.xxh32('abc').digest(), x.digest()) self.assertEqual(xxhash.xxh32_digest('abc'), x.digest()) seed = random.randint(0, 2**32) x = xxhash.xxh32(seed=seed) x.update('a') self.assertEqual(xxhash.xxh32('a', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh32_digest('a', seed), x.digest()) x.update('b') self.assertEqual(xxhash.xxh32('ab', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh32_digest('ab', seed), x.digest()) x.update('c') self.assertEqual(xxhash.xxh32('abc', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh32_digest('abc', seed), x.digest()) def test_xxh32_reset(self): x = xxhash.xxh32() h = x.intdigest() for i in range(10, 50): x.update(os.urandom(i)) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh32_copy(self): a = xxhash.xxh32() a.update('xxhash') b = a.copy() self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) b.update('xxhash') self.assertNotEqual(a.digest(), b.digest()) self.assertNotEqual(a.intdigest(), b.intdigest()) self.assertNotEqual(a.hexdigest(), b.hexdigest()) a.update('xxhash') self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) def test_xxh32_overflow(self): s = 'I want an unsigned 32-bit seed!' a = xxhash.xxh32(s, seed=0) b = xxhash.xxh32(s, seed=2**32) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh32_intdigest(s, seed=0)) self.assertEqual(a.intdigest(), xxhash.xxh32_intdigest(s, seed=2**32)) self.assertEqual(a.digest(), xxhash.xxh32_digest(s, seed=0)) self.assertEqual(a.digest(), xxhash.xxh32_digest(s, seed=2**32)) self.assertEqual(a.hexdigest(), xxhash.xxh32_hexdigest(s, seed=0)) self.assertEqual(a.hexdigest(), xxhash.xxh32_hexdigest(s, seed=2**32)) a = xxhash.xxh32(s, seed=1) b = xxhash.xxh32(s, seed=2**32+1) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh32_intdigest(s, seed=1)) self.assertEqual(a.intdigest(), xxhash.xxh32_intdigest(s, seed=2**32+1)) self.assertEqual(a.digest(), xxhash.xxh32_digest(s, seed=1)) self.assertEqual(a.digest(), xxhash.xxh32_digest(s, seed=2**32+1)) self.assertEqual(a.hexdigest(), xxhash.xxh32_hexdigest(s, seed=1)) self.assertEqual(a.hexdigest(), xxhash.xxh32_hexdigest(s, seed=2**32+1)) a = xxhash.xxh32(s, seed=2**33-1) b = xxhash.xxh32(s, seed=2**34-1) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh32_intdigest(s, seed=2**33-1)) self.assertEqual(a.intdigest(), xxhash.xxh32_intdigest(s, seed=2**34-1)) self.assertEqual(a.digest(), xxhash.xxh32_digest(s, seed=2**33-1)) self.assertEqual(a.digest(), xxhash.xxh32_digest(s, seed=2**34-1)) self.assertEqual(a.hexdigest(), xxhash.xxh32_hexdigest(s, seed=2**33-1)) self.assertEqual(a.hexdigest(), xxhash.xxh32_hexdigest(s, seed=2**34-1)) a = xxhash.xxh32(s, seed=2**65-1) b = xxhash.xxh32(s, seed=2**66-1) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh32_intdigest(s, seed=2**65-1)) self.assertEqual(a.intdigest(), xxhash.xxh32_intdigest(s, seed=2**66-1)) self.assertEqual(a.digest(), xxhash.xxh32_digest(s, seed=2**65-1)) self.assertEqual(a.digest(), xxhash.xxh32_digest(s, seed=2**66-1)) self.assertEqual(a.hexdigest(), xxhash.xxh32_hexdigest(s, seed=2**65-1)) self.assertEqual(a.hexdigest(), xxhash.xxh32_hexdigest(s, seed=2**66-1)) if __name__ == '__main__': unittest.main() python-xxhash-3.2.0/tests/test_xxh3_128.py000066400000000000000000000146251435305667200204200ustar00rootroot00000000000000import os import unittest import random import xxhash class TestXXH(unittest.TestCase): def test_xxh3_128(self): self.assertEqual(xxhash.xxh3_128('a').intdigest(), 225219434562328483135862406050043285023) self.assertEqual(xxhash.xxh3_128('a', 0).intdigest(), 225219434562328483135862406050043285023) self.assertEqual(xxhash.xxh3_128('a', 1).intdigest(), 337425133163118381928709500770786453280) self.assertEqual(xxhash.xxh3_128('a', 2**64-1).intdigest(), 198297796855923085494266857744987477846) def test_xxh3_128_intdigest(self): self.assertEqual(xxhash.xxh3_128_intdigest('a'), 225219434562328483135862406050043285023) self.assertEqual(xxhash.xxh3_128_intdigest('a', 0), 225219434562328483135862406050043285023) self.assertEqual(xxhash.xxh3_128_intdigest('a', 1), 337425133163118381928709500770786453280) self.assertEqual(xxhash.xxh3_128_intdigest('a', 2**64-1), 198297796855923085494266857744987477846) def test_xxh3_128_update(self): x = xxhash.xxh3_128() x.update('a') self.assertEqual(xxhash.xxh3_128('a').digest(), x.digest()) self.assertEqual(xxhash.xxh3_128_digest('a'), x.digest()) x.update('b') self.assertEqual(xxhash.xxh3_128('ab').digest(), x.digest()) self.assertEqual(xxhash.xxh3_128_digest('ab'), x.digest()) x.update('c') self.assertEqual(xxhash.xxh3_128('abc').digest(), x.digest()) self.assertEqual(xxhash.xxh3_128_digest('abc'), x.digest()) seed = random.randint(0, 2**64) x = xxhash.xxh3_128(seed=seed) x.update('a') self.assertEqual(xxhash.xxh3_128('a', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh3_128_digest('a', seed), x.digest()) x.update('b') self.assertEqual(xxhash.xxh3_128('ab', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh3_128_digest('ab', seed), x.digest()) x.update('c') self.assertEqual(xxhash.xxh3_128('abc', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh3_128_digest('abc', seed), x.digest()) def test_xxh3_128_reset(self): x = xxhash.xxh3_128() h = x.intdigest() x.update('x' * 10240) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh3_128_seed_reset(self): seed = random.randint(0, 2**64-1) x = xxhash.xxh3_128(seed=seed) h = x.intdigest() x.update('x' * 10240) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh3_128_reset_more(self): x = xxhash.xxh3_128() h = x.intdigest() for i in range(random.randint(100, 200)): x.reset() for i in range(10, 1000): x.update(os.urandom(i)) x.reset() self.assertEqual(h, x.intdigest()) for i in range(10, 1000): x.update(os.urandom(100)) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh3_128_seed_reset_more(self): seed = random.randint(0, 2**64-1) x = xxhash.xxh3_128(seed=seed) h = x.intdigest() for i in range(random.randint(100, 200)): x.reset() for i in range(10, 1000): x.update(os.urandom(i)) x.reset() self.assertEqual(h, x.intdigest()) for i in range(10, 1000): x.update(os.urandom(100)) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh3_128_copy(self): a = xxhash.xxh3_128() a.update('xxhash') b = a.copy() self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) b.update('xxhash') self.assertNotEqual(a.digest(), b.digest()) self.assertNotEqual(a.intdigest(), b.intdigest()) self.assertNotEqual(a.hexdigest(), b.hexdigest()) a.update('xxhash') self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) def test_xxh3_128_overflow(self): s = 'I want an unsigned 64-bit seed!' a = xxhash.xxh3_128(s, seed=0) b = xxhash.xxh3_128(s, seed=2**64) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh3_128_intdigest(s, seed=0)) self.assertEqual(a.intdigest(), xxhash.xxh3_128_intdigest(s, seed=2**64)) self.assertEqual(a.digest(), xxhash.xxh3_128_digest(s, seed=0)) self.assertEqual(a.digest(), xxhash.xxh3_128_digest(s, seed=2**64)) self.assertEqual(a.hexdigest(), xxhash.xxh3_128_hexdigest(s, seed=0)) self.assertEqual(a.hexdigest(), xxhash.xxh3_128_hexdigest(s, seed=2**64)) a = xxhash.xxh3_128(s, seed=1) b = xxhash.xxh3_128(s, seed=2**64+1) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh3_128_intdigest(s, seed=1)) self.assertEqual(a.intdigest(), xxhash.xxh3_128_intdigest(s, seed=2**64+1)) self.assertEqual(a.digest(), xxhash.xxh3_128_digest(s, seed=1)) self.assertEqual(a.digest(), xxhash.xxh3_128_digest(s, seed=2**64+1)) self.assertEqual(a.hexdigest(), xxhash.xxh3_128_hexdigest(s, seed=1)) self.assertEqual(a.hexdigest(), xxhash.xxh3_128_hexdigest(s, seed=2**64+1)) a = xxhash.xxh3_128(s, seed=2**65-1) b = xxhash.xxh3_128(s, seed=2**66-1) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh3_128_intdigest(s, seed=2**65-1)) self.assertEqual(a.intdigest(), xxhash.xxh3_128_intdigest(s, seed=2**66-1)) self.assertEqual(a.digest(), xxhash.xxh3_128_digest(s, seed=2**65-1)) self.assertEqual(a.digest(), xxhash.xxh3_128_digest(s, seed=2**66-1)) self.assertEqual(a.hexdigest(), xxhash.xxh3_128_hexdigest(s, seed=2**65-1)) self.assertEqual(a.hexdigest(), xxhash.xxh3_128_hexdigest(s, seed=2**66-1)) if __name__ == '__main__': unittest.main() python-xxhash-3.2.0/tests/test_xxh3_64.py000066400000000000000000000145111435305667200203310ustar00rootroot00000000000000from __future__ import print_function import os import sys import unittest import random import xxhash class TestXXH(unittest.TestCase): def test_xxh3_64(self): self.assertEqual(xxhash.xxh3_64('a').intdigest(), 16629034431890738719) self.assertEqual(xxhash.xxh3_64('a', 0).intdigest(), 16629034431890738719) self.assertEqual(xxhash.xxh3_64('a', 1).intdigest(), 15201566949650179872) self.assertEqual(xxhash.xxh3_64('a', 2**64-1).intdigest(), 4875116479388997462) def test_xxh3_64_intdigest(self): self.assertEqual(xxhash.xxh3_64_intdigest('a'), 16629034431890738719) self.assertEqual(xxhash.xxh3_64_intdigest('a', 0), 16629034431890738719) self.assertEqual(xxhash.xxh3_64_intdigest('a', 1), 15201566949650179872) self.assertEqual(xxhash.xxh3_64_intdigest('a', 2**64-1), 4875116479388997462) def test_xxh3_64_update(self): x = xxhash.xxh3_64() x.update('a') self.assertEqual(xxhash.xxh3_64('a').digest(), x.digest()) self.assertEqual(xxhash.xxh3_64_digest('a'), x.digest()) x.update('b') self.assertEqual(xxhash.xxh3_64('ab').digest(), x.digest()) self.assertEqual(xxhash.xxh3_64_digest('ab'), x.digest()) x.update('c') self.assertEqual(xxhash.xxh3_64('abc').digest(), x.digest()) self.assertEqual(xxhash.xxh3_64_digest('abc'), x.digest()) seed = random.randint(0, 2**64) x = xxhash.xxh3_64(seed=seed) x.update('a') self.assertEqual(xxhash.xxh3_64('a', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh3_64_digest('a', seed), x.digest()) x.update('b') self.assertEqual(xxhash.xxh3_64('ab', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh3_64_digest('ab', seed), x.digest()) x.update('c') self.assertEqual(xxhash.xxh3_64('abc', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh3_64_digest('abc', seed), x.digest()) def test_xxh3_64_reset(self): x = xxhash.xxh3_64() h = x.intdigest() x.update('x' * 10240) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh3_64_seed_reset(self): seed = random.randint(0, 2**64-1) x = xxhash.xxh3_64(seed=seed) h = x.intdigest() x.update('x' * 10240) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh3_64_reset_more(self): x = xxhash.xxh3_64() h = x.intdigest() for i in range(random.randint(100, 200)): x.reset() self.assertEqual(h, x.intdigest()) for i in range(10, 1000): x.update(os.urandom(i)) x.reset() self.assertEqual(h, x.intdigest()) for i in range(10, 1000): x.update(os.urandom(100)) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh3_64_seed_reset_more(self): seed = random.randint(0, 2**64-1) x = xxhash.xxh3_64(seed=seed) h = x.intdigest() for i in range(random.randint(100, 200)): x.reset() self.assertEqual(h, x.intdigest()) for i in range(10, 1000): x.update(os.urandom(i)) x.reset() self.assertEqual(h, x.intdigest()) for i in range(10, 1000): x.update(os.urandom(100)) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh3_64_copy(self): a = xxhash.xxh3_64() a.update('xxhash') b = a.copy() self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) b.update('xxhash') self.assertNotEqual(a.digest(), b.digest()) self.assertNotEqual(a.intdigest(), b.intdigest()) self.assertNotEqual(a.hexdigest(), b.hexdigest()) a.update('xxhash') self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) def test_xxh3_64_overflow(self): s = 'I want an unsigned 64-bit seed!' a = xxhash.xxh3_64(s, seed=0) b = xxhash.xxh3_64(s, seed=2**64) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh3_64_intdigest(s, seed=0)) self.assertEqual(a.intdigest(), xxhash.xxh3_64_intdigest(s, seed=2**64)) self.assertEqual(a.digest(), xxhash.xxh3_64_digest(s, seed=0)) self.assertEqual(a.digest(), xxhash.xxh3_64_digest(s, seed=2**64)) self.assertEqual(a.hexdigest(), xxhash.xxh3_64_hexdigest(s, seed=0)) self.assertEqual(a.hexdigest(), xxhash.xxh3_64_hexdigest(s, seed=2**64)) a = xxhash.xxh3_64(s, seed=1) b = xxhash.xxh3_64(s, seed=2**64+1) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh3_64_intdigest(s, seed=1)) self.assertEqual(a.intdigest(), xxhash.xxh3_64_intdigest(s, seed=2**64+1)) self.assertEqual(a.digest(), xxhash.xxh3_64_digest(s, seed=1)) self.assertEqual(a.digest(), xxhash.xxh3_64_digest(s, seed=2**64+1)) self.assertEqual(a.hexdigest(), xxhash.xxh3_64_hexdigest(s, seed=1)) self.assertEqual(a.hexdigest(), xxhash.xxh3_64_hexdigest(s, seed=2**64+1)) a = xxhash.xxh3_64(s, seed=2**65-1) b = xxhash.xxh3_64(s, seed=2**66-1) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh3_64_intdigest(s, seed=2**65-1)) self.assertEqual(a.intdigest(), xxhash.xxh3_64_intdigest(s, seed=2**66-1)) self.assertEqual(a.digest(), xxhash.xxh3_64_digest(s, seed=2**65-1)) self.assertEqual(a.digest(), xxhash.xxh3_64_digest(s, seed=2**66-1)) self.assertEqual(a.hexdigest(), xxhash.xxh3_64_hexdigest(s, seed=2**65-1)) self.assertEqual(a.hexdigest(), xxhash.xxh3_64_hexdigest(s, seed=2**66-1)) if __name__ == '__main__': unittest.main() python-xxhash-3.2.0/tests/test_xxh64.py000066400000000000000000000117551435305667200201160ustar00rootroot00000000000000import os import unittest import random import xxhash class TestXXH(unittest.TestCase): def test_xxh64(self): self.assertEqual(xxhash.xxh64('a').intdigest(), 15154266338359012955) self.assertEqual(xxhash.xxh64('a', 0).intdigest(), 15154266338359012955) self.assertEqual(xxhash.xxh64('a', 1).intdigest(), 16051599287423682246) self.assertEqual(xxhash.xxh64('a', 2**64-1).intdigest(), 6972758980737027682) def test_xxh64_intdigest(self): self.assertEqual(xxhash.xxh64_intdigest('a'), 15154266338359012955) self.assertEqual(xxhash.xxh64_intdigest('a', 0), 15154266338359012955) self.assertEqual(xxhash.xxh64_intdigest('a', 1), 16051599287423682246) self.assertEqual(xxhash.xxh64_intdigest('a', 2**64-1), 6972758980737027682) def test_xxh64_update(self): x = xxhash.xxh64() x.update('a') self.assertEqual(xxhash.xxh64('a').digest(), x.digest()) self.assertEqual(xxhash.xxh64_digest('a'), x.digest()) x.update('b') self.assertEqual(xxhash.xxh64('ab').digest(), x.digest()) self.assertEqual(xxhash.xxh64_digest('ab'), x.digest()) x.update('c') self.assertEqual(xxhash.xxh64('abc').digest(), x.digest()) self.assertEqual(xxhash.xxh64_digest('abc'), x.digest()) seed = random.randint(0, 2**64) x = xxhash.xxh64(seed=seed) x.update('a') self.assertEqual(xxhash.xxh64('a', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh64_digest('a', seed), x.digest()) x.update('b') self.assertEqual(xxhash.xxh64('ab', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh64_digest('ab', seed), x.digest()) x.update('c') self.assertEqual(xxhash.xxh64('abc', seed).digest(), x.digest()) self.assertEqual(xxhash.xxh64_digest('abc', seed), x.digest()) def test_xxh64_reset(self): x = xxhash.xxh64() h = x.intdigest() for i in range(10, 50): x.update(os.urandom(i)) x.reset() self.assertEqual(h, x.intdigest()) def test_xxh64_copy(self): a = xxhash.xxh64() a.update('xxhash') b = a.copy() self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) b.update('xxhash') self.assertNotEqual(a.digest(), b.digest()) self.assertNotEqual(a.intdigest(), b.intdigest()) self.assertNotEqual(a.hexdigest(), b.hexdigest()) a.update('xxhash') self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) def test_xxh64_overflow(self): s = 'I want an unsigned 64-bit seed!' a = xxhash.xxh64(s, seed=0) b = xxhash.xxh64(s, seed=2**64) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh64_intdigest(s, seed=0)) self.assertEqual(a.intdigest(), xxhash.xxh64_intdigest(s, seed=2**64)) self.assertEqual(a.digest(), xxhash.xxh64_digest(s, seed=0)) self.assertEqual(a.digest(), xxhash.xxh64_digest(s, seed=2**64)) self.assertEqual(a.hexdigest(), xxhash.xxh64_hexdigest(s, seed=0)) self.assertEqual(a.hexdigest(), xxhash.xxh64_hexdigest(s, seed=2**64)) a = xxhash.xxh64(s, seed=1) b = xxhash.xxh64(s, seed=2**64+1) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh64_intdigest(s, seed=1)) self.assertEqual(a.intdigest(), xxhash.xxh64_intdigest(s, seed=2**64+1)) self.assertEqual(a.digest(), xxhash.xxh64_digest(s, seed=1)) self.assertEqual(a.digest(), xxhash.xxh64_digest(s, seed=2**64+1)) self.assertEqual(a.hexdigest(), xxhash.xxh64_hexdigest(s, seed=1)) self.assertEqual(a.hexdigest(), xxhash.xxh64_hexdigest(s, seed=2**64+1)) a = xxhash.xxh64(s, seed=2**65-1) b = xxhash.xxh64(s, seed=2**66-1) self.assertEqual(a.seed, b.seed) self.assertEqual(a.intdigest(), b.intdigest()) self.assertEqual(a.hexdigest(), b.hexdigest()) self.assertEqual(a.digest(), b.digest()) self.assertEqual(a.intdigest(), xxhash.xxh64_intdigest(s, seed=2**65-1)) self.assertEqual(a.intdigest(), xxhash.xxh64_intdigest(s, seed=2**66-1)) self.assertEqual(a.digest(), xxhash.xxh64_digest(s, seed=2**65-1)) self.assertEqual(a.digest(), xxhash.xxh64_digest(s, seed=2**66-1)) self.assertEqual(a.hexdigest(), xxhash.xxh64_hexdigest(s, seed=2**65-1)) self.assertEqual(a.hexdigest(), xxhash.xxh64_hexdigest(s, seed=2**66-1)) if __name__ == '__main__': unittest.main() python-xxhash-3.2.0/typecheck.sh000066400000000000000000000000571435305667200166660ustar00rootroot00000000000000#!/bin/bash pipenv run python -m mypy tests/* python-xxhash-3.2.0/xxhash/000077500000000000000000000000001435305667200156545ustar00rootroot00000000000000python-xxhash-3.2.0/xxhash/__init__.py000066400000000000000000000021731435305667200177700ustar00rootroot00000000000000from ._xxhash import ( xxh32, xxh32_digest, xxh32_intdigest, xxh32_hexdigest, xxh64, xxh64_digest, xxh64_intdigest, xxh64_hexdigest, xxh3_64, xxh3_64_digest, xxh3_64_intdigest, xxh3_64_hexdigest, xxh3_128, xxh3_128_digest, xxh3_128_intdigest, xxh3_128_hexdigest, XXHASH_VERSION, ) from .version import VERSION, VERSION_TUPLE xxh128 = xxh3_128 xxh128_hexdigest = xxh3_128_hexdigest xxh128_intdigest = xxh3_128_intdigest xxh128_digest = xxh3_128_digest algorithms_available = set([ "xxh32", "xxh64", "xxh3_64", "xxh128", "xxh3_128", ]) __all__ = [ "xxh32", "xxh32_digest", "xxh32_intdigest", "xxh32_hexdigest", "xxh64", "xxh64_digest", "xxh64_intdigest", "xxh64_hexdigest", "xxh3_64", "xxh3_64_digest", "xxh3_64_intdigest", "xxh3_64_hexdigest", "xxh3_128", "xxh3_128_digest", "xxh3_128_intdigest", "xxh3_128_hexdigest", "xxh128", "xxh128_digest", "xxh128_intdigest", "xxh128_hexdigest", "VERSION", "VERSION_TUPLE", "XXHASH_VERSION", "algorithms_available", ] python-xxhash-3.2.0/xxhash/__init__.pyi000066400000000000000000000033721435305667200201430ustar00rootroot00000000000000import array from typing import Union from typing_extensions import final _InputType = Union[str, bytes, bytearray, memoryview, array.ArrayType[int]] VERSION: str XXHASH_VERSION: str VERSION_TUPLE: tuple[int, ...] algorithms_available: set[str] class _Hasher: def __init__(self, input: _InputType = ..., seed: int = ...) -> None: ... def update(self, input: _InputType) -> None: ... def digest(self) -> bytes: ... def hexdigest(self) -> str: ... def intdigest(self) -> int: ... def copy(self) -> _Hasher: ... def reset(self) -> None: ... @property def digestsize(self) -> int: ... @property def digest_size(self) -> int: ... @property def block_size(self) -> int: ... @property def name(self) -> str: ... @property def seed(self) -> int: ... @final class xxh32(_Hasher): ... @final class xxh3_64(_Hasher): ... @final class xxh3_128(_Hasher): ... xxh64 = xxh3_64 xxh128 = xxh3_128 def xxh32_digest(args: _InputType, seed: int = ...) -> bytes: ... def xxh32_hexdigest(args: _InputType, seed: int = ...) -> str: ... def xxh32_intdigest(args: _InputType, seed: int = ...) -> int: ... def xxh3_64_digest(args: _InputType, seed: int = ...) -> bytes: ... def xxh3_64_hexdigest(args: _InputType, seed: int = ...) -> str: ... def xxh3_64_intdigest(args: _InputType, seed: int = ...) -> int: ... def xxh3_128_digest(args: _InputType, seed: int = ...) -> bytes: ... def xxh3_128_hexdigest(args: _InputType, seed: int = ...) -> str: ... def xxh3_128_intdigest(args: _InputType, seed: int = ...) -> int: ... xxh64_digest = xxh3_64_digest xxh64_hexdigest = xxh3_64_hexdigest xxh64_intdigest = xxh3_64_intdigest xxh128_digest = xxh3_128_digest xxh128_hexdigest = xxh3_128_hexdigest xxh128_intdigest = xxh3_128_intdigest python-xxhash-3.2.0/xxhash/py.typed000066400000000000000000000000001435305667200173410ustar00rootroot00000000000000