pax_global_header00006660000000000000000000000064151150075520014513gustar00rootroot0000000000000052 comment=2632d3d19a29feeefd0f28dcdd94e10283d88364 pybase64-1.4.3/000077500000000000000000000000001511500755200131555ustar00rootroot00000000000000pybase64-1.4.3/.github/000077500000000000000000000000001511500755200145155ustar00rootroot00000000000000pybase64-1.4.3/.github/dependabot.yml000066400000000000000000000013671511500755200173540ustar00rootroot00000000000000# To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: # Maintain dependencies for python - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" # Maintain dependencies for git submodule (base64) - package-ecosystem: "gitsubmodule" directory: "/" schedule: interval: "daily" # Maintain dependencies for GitHub Actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" pybase64-1.4.3/.github/workflows/000077500000000000000000000000001511500755200165525ustar00rootroot00000000000000pybase64-1.4.3/.github/workflows/benchmark.yml000066400000000000000000000025711511500755200212340ustar00rootroot00000000000000name: Benchmark on: push: branches-ignore: - "dependabot/**" - "pre-commit-ci-update-config" pull_request: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: contents: read jobs: benchmark: name: Benchmark ${{ matrix.archs }} ${{ matrix.build }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-22.04] archs: ["x86_64"] build: ["manylinux"] steps: - name: Set git to use LF run: | git config --global core.autocrlf false git config --global core.eol lf - uses: actions/checkout@v6 with: submodules: recursive persist-credentials: false - name: Build wheel uses: pypa/cibuildwheel@v3.3.0 env: CIBW_ARCHS: "${{ matrix.archs }}" CIBW_BUILD: "cp312-${{ matrix.build }}*" - uses: wntrblm/nox@2025.11.12 name: Install Nox with: python-versions: "3.12" - name: Install dependencies run: nox -s benchmark --install-only -- --wheel wheelhouse/*.whl - name: Run benchmark uses: CodSpeedHQ/action@v4 with: mode: instrumentation run: nox -s benchmark --reuse-existing-virtualenvs --no-install -- -v pybase64-1.4.3/.github/workflows/build-upload.yml000066400000000000000000000164001511500755200216570ustar00rootroot00000000000000name: Build and upload to PyPI on: push: tags: - '**' branches-ignore: - "dependabot/**" - "pre-commit-ci-update-config" pull_request: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: {} jobs: lint: name: Lint permissions: contents: read runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v6 with: persist-credentials: false - uses: actions/setup-python@v6 with: python-version: "3.10" - uses: pre-commit/action@v3.0.1 build_wheels: name: ${{ matrix.build || matrix.platform }} ${{ matrix.archs }} wheels needs: [lint] permissions: contents: read runs-on: "${{ matrix.runs-on }}${{ startsWith(matrix.archs, 'aarch64') && '-arm' || '' }}" strategy: matrix: platform: ["linux"] archs: ["x86_64, i686", "aarch64, armv7l", "ppc64le", "s390x", "riscv64"] build: ["manylinux", "musllinux"] runs-on: [ubuntu-24.04] include: - platform: "windows" archs: "AMD64" runs-on: windows-2022 - platform: "windows" archs: "x86" runs-on: windows-2022 - platform: "windows" archs: "ARM64" runs-on: windows-11-arm - platform: "macos" archs: "x86_64" runs-on: macos-15-intel - platform: "macos" archs: "arm64" runs-on: macos-14 - platform: "ios" archs: "x86_64_iphonesimulator" runs-on: macos-15-intel - platform: "ios" archs: "arm64_iphonesimulator,arm64_iphoneos" runs-on: macos-14 - platform: "android" archs: "arm64_v8a,x86_64" runs-on: ubuntu-24.04 - platform: "pyodide" archs: "wasm32" runs-on: ubuntu-24.04 steps: - name: Set git to use LF run: | git config --global core.autocrlf false git config --global core.eol lf - uses: actions/checkout@v6 with: submodules: recursive persist-credentials: false - name: Set up QEMU uses: docker/setup-qemu-action@v3.7.0 if: runner.os == 'Linux' && runner.arch == 'X64' # https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/ - name: Enable KVM for Android emulator if: matrix.platform == 'android' && runner.os == 'Linux' && runner.arch == 'X64' run: | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - name: Install cmake if: runner.os == 'macOS' run: | # workaround https://gitlab.kitware.com/cmake/cmake/-/issues/26570 pipx install -f cmake which cmake cmake --version # see https://cibuildwheel.pypa.io/en/stable/faq/#macos-building-cpython-38-wheels-on-arm64 - name: "Install python 3.8 universal2 on macOS arm64" if: runner.os == 'macOS' && runner.arch == 'ARM64' uses: actions/setup-python@v6 env: PIP_DISABLE_PIP_VERSION_CHECK: 1 with: python-version: 3.8 - name: Build wheels uses: pypa/cibuildwheel@v3.3.0 env: CIBW_ARCHS: "${{ matrix.archs }}" CIBW_BUILD: "${{ matrix.build && '*-' || ''}}${{ matrix.build }}*" CIBW_ENABLE: "${{ startsWith(github.ref, 'refs/tags/v') && '' || 'cpython-prerelease'}}" CIBW_PLATFORM: "${{ matrix.platform }}" - uses: actions/upload-artifact@v5 with: name: "${{ (matrix.platform != 'pyodide') && 'pypi' || 'cibw' }}-wheels ${{ matrix.build || matrix.platform }} ${{ matrix.archs }}" path: ./wheelhouse/*.whl build_sdist: name: source distribution needs: [lint] permissions: contents: read runs-on: ubuntu-22.04 env: CIBUILDWHEEL: 1 # make C extension mandatory steps: - uses: actions/checkout@v6 with: submodules: recursive persist-credentials: false - name: Build sdist run: pipx run build --sdist - uses: actions/setup-python@v6 name: Install Python with: python-version: "3.11" - name: Install run: python -m pip install ${{ github.workspace }}/dist/pybase64*.tar.gz working-directory: "${{ runner.temp }}" - name: Test run: | python -m pip install -r requirements-test.txt pytest - uses: actions/upload-artifact@v5 with: name: pypi-sdist path: dist/*.tar.gz check_dist: name: Check dist needs: [build_wheels, build_sdist] permissions: contents: read runs-on: ubuntu-24.04 steps: - uses: actions/download-artifact@v6 with: # unpacks all PyPI artifacts into dist/ pattern: pypi-* path: dist merge-multiple: true - run: | set -x WHEEL_COUNT=$(find dist -name '*.whl' | wc -l) EXPECTED_WHEEL_COUNT=${{ startsWith(github.ref, 'refs/tags/v') && '214' || '214' }} test ${WHEEL_COUNT} -eq ${EXPECTED_WHEEL_COUNT} pipx run twine check --strict dist/* - uses: actions/download-artifact@v6 with: # unpacks all non PyPI artifacts into nodist/ pattern: cibw-* path: nodist merge-multiple: true - run: | set -x WHEEL_COUNT=$(find nodist -name '*.whl' | wc -l) EXPECTED_WHEEL_COUNT=${{ startsWith(github.ref, 'refs/tags/v') && '2' || '2' }} test ${WHEEL_COUNT} -eq ${EXPECTED_WHEEL_COUNT} pipx run twine check --strict nodist/* upload_test_pypi: name: Upload to Test PyPI needs: [check_dist] runs-on: ubuntu-22.04 if: github.event_name == 'push' && github.repository == 'mayeut/pybase64' environment: name: test-pypi url: https://test.pypi.org/p/pybase64 permissions: id-token: write # trusted publishing + attestations steps: - uses: actions/download-artifact@v6 with: # unpacks all PyPI artifacts into dist/ pattern: pypi-* path: dist merge-multiple: true - name: Upload to Test PyPI uses: pypa/gh-action-pypi-publish@v1.13.0 with: skip-existing: true repository-url: https://test.pypi.org/legacy/ upload_pypi: name: Upload to PyPI needs: [upload_test_pypi] runs-on: ubuntu-22.04 if: github.event_name == 'push' && github.repository == 'mayeut/pybase64' && startsWith(github.ref, 'refs/tags/v') environment: name: pypi url: https://pypi.org/p/pybase64 permissions: id-token: write # trusted publishing + attestations steps: - uses: actions/download-artifact@v6 with: # unpacks all PyPI artifacts into dist/ pattern: pypi-* path: dist merge-multiple: true - name: Upload to PyPI uses: pypa/gh-action-pypi-publish@v1.13.0 with: skip-existing: true pybase64-1.4.3/.github/workflows/coverage.yml000066400000000000000000000022351511500755200210720ustar00rootroot00000000000000name: Coverage on: push: branches-ignore: - "dependabot/**" - "pre-commit-ci-update-config" pull_request: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: contents: read jobs: build_sdist: name: Coverage runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v6 with: submodules: recursive persist-credentials: false - uses: wntrblm/nox@2025.11.12 with: python-versions: "3.13, pypy3.10" - name: Install Intel SDE run: | curl -fsSLo ${HOME}/sde.tar.xz https://downloadmirror.intel.com/813591/sde-external-9.33.0-2024-01-07-lin.tar.xz mkdir ${HOME}/sde tar -C ${HOME}/sde --strip-components 1 -xf ${HOME}/sde.tar.xz echo "PATH=${HOME}/sde:${PATH}" >> $GITHUB_ENV - name: Run coverage tests run: nox -s coverage -- --with-sde - name: Upload coverage to codecov uses: codecov/codecov-action@v5 with: files: coverage-native.xml,coverage-python.xml token: ${{ secrets.CODECOV_TOKEN }} pybase64-1.4.3/.github/workflows/msys2.yml000066400000000000000000000030701511500755200203520ustar00rootroot00000000000000name: MSYS2 Tests on: push: branches-ignore: - "dependabot/**" - "pre-commit-ci-update-config" pull_request: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: contents: read jobs: test: name: Test with MSYS2 ${{ matrix.sys }} runs-on: windows-2022 strategy: matrix: include: - { sys: msys, toolchain: "gcc" } - { sys: mingw64, env: mingw-w64-x86_64- } - { sys: ucrt64, env: mingw-w64-ucrt-x86_64- } - { sys: clang64, env: mingw-w64-clang-x86_64- } steps: - uses: actions/checkout@v6 with: submodules: recursive persist-credentials: false - name: 'Setup MSYS2' uses: msys2/setup-msys2@v2 with: msystem: ${{matrix.sys}} update: true install: >- make ${{matrix.env}}cmake ${{matrix.env}}ninja ${{matrix.env}}${{matrix.toolchain || 'toolchain' }} ${{matrix.env}}python ${{matrix.env}}python-pip ${{matrix.env}}python-pytest ${{matrix.env}}python-pygments ${{matrix.env}}python-setuptools ${{matrix.env}}python-typing_extensions - name: "Run tests" shell: msys2 {0} env: CIBUILDWHEEL: 1 CC: cc run: | # virtual env seems to be broken # just allow breaking system packages, we're in CI python -m pip install --break-system-packages -v --no-build-isolation . python -m pytest pybase64-1.4.3/.github/workflows/test.yml000066400000000000000000000012461511500755200202570ustar00rootroot00000000000000name: Test on: push: branches-ignore: - "dependabot/**" - "pre-commit-ci-update-config" pull_request: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: contents: read jobs: test: name: Test runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v6 with: submodules: recursive persist-credentials: false - uses: wntrblm/nox@2025.11.12 with: python-versions: "3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14, pypy3.9, pypy3.10, pypy3.11" - name: "Run tests" run: nox --error-on-missing-interpreters -s test pybase64-1.4.3/.github/workflows/valgrind.yml000066400000000000000000000023361511500755200211070ustar00rootroot00000000000000name: Valgrind on: push: branches-ignore: - "dependabot/**" - "pre-commit-ci-update-config" pull_request: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: contents: read jobs: build_sdist: name: Valgrind runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 with: submodules: recursive persist-credentials: false - name: Install dependencies run: | set -exuo pipefail sudo apt-get update sudo apt-get install -y --no-install-recommends valgrind python3.12-dbg python3.12-dev python3.12-dbg -mvenv ./venv-dbg ln -sf $(pwd)/venv-dbg/bin/python /usr/local/bin/python-pb64 python-pb64 -m pip install --upgrade pip setuptools wheel python-pb64 -m pip install -r requirements-test.txt - name: Run valgrind tests run: | set -exuo pipefail CFLAGS="-O0" CIBUILDWHEEL=1 python-pb64 -m pip install -e . PYTHONMALLOC=malloc valgrind --leak-check=full --show-leak-kinds=definite --errors-for-leak-kinds=definite --error-exitcode=2 $(which python-pb64) -m pytest pybase64-1.4.3/.gitignore000066400000000000000000000021631511500755200151470ustar00rootroot00000000000000# Genertaed files src/pybase64/_license.py # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions .base64_build/ *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheelhouse/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage*.xml *,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # IPython Notebook .ipynb_checkpoints # pyenv .python-version # celery beat schedule file celerybeat-schedule # dotenv .env # virtualenv .venv/ venv/ ENV/ # Spyder project settings .spyderproject # Rope project settings .ropeproject pybase64-1.4.3/.gitmodules000066400000000000000000000001201511500755200153230ustar00rootroot00000000000000[submodule "base64"] path = base64 url = https://github.com/aklomp/base64.git pybase64-1.4.3/.pre-commit-config.yaml000066400000000000000000000030201511500755200174310ustar00rootroot00000000000000# See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: - id: check-builtin-literals - id: check-added-large-files - id: check-case-conflict - id: check-toml - id: check-yaml - id: debug-statements - id: end-of-file-fixer - id: forbid-new-submodules - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.14.7 hooks: - id: ruff args: ["--fix", "--show-fixes"] - id: ruff-format - repo: local hooks: - id: mypy name: mypy 3.8 entry: mypy language: python 'types_or': [ python, pyi ] require_serial: true minimum_pre_commit_version: '2.9.2' exclude: docs|conftest.py args: ["--python-version=3.8"] additional_dependencies: - mypy==1.16.1 - nox - pytest<8.4 - types-setuptools - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.19.0 hooks: - id: mypy name: mypy 3.9 exclude: docs|conftest.py args: ["--python-version=3.9"] additional_dependencies: - nox - pytest<9 - types-setuptools - id: mypy name: mypy 3.10 exclude: docs|conftest.py args: ["--python-version=3.10"] additional_dependencies: - nox - pytest - types-setuptools - id: mypy name: mypy 3.14 exclude: docs|conftest.py args: ["--python-version=3.14"] additional_dependencies: - nox - pytest - types-setuptools pybase64-1.4.3/.readthedocs.yaml000066400000000000000000000012311511500755200164010ustar00rootroot00000000000000# .readthedocs.yaml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Set the version of Python and other tools you might need build: os: ubuntu-22.04 tools: python: "3.11" # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/conf.py # If using Sphinx, optionally build your docs in additional formats such as PDF formats: - epub - pdf # Optionally declare the Python requirements required to build your docs python: install: - requirements: requirements-doc.txt - method: pip path: . submodules: include: all pybase64-1.4.3/LICENSE000066400000000000000000000024561511500755200141710ustar00rootroot00000000000000BSD 2-Clause License Copyright (c) 2017-2022, Matthieu Darbois 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. pybase64-1.4.3/MANIFEST.in000066400000000000000000000004531511500755200147150ustar00rootroot00000000000000# Include the license file include LICENSE # Include headers include src/pybase64/_pybase64_get_simd_flags.h # Include type stub for extension include src/pybase64/_pybase64.pyi # Include full base64 folder graft base64 # but the git folder prune base64/.git # and hidden files global-exclude .* pybase64-1.4.3/README.rst000066400000000000000000000162561511500755200146560ustar00rootroot00000000000000.. SETUP VARIABLES .. |license-status| image:: https://img.shields.io/badge/license-BSD%202--Clause-blue.svg :target: https://github.com/mayeut/pybase64/blob/master/LICENSE .. |pypi-status| image:: https://img.shields.io/pypi/v/pybase64.svg :target: https://pypi.python.org/pypi/pybase64 .. |python-versions| image:: https://img.shields.io/pypi/pyversions/pybase64.svg .. |rtd-status| image:: https://readthedocs.org/projects/pybase64/badge/?version=stable :target: http://pybase64.readthedocs.io/en/stable/?badge=stable :alt: Documentation Status .. |gha-status| image:: https://github.com/mayeut/pybase64/workflows/Build%20and%20upload%20to%20PyPI/badge.svg :target: https://github.com/mayeut/pybase64/actions?query=workflow%3A%22Build+and+upload+to+PyPI%22 .. |codecov-status| image:: https://codecov.io/gh/mayeut/pybase64/branch/master/graph/badge.svg :target: https://codecov.io/gh/mayeut/pybase64/branch/master .. END OF SETUP Fast Base64 implementation ========================== |license-status| |pypi-status| |python-versions| |rtd-status| |gha-status| |codecov-status| This project is a wrapper on `libbase64 `_. It aims to provide a fast base64 implementation for base64 encoding/decoding. Installation ============ .. code:: pip install pybase64 Usage ===== ``pybase64`` uses the same API as Python base64 "modern interface" (introduced in Python 2.4) for an easy integration. To get the fastest decoding, it is recommended to use the ``pybase64.b64decode`` and ``validate=True`` when possible. .. code:: python import pybase64 print(pybase64.b64encode(b'>>>foo???', altchars='_:')) # b'Pj4_Zm9vPz8:' print(pybase64.b64decode(b'Pj4_Zm9vPz8:', altchars='_:', validate=True)) # b'>>>foo???' # Standard encoding helpers print(pybase64.standard_b64encode(b'>>>foo???')) # b'Pj4+Zm9vPz8/' print(pybase64.standard_b64decode(b'Pj4+Zm9vPz8/')) # b'>>>foo???' # URL safe encoding helpers print(pybase64.urlsafe_b64encode(b'>>>foo???')) # b'Pj4-Zm9vPz8_' print(pybase64.urlsafe_b64decode(b'Pj4-Zm9vPz8_')) # b'>>>foo???' .. begin cli A command-line tool is also provided. It has encode, decode and benchmark subcommands. .. code:: usage: pybase64 [-h] [-V] {benchmark,encode,decode} ... pybase64 command-line tool. positional arguments: {benchmark,encode,decode} tool help benchmark -h for usage encode -h for usage decode -h for usage optional arguments: -h, --help show this help message and exit -V, --version show program's version number and exit .. end cli Full documentation on `Read the Docs `_. Benchmark ========= .. begin benchmark Running Python 3.7.2, Apple LLVM version 10.0.0 (clang-1000.11.45.5), Mac OS X 10.14.2 on an Intel Core i7-4870HQ @ 2.50GHz .. code:: pybase64 0.5.0 (C extension active - AVX2) bench: altchars=None, validate=False pybase64._pybase64.encodebytes: 1734.776 MB/s (13,271,472 bytes -> 17,928,129 bytes) pybase64._pybase64.b64encode: 4039.539 MB/s (13,271,472 bytes -> 17,695,296 bytes) pybase64._pybase64.b64decode: 1854.423 MB/s (17,695,296 bytes -> 13,271,472 bytes) base64.encodebytes: 78.352 MB/s (13,271,472 bytes -> 17,928,129 bytes) base64.b64encode: 539.840 MB/s (13,271,472 bytes -> 17,695,296 bytes) base64.b64decode: 287.826 MB/s (17,695,296 bytes -> 13,271,472 bytes) bench: altchars=None, validate=True pybase64._pybase64.b64encode: 4156.607 MB/s (13,271,472 bytes -> 17,695,296 bytes) pybase64._pybase64.b64decode: 4107.997 MB/s (17,695,296 bytes -> 13,271,472 bytes) base64.b64encode: 559.342 MB/s (13,271,472 bytes -> 17,695,296 bytes) base64.b64decode: 143.674 MB/s (17,695,296 bytes -> 13,271,472 bytes) bench: altchars=b'-_', validate=False pybase64._pybase64.b64encode: 2786.776 MB/s (13,271,472 bytes -> 17,695,296 bytes) pybase64._pybase64.b64decode: 1124.136 MB/s (17,695,296 bytes -> 13,271,472 bytes) base64.b64encode: 322.427 MB/s (13,271,472 bytes -> 17,695,296 bytes) base64.b64decode: 205.195 MB/s (17,695,296 bytes -> 13,271,472 bytes) bench: altchars=b'-_', validate=True pybase64._pybase64.b64encode: 2806.271 MB/s (13,271,472 bytes -> 17,695,296 bytes) pybase64._pybase64.b64decode: 2740.456 MB/s (17,695,296 bytes -> 13,271,472 bytes) base64.b64encode: 314.709 MB/s (13,271,472 bytes -> 17,695,296 bytes) base64.b64decode: 121.803 MB/s (17,695,296 bytes -> 13,271,472 bytes) .. end benchmark .. begin changelog Changelog ========= 1.4.3 ----- - Publish Android Python 3.14 wheels - Publish GraalPy v25 wheels 1.4.2 ----- - Update base64 library (Windows ARM64 Neon support) - Publish Python 3.14 wheels - Publish Linux riscv64 wheels - Publish Android wheels - Publish iOS wheels - Publish GraalPy wheels 1.4.1 ----- - Publish PyPy 3.11 wheels - Publish armv7l wheels 1.4.0 ----- - Publish python 3.13 wheels - Add support for free-threaded builds - Add MSYS2 support for C-extension - Better logging on base64 build failure when C-extension build is optional - Drop python 3.6 & 3.7 support 1.3.2 ----- - Update base64 library - PyPy: fix wrong outcome with non C-contiguous buffer 1.3.1 ----- - Add missing py.typed marker 1.3.0 ----- - Update base64 library - Add AVX512-VBMI implementation - Rework extension build to remove adherence on distutils - Publish python 3.12 wheels - Documentation now uses furo theme 1.2.3 ----- - Update base64 library - Publish python 3.11 wheels 1.2.2 ----- - Update base64 library - Fix C extension build on musl distros - Publish musllinux wheels 1.2.1 ----- - Publish PyPy 3.8 (pypy38_pp73) wheels 1.2.0 ----- - Release the GIL - Publish CPython 3.10 wheels - Drop python 3.5 support 1.1.4 ----- - Add macOS arm64 wheel 1.1.3 ----- - GitHub Actions: fix build on tag 1.1.2 ----- - Add PyPy wheels - Add aarch64, ppc64le & s390x manylinux wheels 1.1.1 ----- - Move CI from TravisCI/AppVeyor to GitHub Actions - Fix publication of Linux/macOS wheels 1.1.0 ----- - Add b64encode_as_string, same as b64encode but returns a str object instead of a bytes object - Add b64decode_as_bytearray, same as b64decode but returns a bytarray object instead of a bytes object - Speed-Up decoding from UCS1 strings 1.0.2 ----- - Update base64 library - Publish python 3.9 wheels 1.0.1 ----- - Publish python 3.8 wheels 1.0.0 ----- - Drop python 3.4 support - Drop python 2.7 support 0.5.0 ----- - Publish python 3.7 wheels - Drop python 3.3 support 0.4.0 ----- - Speed-up decoding when validate==False 0.3.1 ----- - Fix deployment issues 0.3.0 ----- - Add encodebytes function 0.2.1 ----- - Fixed invalid results on Windows 0.2.0 ----- - Added documentation - Added subcommands to the main script: * help * version * encode * decode * benchmark 0.1.2 ----- - Updated base64 native library 0.1.1 ----- - Fixed deployment issues 0.1.0 ----- - First public release .. end changelog pybase64-1.4.3/base64/000077500000000000000000000000001511500755200142415ustar00rootroot00000000000000pybase64-1.4.3/conftest.py000066400000000000000000000002411511500755200153510ustar00rootroot00000000000000from __future__ import annotations def pytest_addoption(parser) -> None: parser.addoption("--sde-cpu", action="store", default=None, help="run sde tests") pybase64-1.4.3/docs/000077500000000000000000000000001511500755200141055ustar00rootroot00000000000000pybase64-1.4.3/docs/Makefile000066400000000000000000000011411511500755200155420ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = python -msphinx SPHINXPROJ = pybase64 SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) pybase64-1.4.3/docs/api.rst000066400000000000000000000012661511500755200154150ustar00rootroot00000000000000API Reference ============= Main API Reference ------------------ .. autofunction:: pybase64.b64encode .. autofunction:: pybase64.b64encode_as_string .. autofunction:: pybase64.b64decode .. autofunction:: pybase64.b64decode_as_bytearray Helpers API Reference --------------------- .. autofunction:: pybase64.standard_b64encode .. autofunction:: pybase64.standard_b64decode .. autofunction:: pybase64.urlsafe_b64encode .. autofunction:: pybase64.urlsafe_b64decode Legacy API Reference -------------------- .. autofunction:: pybase64.encodebytes Information API Reference ------------------------- .. autofunction:: pybase64.get_version .. autofunction:: pybase64.get_license_text pybase64-1.4.3/docs/changelog.rst000066400000000000000000000001421511500755200165630ustar00rootroot00000000000000.. include:: ../README.rst :start-after: .. begin changelog :end-before: .. end changelog pybase64-1.4.3/docs/conf.py000066400000000000000000000123311511500755200154040ustar00rootroot00000000000000# pybase64 documentation build configuration file, created by # sphinx-quickstart on Tue Aug 29 22:06:28 2017. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. from __future__ import annotations import datetime import os import runpy import sys here = os.path.abspath(os.path.dirname(__file__)) # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath(os.path.join(here, ".."))) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ "sphinx.ext.autodoc", "sphinx.ext.coverage", "sphinx.ext.intersphinx", "sphinx.ext.viewcode", ] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = ".rst" # The master toctree document. master_doc = "index" # General information about the project. project = "pybase64" author = "Matthieu Darbois" copyright = f"2017-{datetime.date.today().year}, Matthieu Darbois" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # Get version _version = runpy.run_path(os.path.join(here, "..", "src", "pybase64", "_version.py"))["_version"] # The short X.Y version. version = _version # The full version, including alpha/beta/rc tags. release = _version # default highlight language to 'none', requires to be explicit highlight_language = "none" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = "furo" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. htmlhelp_basename = "pybase64doc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, "pybase64.tex", "pybase64 Documentation", author, "manual"), ] # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [(master_doc, "pybase64", "pybase64 Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ( master_doc, "pybase64", "pybase64 Documentation", author, "pybase64", "Fast Base64 implementation for Python.", "Miscellaneous", ), ] # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {"python": ("https://docs.python.org/3", None)} pybase64-1.4.3/docs/index.rst000066400000000000000000000003231511500755200157440ustar00rootroot00000000000000pybase64 ======== Fast Base64 implementation for Python. .. toctree:: :maxdepth: 2 :caption: Contents: intro api changelog license pybase64 on Github pybase64-1.4.3/docs/intro.rst000066400000000000000000000025151511500755200157750ustar00rootroot00000000000000Getting started =============== ``pybase64`` is a wrapper on `libbase64 `_. It aims to provide a fast base64 implementation for base64 encoding/decoding. Installation ------------ .. code-block:: bash pip install pybase64 Usage ----- ``pybase64`` uses the same API as Python :mod:`base64` "modern interface" (introduced in Python 2.4) for an easy integration. To get the fastest decoding, it is recommended to use the :func:`~pybase64.b64decode` and `validate=True` when possible. .. code-block:: python import pybase64 print(pybase64.b64encode(b'>>>foo???', altchars='_:')) # b'Pj4_Zm9vPz8:' print(pybase64.b64decode(b'Pj4_Zm9vPz8:', altchars='_:', validate=True)) # b'>>>foo???' # Standard encoding helpers print(pybase64.standard_b64encode(b'>>>foo???')) # b'Pj4+Zm9vPz8/' print(pybase64.standard_b64decode(b'Pj4+Zm9vPz8/')) # b'>>>foo???' # URL safe encoding helpers print(pybase64.urlsafe_b64encode(b'>>>foo???')) # b'Pj4-Zm9vPz8_' print(pybase64.urlsafe_b64decode(b'Pj4-Zm9vPz8_')) # b'>>>foo???' Check :doc:`api` for more details. .. include:: ../README.rst :start-after: .. begin cli :end-before: .. end cli Benchmark --------- .. include:: ../README.rst :start-after: .. begin benchmark :end-before: .. end benchmark pybase64-1.4.3/docs/license.rst000066400000000000000000000002451511500755200162620ustar00rootroot00000000000000License ======= pybase64 -------- .. literalinclude:: ../LICENSE :language: none libbase64 --------- .. literalinclude:: ../base64/LICENSE :language: none pybase64-1.4.3/noxfile.py000066400000000000000000000134261511500755200152010ustar00rootroot00000000000000from __future__ import annotations import os import sys from pathlib import Path import nox HERE = Path(__file__).resolve().parent nox.options.sessions = ["lint", "test"] ALL_CPYTHON = [f"3.{minor}" for minor in range(8, 14 + 1)] ALL_PYPY = [f"pypy3.{minor}" for minor in range(9, 11 + 1)] ALL_PYTHON = ALL_CPYTHON + ALL_PYPY @nox.session def lint(session: nox.Session) -> None: """Run linters on the codebase.""" session.install("pre-commit") session.run("pre-commit", "run", "-a") def update_env_macos(session: nox.Session, env: dict[str, str]) -> None: if sys.platform.startswith("darwin"): # we don't support universal builds machine = session.run( # type: ignore[union-attr] "python", "-sSEc", "import platform; print(platform.machine())", silent=True ).strip() env["ARCHFLAGS"] = f"-arch {machine}" env["_PYTHON_HOST_PLATFORM"] = f"macosx-11.0-{machine}" def remove_extension(session: nox.Session, in_place: bool = False) -> None: if in_place: where = HERE / "src" / "pybase64" else: command = "import sysconfig; print(sysconfig.get_path('platlib'))" platlib = session.run("python", "-c", command, silent=True).strip() # type: ignore[union-attr] where = Path(platlib) / "pybase64" assert where.exists() removed = False for ext in ["*.so", "*.pyd"]: for file in where.glob(ext): session.log(f"removing '{file.relative_to(HERE)}'") file.unlink() removed = True if not in_place: assert removed @nox.session(python="3.12") def develop(session: nox.Session) -> None: """create venv for dev.""" session.install("nox", "setuptools", "-r", "requirements-test.txt") # make extension mandatory by exporting CIBUILDWHEEL=1 env = {"CIBUILDWHEEL": "1"} update_env_macos(session, env) session.install("-e", ".", env=env) @nox.session(python=ALL_PYTHON) def test(session: nox.Session) -> None: """Run tests.""" session.install("-r", "requirements-test.txt") # make extension mandatory by exporting CIBUILDWHEEL=1 env = {"CIBUILDWHEEL": "1"} update_env_macos(session, env) session.install(".", env=env) session.run("pytest", *session.posargs, env=env) # run without extension as well env.pop("CIBUILDWHEEL") remove_extension(session) session.run("pytest", *session.posargs, env=env) @nox.session(python=["3.13", "pypy3.10"]) def _coverage(session: nox.Session) -> None: """internal coverage run. Do not run manually""" with_sde = "--with-sde" in session.posargs clean = "--clean" in session.posargs report = "--report" in session.posargs coverage_args = ( "--cov=pybase64", "--cov=tests", "--cov-append", "--cov-report=", ) pytest_command = ("pytest", *coverage_args) session.install("-r", "requirements-test.txt", "-r", "requirements-coverage.txt") remove_extension(session, in_place=True) # make extension mandatory by exporting CIBUILDWHEEL=1 env = { "CIBUILDWHEEL": "1", "CFLAGS": "-O0 -coverage", "LDFLAGS": "-coverage", } update_env_macos(session, env) session.install("-e", ".", env=env) if clean: session.run("coverage", "erase", env=env) session.run(*pytest_command, env=env) if with_sde: cpu = "spr" sde = ("sde", f"-{cpu}", "--") session.run(*sde, *pytest_command, f"--sde-cpu={cpu}", env=env, external=True) for cpu in ["p4p", "mrm", "pnr", "nhm", "snb", "hsw"]: sde = ("sde", f"-{cpu}", "--") pytest_addopt = (f"--sde-cpu={cpu}", "-k=test_flags") session.run(*sde, *pytest_command, *pytest_addopt, env=env, external=True) # run without extension as well env.pop("CIBUILDWHEEL") remove_extension(session, in_place=True) session.run(*pytest_command, env=env) # reports if report: threshold = 100.0 if "CI" in os.environ else 99.8 session.run("coverage", "report", "--show-missing", f"--fail-under={threshold}") session.run("coverage", "xml", "-ocoverage-python.xml") if sys.platform.startswith("linux"): gcovr_config = ("-r=.", "-e=base64", "-e=.base64_build") session.run( "gcovr", *gcovr_config, "--fail-under-line=90", "--txt", "-s", "--xml=coverage-native.xml", ) @nox.session(venv_backend="none") def coverage(session: nox.Session) -> None: """Coverage tests.""" posargs_ = set(session.posargs) assert len(posargs_ & {"--clean", "--report"}) == 0 assert len(posargs_ - {"--with-sde"}) == 0 posargs = [*session.posargs, "--report"] session.notify("_coverage-pypy3.10", ["--clean"]) session.notify("_coverage-3.13", posargs) @nox.session(python="3.12") def benchmark(session: nox.Session) -> None: """Benchmark tests.""" project_install: tuple[str, ...] = ("-e", ".") posargs = session.posargs.copy() if "--wheel" in posargs: index = posargs.index("--wheel") posargs.pop(index) project_install = (posargs.pop(index),) env = {"CIBUILDWHEEL": "1"} update_env_macos(session, env) session.install("-r", "requirements-benchmark.txt", *project_install, env=env) session.run("pytest", "--codspeed", *posargs) @nox.session(python="3.11") def docs(session: nox.Session) -> None: """ Build the docs. """ session.install("-r", "requirements-doc.txt", ".") session.run("pip", "list") session.chdir("docs") session.run( "python", "-m", "sphinx", "-T", "-E", "-b", "html", "-d", "_build/doctrees", "-D", "language=en", ".", "build", ) pybase64-1.4.3/pyproject.toml000066400000000000000000000057671511500755200161100ustar00rootroot00000000000000[build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" [tool.cibuildwheel] build-verbosity = 1 enable = ["cpython-freethreading", "graalpy", "pypy", "pypy-eol"] test-skip = ["gp3*-win_amd64", "*-android*"] # https://github.com/oracle/graalpython/issues/490 test-requires = "-r requirements-test.txt" test-sources = ["conftest.py", "pyproject.toml", "tests"] test-command = "python -m pytest" xbuild-tools = ["cmake"] [[tool.cibuildwheel.overrides]] select = "*-manylinux*" environment = { AUDITWHEEL_PLAT="manylinux2014_${AUDITWHEEL_ARCH}" } [[tool.cibuildwheel.overrides]] select = "*-manylinux_riscv64" environment = { AUDITWHEEL_PLAT="manylinux_2_31_${AUDITWHEEL_ARCH}" } [tool.coverage.run] branch = true patch = ["subprocess"] omit = [ "tests/conftest.py", "tests/test_benchmark.py", ] [tool.coverage.report] exclude_lines = ["pragma: no cover", "class .*\\(Protocol\\):", "if TYPE_CHECKING:"] [tool.mypy] python_version = "3.8" files = [ "src/**/*.py", "test/**/*.py", "noxfile.py", "setup.py", ] warn_unused_configs = true show_error_codes = true warn_redundant_casts = true no_implicit_reexport = true strict_equality = true warn_unused_ignores = true check_untyped_defs = true ignore_missing_imports = false disallow_subclassing_any = true disallow_any_generics = true disallow_untyped_defs = true disallow_untyped_calls = true disallow_incomplete_defs = true disallow_untyped_decorators = true disallow_any_explicit = true warn_return_any = true no_implicit_optional = true enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] warn_unreachable = true [[tool.mypy.overrides]] module = ["pybase64.__main__", "tests.test_pybase64", "tests.utils"] disallow_any_explicit = false [tool.pytest.ini_options] minversion = "7.0" addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config", "-p", "no:legacypath"] markers = ["benchmark"] [tool.ruff] target-version = "py38" line-length = 100 [tool.ruff.lint] extend-select = [ "B", # flake8-bugbear "I", # isort "ARG", # flake8-unused-arguments "C4", # flake8-comprehensions "EM", # flake8-errmsg "ICN", # flake8-import-conventions "ISC", # flake8-implicit-str-concat "G", # flake8-logging-format "PGH", # pygrep-hooks "PIE", # flake8-pie "PL", # pylint "PT", # flake8-pytest-style "RET", # flake8-return "RUF", # Ruff-specific "SIM", # flake8-simplify "TID251", # flake8-tidy-imports.banned-api "UP", # pyupgrade "YTT", # flake8-2020 "EXE", # flake8-executable "PYI", # flake8-pyi ] ignore = [ "PLR", # Design related pylint codes ] typing-modules = ["pybase64._typing"] [tool.ruff.lint.flake8-tidy-imports.banned-api] "typing.Callable".msg = "Use collections.abc.Callable instead." "typing.Iterator".msg = "Use collections.abc.Iterator instead." "typing.Sequence".msg = "Use collections.abc.Sequence instead." pybase64-1.4.3/requirements-benchmark.txt000066400000000000000000000000601511500755200203650ustar00rootroot00000000000000-r requirements-test.txt pytest-codspeed==4.2.0 pybase64-1.4.3/requirements-coverage.txt000066400000000000000000000001071511500755200202300ustar00rootroot00000000000000-r requirements-test.txt gcovr==8.4 pytest-cov==7.0.0 coverage==7.10.7 pybase64-1.4.3/requirements-doc.txt000066400000000000000000000000361511500755200172030ustar00rootroot00000000000000sphinx==8.2.3 furo==2025.9.25 pybase64-1.4.3/requirements-test.txt000066400000000000000000000002221511500755200174120ustar00rootroot00000000000000pytest==9.0.0 ; python_version >= '3.10' pytest==8.4.2 ; python_version == '3.9' pytest==8.3.5 ; python_version == '3.8' typing_extensions>=4.6.0 pybase64-1.4.3/setup.py000066400000000000000000000246031511500755200146740ustar00rootroot00000000000000from __future__ import annotations import logging import os import platform as platform_module import shutil import subprocess import sys import sysconfig from contextlib import contextmanager from pathlib import Path from typing import Generator, cast from setuptools import Extension, find_packages, setup from setuptools.command.build_ext import build_ext HERE = Path(__file__).resolve().parent OPTIONAL_EXTENSION = os.environ.get("CIBUILDWHEEL", "0") != "1" IS_64BIT = sys.maxsize > 2**32 IS_WINDOWS = sys.platform.startswith("win32") IS_MACOS = sys.platform.startswith("darwin") log = logging.getLogger("pybase64-setup") # Get version version_dict: dict[str, object] = {} exec(HERE.joinpath("src", "pybase64", "_version.py").read_text(), {}, version_dict) version = cast(str, version_dict["_version"]) # Get the long description from the README file long_description = HERE.joinpath("README.rst").read_text() # Generate license text with HERE.joinpath("src", "pybase64", "_license.py").open("w") as f: f.write('_license = """') f.write("pybase64\n") f.write("=" * 79 + "\n") f.write(HERE.joinpath("LICENSE").read_text()) f.write("=" * 79 + "\n\n") f.write("libbase64\n") f.write("=" * 79 + "\n") f.write(HERE.joinpath("base64", "LICENSE").read_text()) f.write("=" * 74) f.write('""" \\\n') f.write(' + "====="\n') pybase64_ext = Extension( "pybase64._pybase64", [ "src/pybase64/_pybase64.c", "src/pybase64/_pybase64_get_simd_flags.c", ], include_dirs=["base64/include/", "base64/lib/", ".base64_build"], library_dirs=[".base64_build"], libraries=["base64"], define_macros=[("BASE64_STATIC_DEFINE", "1")], optional=OPTIONAL_EXTENSION, ) def get_cmake_extra_config(plat_name: str | None, build_type: str) -> tuple[bool, list[str]]: log.info("getting cmake extra config") extra_config = [] machine = platform_module.machine().lower() platform = sysconfig.get_platform() archflags = os.environ.get("ARCHFLAGS", None) log.info(" machine: %s", machine) log.info(" platform: %s", platform) log.info(" plat_name: %s", plat_name) log.info(" ARCHFLAGS: %s", archflags) log.info(" CC: %s", os.environ.get("CC", None)) log.info(" CFLAGS: %s", os.environ.get("CFLAGS", None)) log.info(" LDFLAGS: %s", os.environ.get("LDFLAGS", None)) log.info(" CMAKE_TOOLCHAIN_FILE: %s", os.environ.get("CMAKE_TOOLCHAIN_FILE", None)) log.info(" sysconfig CC: %s", sysconfig.get_config_var("CC")) log.info(" sysconfig CCSHARED: %s", sysconfig.get_config_var("CCSHARED")) log.info(" sysconfig CFLAGS: %s", sysconfig.get_config_var("CFLAGS")) log.info(" sysconfig BASECFLAGS: %s", sysconfig.get_config_var("BASECFLAGS")) log.info(" sysconfig OPT: %s", sysconfig.get_config_var("OPT")) log.info(" sysconfig LDFLAGS: %s", sysconfig.get_config_var("LDFLAGS")) platform = plat_name or platform is_msvc = platform.startswith("win") is_macos = platform.startswith("macosx-") is_ios = platform.startswith("ios-") if not is_msvc: extra_config.append(f"-DCMAKE_BUILD_TYPE={build_type}") if is_msvc: if not IS_WINDOWS: msg = f"Building {platform} is only supported on Windows" raise ValueError(msg) # setup cross-compile # assumes VS2019 or VS2022 will be used as the default generator if platform == "win-amd64" and machine != "amd64": extra_config.append("-A x64") if platform == "win32" and machine != "x86": extra_config.append("-A Win32") if platform == "win-arm64" and machine != "arm64": extra_config.append("-A ARM64") elif is_macos or is_ios: known_archs = { "arm64", "arm64e", "armv7", "armv7s", "x86_64", "i386", "ppc", "ppc64", } if is_macos and not IS_MACOS: msg = f"Building {platform} is only supported on macOS" raise ValueError(msg) if is_ios: _, min_ver, platform_arch, sdk = platform.split("-") min_ver = os.getenv("IPHONEOS_DEPLOYMENT_TARGET", min_ver) extra_config.append("-DCMAKE_SYSTEM_NAME=iOS") extra_config.append(f"-DCMAKE_OSX_SYSROOT={sdk}") else: _, min_ver, platform_arch = platform.split("-") min_ver = os.getenv("MACOSX_DEPLOYMENT_TARGET", min_ver) extra_config.append(f"-DCMAKE_OSX_DEPLOYMENT_TARGET={min_ver}") if platform_arch.startswith(("universal", "fat")): msg = f"multiple arch `{platform_arch}` is not supported" raise ValueError(msg) configured_archs = {platform_arch} if archflags: flags = [arch.strip() for arch in archflags.strip().split() if arch.strip()] for i in range(len(flags) - 1): if flags[i] == "-arch": configured_archs.add(flags[i + 1]) if len(configured_archs) > 1: msg = f"multiple arch `{configured_archs}` is not supported" raise ValueError(msg) arch = configured_archs.pop() if arch in known_archs: extra_config.append(f"-DCMAKE_OSX_ARCHITECTURES={arch}") else: log.warning("`%s` is not a known value for CMAKE_OSX_ARCHITECTURES", arch) return is_msvc, extra_config def cmake(*args: str) -> None: args_string = " ".join(f"'{arg}'" for arg in args) log.info("running cmake %s", args_string) subprocess.run(["cmake", *args], check=True) @contextmanager def base64_build(plat_name: str | None) -> Generator[bool, None, None]: base64_built = False source_dir = HERE / "base64" build_dir = HERE / ".base64_build" build_type = "Release" config_options = [ "-S", str(source_dir), "-B", str(build_dir), "-DBASE64_BUILD_TESTS:BOOL=OFF", "-DBASE64_BUILD_CLI:BOOL=OFF", "-DCMAKE_POSITION_INDEPENDENT_CODE=ON", "-DBUILD_SHARED_LIBS:BOOL=OFF", ] if build_dir.exists(): shutil.rmtree(build_dir) try: try: cmake("--version") is_msvc, extra_config = get_cmake_extra_config(plat_name, build_type) config_options.extend(extra_config) cmake(*config_options) cmake("--build", str(build_dir), "--config", build_type, "--verbose") if is_msvc: shutil.copyfile(build_dir / build_type / "base64.lib", build_dir / "base64.lib") base64_built = True except Exception as e: log.error("error: %s", e) if not OPTIONAL_EXTENSION: raise yield base64_built finally: if build_dir.exists(): shutil.rmtree(build_dir, ignore_errors=True) class BuildExt(build_ext): def finalize_options(self) -> None: if "-coverage" in os.environ.get("CFLAGS", "").split(): plat_name = getattr(self, "plat_name", None) or sysconfig.get_platform() temp_name = f"coverage-{plat_name}-{sys.implementation.cache_tag}" coverage_build = HERE / "build" / temp_name if coverage_build.exists(): shutil.rmtree(coverage_build) self.build_temp = str(coverage_build) super().finalize_options() def run(self) -> None: plat_name = getattr(self, "plat_name", None) with base64_build(plat_name) as build_successful: if build_successful: super().run() else: assert OPTIONAL_EXTENSION log.warning("warning: skipping optional C-extension, base64 library build failed") setup( name="pybase64", cmdclass={"build_ext": BuildExt}, ext_modules=[pybase64_ext], # Versions should comply with PEP440. For a discussion on single-sourcing # the version across setup.py and the project code, see # https://packaging.python.org/en/latest/single_source_version.html version=version, description="Fast Base64 encoding/decoding", long_description=long_description, long_description_content_type="text/x-rst", # The project's main homepage. url="https://github.com/mayeut/pybase64", project_urls={ "Source": "https://github.com/mayeut/pybase64", "Tracker": "https://github.com/mayeut/pybase64/issues", "Documentation": "https://pybase64.readthedocs.io/en/stable", }, # Author details author="Matthieu Darbois", # author_email = 'mayeut@users.noreply.github.com', # Choose your license license="BSD-2-Clause", # See https://pypi.python.org/pypi?%3Aaction=list_classifiers classifiers=[ # How mature is this project? Common values are # 3 - Alpha # 4 - Beta # 5 - Production/Stable "Development Status :: 5 - Production/Stable", # Indicate who your project is intended for "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities", # Pick your license as you wish (should match "license" above) "License :: OSI Approved :: BSD License", # Specify the Python versions you support here. In particular, ensure # that you indicate whether you support Python 2, Python 3 or both. "Programming Language :: C", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", ], # Supported python versions python_requires=">=3.8", # What does your project relate to? keywords="base64", # You can just specify the packages manually here if your project is # simple. Or you can use find_packages(). packages=find_packages(where="src"), package_dir={"": "src"}, package_data={"pybase64": ["py.typed", "_pybase64.pyi"]}, # To provide executable scripts, use entry points in preference to the # "scripts" keyword. Entry points provide cross-platform support and allow # pip to create the appropriate form of executable for the target platform. entry_points={ "console_scripts": [ "pybase64=pybase64.__main__:main", ], }, ) pybase64-1.4.3/src/000077500000000000000000000000001511500755200137445ustar00rootroot00000000000000pybase64-1.4.3/src/pybase64/000077500000000000000000000000001511500755200154015ustar00rootroot00000000000000pybase64-1.4.3/src/pybase64/__init__.py000066400000000000000000000062361511500755200175210ustar00rootroot00000000000000from __future__ import annotations from typing import TYPE_CHECKING from ._license import _license from ._version import _version if TYPE_CHECKING: from ._typing import Buffer try: from ._pybase64 import ( _get_simd_flags_compile, # noqa: F401 _get_simd_flags_runtime, # noqa: F401 _get_simd_name, _get_simd_path, _set_simd_path, # noqa: F401 b64decode, b64decode_as_bytearray, b64encode, b64encode_as_string, encodebytes, ) except ImportError: from ._fallback import ( _get_simd_name, _get_simd_path, b64decode, b64decode_as_bytearray, b64encode, b64encode_as_string, encodebytes, ) __all__ = ( "b64decode", "b64decode_as_bytearray", "b64encode", "b64encode_as_string", "encodebytes", "standard_b64decode", "standard_b64encode", "urlsafe_b64decode", "urlsafe_b64encode", ) __version__ = _version def get_license_text() -> str: """Returns pybase64 license information as a :class:`str` object. The result includes libbase64 license information as well. """ return _license def get_version() -> str: """Returns pybase64 version as a :class:`str` object. The result reports if the C extension is used or not. e.g. `1.0.0 (C extension active - AVX2)` """ simd_name = _get_simd_name(_get_simd_path()) if simd_name != "fallback": return f"{__version__} (C extension active - {simd_name})" return f"{__version__} (C extension inactive)" def standard_b64encode(s: Buffer) -> bytes: """Encode bytes using the standard Base64 alphabet. Argument ``s`` is a :term:`bytes-like object` to encode. The result is returned as a :class:`bytes` object. """ return b64encode(s) def standard_b64decode(s: str | Buffer) -> bytes: """Decode bytes encoded with the standard Base64 alphabet. Argument ``s`` is a :term:`bytes-like object` or ASCII string to decode. The result is returned as a :class:`bytes` object. A :exc:`binascii.Error` is raised if the input is incorrectly padded. Characters that are not in the standard alphabet are discarded prior to the padding check. """ return b64decode(s) def urlsafe_b64encode(s: Buffer) -> bytes: """Encode bytes using the URL- and filesystem-safe Base64 alphabet. Argument ``s`` is a :term:`bytes-like object` to encode. The result is returned as a :class:`bytes` object. The alphabet uses '-' instead of '+' and '_' instead of '/'. """ return b64encode(s, b"-_") def urlsafe_b64decode(s: str | Buffer) -> bytes: """Decode bytes using the URL- and filesystem-safe Base64 alphabet. Argument ``s`` is a :term:`bytes-like object` or ASCII string to decode. The result is returned as a :class:`bytes` object. A :exc:`binascii.Error` is raised if the input is incorrectly padded. Characters that are not in the URL-safe base-64 alphabet, and are not a plus '+' or slash '/', are discarded prior to the padding check. The alphabet uses '-' instead of '+' and '_' instead of '/'. """ return b64decode(s, b"-_") pybase64-1.4.3/src/pybase64/__main__.py000066400000000000000000000205221511500755200174740ustar00rootroot00000000000000from __future__ import annotations import argparse import base64 import sys from base64 import b64decode as b64decodeValidate from base64 import encodebytes as b64encodebytes from collections.abc import Sequence from pathlib import Path from timeit import default_timer as timer from typing import TYPE_CHECKING, Any import pybase64 if TYPE_CHECKING: from pybase64._typing import Decode, Encode, EncodeBytes def bench_one( duration: float, data: bytes, enc: Encode, dec: Decode, encbytes: EncodeBytes, altchars: bytes | None = None, validate: bool = False, ) -> None: duration = duration / 2.0 if not validate and altchars is None: number = 0 time = timer() while True: encodedcontent = encbytes(data) number += 1 if timer() - time > duration: break iter = number time = timer() while iter > 0: encodedcontent = encbytes(data) iter -= 1 time = timer() - time print( "{:<32s} {:9.3f} MB/s ({:,d} bytes -> {:,d} bytes)".format( encbytes.__module__ + "." + encbytes.__name__ + ":", ((number * len(data)) / (1024.0 * 1024.0)) / time, len(data), len(encodedcontent), ) ) number = 0 time = timer() while True: encodedcontent = enc(data, altchars=altchars) number += 1 if timer() - time > duration: break iter = number time = timer() while iter > 0: encodedcontent = enc(data, altchars=altchars) iter -= 1 time = timer() - time print( "{:<32s} {:9.3f} MB/s ({:,d} bytes -> {:,d} bytes)".format( enc.__module__ + "." + enc.__name__ + ":", ((number * len(data)) / (1024.0 * 1024.0)) / time, len(data), len(encodedcontent), ) ) number = 0 time = timer() while True: decodedcontent = dec(encodedcontent, altchars=altchars, validate=validate) number += 1 if timer() - time > duration: break iter = number time = timer() while iter > 0: decodedcontent = dec(encodedcontent, altchars=altchars, validate=validate) iter -= 1 time = timer() - time print( "{:<32s} {:9.3f} MB/s ({:,d} bytes -> {:,d} bytes)".format( dec.__module__ + "." + dec.__name__ + ":", ((number * len(data)) / (1024.0 * 1024.0)) / time, len(encodedcontent), len(data), ) ) assert decodedcontent == data def readall(file: str) -> bytes: if file == "-": return sys.stdin.buffer.read() return Path(file).read_bytes() def writeall(file: str, data: bytes) -> None: if file == "-": sys.stdout.buffer.write(data) else: Path(file).write_bytes(data) def benchmark(duration: float, input: str) -> None: print(__package__ + " " + pybase64.get_version()) data = readall(input) for altchars in [None, b"-_"]: for validate in [False, True]: print(f"bench: altchars={altchars!r:s}, validate={validate!r:s}") bench_one( duration, data, pybase64.b64encode, pybase64.b64decode, pybase64.encodebytes, altchars, validate, ) bench_one( duration, data, base64.b64encode, b64decodeValidate, b64encodebytes, altchars, validate, ) def encode(input: str, altchars: bytes | None, output: str) -> None: data = readall(input) data = pybase64.b64encode(data, altchars) writeall(output, data) def decode(input: str, altchars: bytes | None, validate: bool, output: str) -> None: data = readall(input) data = pybase64.b64decode(data, altchars, validate) writeall(output, data) class LicenseAction(argparse.Action): def __init__( self, option_strings: Sequence[str], dest: str, license: str | None = None, help: str | None = "show license information and exit", ): super().__init__( option_strings=option_strings, dest=dest, default=argparse.SUPPRESS, nargs=0, help=help, ) self.license = license def __call__( self, parser: argparse.ArgumentParser, namespace: argparse.Namespace, # noqa: ARG002 values: str | Sequence[Any] | None, # noqa: ARG002 option_string: str | None = None, # noqa: ARG002 ) -> None: print(self.license) parser.exit() def check_file(value: str, is_input: bool) -> str: if value == "-": return value path = Path(value) if is_input: return str(path.resolve(strict=True)) return str(path.parent.resolve(strict=True) / path.name) def main(argv: Sequence[str] | None = None) -> None: # main parser parser = argparse.ArgumentParser( prog=__package__, description=__package__ + " command-line tool." ) parser.add_argument( "-V", "--version", action="version", version=__package__ + " " + pybase64.get_version(), ) parser.add_argument("--license", action=LicenseAction, license=pybase64.get_license_text()) # create sub-parsers subparsers = parser.add_subparsers(help="tool help") # benchmark parser benchmark_parser = subparsers.add_parser("benchmark", help="-h for usage") benchmark_parser.add_argument( "-d", "--duration", metavar="D", dest="duration", type=float, default=1.0, help="expected duration for a single encode or decode test", ) benchmark_parser.register("type", "input file", lambda s: check_file(s, True)) benchmark_parser.add_argument( "input", type="input file", help="input file used for the benchmark" ) benchmark_parser.set_defaults(func=benchmark) # encode parser encode_parser = subparsers.add_parser("encode", help="-h for usage") encode_parser.register("type", "input file", lambda s: check_file(s, True)) encode_parser.register("type", "output file", lambda s: check_file(s, False)) encode_parser.add_argument("input", type="input file", help="input file to be encoded") group = encode_parser.add_mutually_exclusive_group() group.add_argument( "-u", "--url", action="store_const", const=b"-_", dest="altchars", help="use URL encoding", ) group.add_argument( "-a", "--altchars", dest="altchars", help="use alternative characters for encoding", ) encode_parser.add_argument( "-o", "--output", dest="output", type="output file", default="-", help="encoded output file (default to stdout)", ) encode_parser.set_defaults(func=encode) # decode parser decode_parser = subparsers.add_parser("decode", help="-h for usage") decode_parser.register("type", "input file", lambda s: check_file(s, True)) decode_parser.register("type", "output file", lambda s: check_file(s, False)) decode_parser.add_argument("input", type="input file", help="input file to be decoded") group = decode_parser.add_mutually_exclusive_group() group.add_argument( "-u", "--url", action="store_const", const=b"-_", dest="altchars", help="use URL decoding", ) group.add_argument( "-a", "--altchars", dest="altchars", help="use alternative characters for decoding", ) decode_parser.add_argument( "-o", "--output", dest="output", type="output file", default="-", help="decoded output file (default to stdout)", ) decode_parser.add_argument( "--no-validation", dest="validate", action="store_false", help="disable validation of the input data", ) decode_parser.set_defaults(func=decode) # ready, parse if argv is None: argv = sys.argv[1:] if len(argv) == 0: argv = ["-h"] args = vars(parser.parse_args(args=argv)) func = args.pop("func") func(**args) if __name__ == "__main__": main() pybase64-1.4.3/src/pybase64/_fallback.py000066400000000000000000000132501511500755200176520ustar00rootroot00000000000000from __future__ import annotations from base64 import b64decode as builtin_decode from base64 import b64encode as builtin_encode from base64 import encodebytes as builtin_encodebytes from binascii import Error as BinAsciiError from typing import TYPE_CHECKING if TYPE_CHECKING: from ._typing import Buffer _bytes_types = (bytes, bytearray) # Types acceptable as binary data def _get_simd_name(flags: int) -> str: assert flags == 0 return "fallback" def _get_simd_path() -> int: return 0 def _get_bytes(s: str | Buffer) -> bytes | bytearray: if isinstance(s, str): try: return s.encode("ascii") except UnicodeEncodeError: msg = "string argument should contain only ASCII characters" raise ValueError(msg) from None if isinstance(s, _bytes_types): return s try: mv = memoryview(s) if not mv.c_contiguous: msg = f"{s.__class__.__name__!r:s}: underlying buffer is not C-contiguous" raise BufferError(msg) return mv.tobytes() except TypeError: msg = ( "argument should be a bytes-like object or ASCII " f"string, not {s.__class__.__name__!r:s}" ) raise TypeError(msg) from None def b64decode( s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False ) -> bytes: """Decode bytes encoded with the standard Base64 alphabet. Argument ``s`` is a :term:`bytes-like object` or ASCII string to decode. Optional ``altchars`` must be a :term:`bytes-like object` or ASCII string of length 2 which specifies the alternative alphabet used instead of the '+' and '/' characters. If ``validate`` is ``False`` (the default), characters that are neither in the normal base-64 alphabet nor the alternative alphabet are discarded prior to the padding check. If ``validate`` is ``True``, these non-alphabet characters in the input result in a :exc:`binascii.Error`. The result is returned as a :class:`bytes` object. A :exc:`binascii.Error` is raised if ``s`` is incorrectly padded. """ s = _get_bytes(s) if altchars is not None: altchars = _get_bytes(altchars) if validate: if len(s) % 4 != 0: msg = "Incorrect padding" raise BinAsciiError(msg) result = builtin_decode(s, altchars, validate=False) # check length of result vs length of input expected_len = 0 if len(s) > 0: padding = 0 # len(s) % 4 != 0 implies len(s) >= 4 here if s[-2] == 61: # 61 == ord("=") padding += 1 if s[-1] == 61: padding += 1 expected_len = 3 * (len(s) // 4) - padding if expected_len != len(result): msg = "Non-base64 digit found" raise BinAsciiError(msg) return result return builtin_decode(s, altchars, validate=False) def b64decode_as_bytearray( s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False ) -> bytearray: """Decode bytes encoded with the standard Base64 alphabet. Argument ``s`` is a :term:`bytes-like object` or ASCII string to decode. Optional ``altchars`` must be a :term:`bytes-like object` or ASCII string of length 2 which specifies the alternative alphabet used instead of the '+' and '/' characters. If ``validate`` is ``False`` (the default), characters that are neither in the normal base-64 alphabet nor the alternative alphabet are discarded prior to the padding check. If ``validate`` is ``True``, these non-alphabet characters in the input result in a :exc:`binascii.Error`. The result is returned as a :class:`bytearray` object. A :exc:`binascii.Error` is raised if ``s`` is incorrectly padded. """ return bytearray(b64decode(s, altchars=altchars, validate=validate)) def b64encode(s: Buffer, altchars: str | Buffer | None = None) -> bytes: """Encode bytes using the standard Base64 alphabet. Argument ``s`` is a :term:`bytes-like object` to encode. Optional ``altchars`` must be a byte string of length 2 which specifies an alternative alphabet for the '+' and '/' characters. This allows an application to e.g. generate url or filesystem safe Base64 strings. The result is returned as a :class:`bytes` object. """ mv = memoryview(s) if not mv.c_contiguous: msg = f"{s.__class__.__name__!r:s}: underlying buffer is not C-contiguous" raise BufferError(msg) if altchars is not None: altchars = _get_bytes(altchars) return builtin_encode(s, altchars) def b64encode_as_string(s: Buffer, altchars: str | Buffer | None = None) -> str: """Encode bytes using the standard Base64 alphabet. Argument ``s`` is a :term:`bytes-like object` to encode. Optional ``altchars`` must be a byte string of length 2 which specifies an alternative alphabet for the '+' and '/' characters. This allows an application to e.g. generate url or filesystem safe Base64 strings. The result is returned as a :class:`str` object. """ return b64encode(s, altchars).decode("ascii") def encodebytes(s: Buffer) -> bytes: """Encode bytes into a bytes object with newlines (b'\\\\n') inserted after every 76 bytes of output, and ensuring that there is a trailing newline, as per :rfc:`2045` (MIME). Argument ``s`` is a :term:`bytes-like object` to encode. The result is returned as a :class:`bytes` object. """ mv = memoryview(s) if not mv.c_contiguous: msg = f"{s.__class__.__name__!r:s}: underlying buffer is not C-contiguous" raise BufferError(msg) return builtin_encodebytes(s) pybase64-1.4.3/src/pybase64/_license.pyi000066400000000000000000000000161511500755200177020ustar00rootroot00000000000000_license: str pybase64-1.4.3/src/pybase64/_pybase64.c000066400000000000000000000676351511500755200173620ustar00rootroot00000000000000#include "_pybase64_get_simd_flags.h" #define PY_SSIZE_T_CLEAN #define PY_CXX_CONST const #include #include #include #include #include #include /* memset */ #include #ifdef __SSE2__ #include #endif #if defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64) #define HAVE_FAST_UNALIGNED_ACCESS 1 #else #define HAVE_FAST_UNALIGNED_ACCESS 0 #endif typedef struct pybase64_state { PyObject *binAsciiError; uint32_t active_simd_flag; uint32_t simd_flags; int libbase64_simd_flag; } pybase64_state; #if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x030d0000 #define KW_CONST_CAST #else #define KW_CONST_CAST (char**) #endif /* returns 0 on success */ static int get_buffer(PyObject* object, Py_buffer* buffer) { if (PyObject_GetBuffer(object, buffer, PyBUF_RECORDS_RO | PyBUF_C_CONTIGUOUS) != 0) { return -1; } #if defined(PYPY_VERSION) /* PyPy does not respect PyBUF_C_CONTIGUOUS */ if (!PyBuffer_IsContiguous(buffer, 'C')) { PyBuffer_Release(buffer); PyErr_Format(PyExc_BufferError, "%R: underlying buffer is not C-contiguous", Py_TYPE(object)); return -1; } #endif return 0; } /* returns 0 on success */ static int parse_alphabet(PyObject* alphabetObject, char* alphabet, int* useAlphabet) { Py_buffer buffer; assert(useAlphabet != NULL); if ((alphabetObject == NULL) || (alphabetObject == Py_None)) { *useAlphabet = 0; return 0; } if (PyUnicode_Check(alphabetObject)) { alphabetObject = PyUnicode_AsASCIIString(alphabetObject); if (alphabetObject == NULL) { if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { PyErr_SetString(PyExc_ValueError, "string argument should contain only ASCII characters"); } return -1; } } else { Py_INCREF(alphabetObject); } if (get_buffer(alphabetObject, &buffer) != 0) { Py_DECREF(alphabetObject); return -1; } if (buffer.len != 2) { PyBuffer_Release(&buffer); Py_DECREF(alphabetObject); PyErr_SetString(PyExc_AssertionError, "len(altchars) != 2"); return -1; } *useAlphabet = 1; alphabet[0] = ((const char*)buffer.buf)[0]; alphabet[1] = ((const char*)buffer.buf)[1]; if ((alphabet[0] == '+') && (alphabet[1] == '/')) { *useAlphabet = 0; } PyBuffer_Release(&buffer); Py_DECREF(alphabetObject); return 0; } static void translate_inplace(char* pSrcDst, size_t len, const char* alphabet) { size_t i = 0U; const char c0 = alphabet[0]; const char c1 = alphabet[1]; #ifdef __SSE2__ if (len >= 16U) { const __m128i plus = _mm_set1_epi8('+'); const __m128i slash = _mm_set1_epi8('/'); const __m128i c0_ = _mm_set1_epi8(c0); const __m128i c1_ = _mm_set1_epi8(c1); for (; i < (len & ~(size_t)15U); i += 16) { __m128i srcDst = _mm_loadu_si128((const __m128i*)(pSrcDst + i)); __m128i m0 = _mm_cmpeq_epi8(srcDst, plus); __m128i m1 = _mm_cmpeq_epi8(srcDst, slash); srcDst = _mm_or_si128(_mm_andnot_si128(m0, srcDst), _mm_and_si128(m0, c0_)); srcDst = _mm_or_si128(_mm_andnot_si128(m1, srcDst), _mm_and_si128(m1, c1_)); _mm_storeu_si128((__m128i*)(pSrcDst + i), srcDst); } } #endif for (; i < len; ++i) { char c = pSrcDst[i]; if (c == '+') { pSrcDst[i] = c0; } else if (c == '/') { pSrcDst[i] = c1; } } } static void translate(const char* pSrc, char* pDst, size_t len, const char* alphabet) { size_t i = 0U; const char c0 = alphabet[0]; const char c1 = alphabet[1]; #ifdef __SSE2__ if (len >= 16U) { const __m128i plus = _mm_set1_epi8('+'); const __m128i slash = _mm_set1_epi8('/'); const __m128i c0_ = _mm_set1_epi8(c0); const __m128i c1_ = _mm_set1_epi8(c1); for (; i < (len & ~(size_t)15U); i += 16) { __m128i srcDst = _mm_loadu_si128((const __m128i*)(pSrc + i)); __m128i m0 = _mm_cmpeq_epi8(srcDst, c0_); __m128i m1 = _mm_cmpeq_epi8(srcDst, c1_); srcDst = _mm_or_si128(_mm_andnot_si128(m0, srcDst), _mm_and_si128(m0, plus)); srcDst = _mm_or_si128(_mm_andnot_si128(m1, srcDst), _mm_and_si128(m1, slash)); _mm_storeu_si128((__m128i*)(pDst + i), srcDst); } } #endif for (; i < len; ++i) { const char cs = pSrc[i]; char cd; if (cs == c0) { cd = '+'; } else if (cs == c1) { cd = '/'; } #if 0 /* TODO, python does not do this, add option */ else if (cs == '+') { cd = c0; } else if (cs == '/') { cd = c1; } #endif else { cd = cs; } pDst[i] = cd; } } static int next_valid_padding(const uint8_t *src, size_t srclen) { int ret = 255; while (srclen && (ret == 255)) { ret = base64_table_dec_8bit[*src++]; srclen--; } return ret; } static int decode_novalidate(const uint8_t *src, size_t srclen, uint8_t *out, size_t*outlen) { uint8_t* out_start = out; uint8_t carry; while (srclen > 0U) { /* case bytes == 0 */ while (srclen > 4U) { union { uint32_t asint; uint8_t aschar[4]; } x; x.asint = base64_table_dec_32bit_d0[src[0]] | base64_table_dec_32bit_d1[src[1]] | base64_table_dec_32bit_d2[src[2]] | base64_table_dec_32bit_d3[src[3]]; #if BASE64_LITTLE_ENDIAN /* LUTs for little-endian set Most Significant Bit in case of invalid character */ if (x.asint & 0x80000000U) break; #else /* LUTs for big-endian set Least Significant Bit in case of invalid character */ if (x.asint & 1U) break; #endif #if HAVE_FAST_UNALIGNED_ACCESS /* This might segfault or be too slow on some architectures, do this only if specified with HAVE_FAST_UNALIGNED_ACCESS macro We write one byte more than needed */ *(uint32_t*)out = x.asint; #else /* Fallback, write bytes one by one */ out[0] = x.aschar[0]; out[1] = x.aschar[1]; out[2] = x.aschar[2]; #endif src += 4; out += 3; srclen -= 4; } /* case bytes == 0, remainder */ { uint8_t c = *src++; srclen--; uint8_t q; if ((q = base64_table_dec_8bit[c]) >= 254) { continue; } carry = q << 2; } /* case bytes == 1 */ for(;;) { if (srclen-- == 0) { return 1; } uint8_t c = *src++; uint8_t q; if ((q = base64_table_dec_8bit[c]) >= 254) { continue; } *out++ = carry | (q >> 4); carry = q << 4; break; } /* case bytes == 2 */ for(;;) { if (srclen-- == 0) { return 1; } uint8_t c = *src++; uint8_t q; if ((q = base64_table_dec_8bit[c]) >= 254) { if (q == 254) { /* if the next valid byte is '=' => end */ if (next_valid_padding(src, srclen) == 254) { goto END; } } continue; } *out++ = carry | (q >> 2); carry = q << 6; break; } /* case bytes == 3 */ for(;;) { if (srclen-- == 0) { return 1; } uint8_t c = *src++; uint8_t q; if ((q = base64_table_dec_8bit[c]) >= 254) { if (q == 254) { srclen = 0U; break; } continue; } *out++ = carry | q; break; } } END: *outlen = out - out_start; return 0; } static PyObject* pybase64_encode_impl(PyObject* self, PyObject* args, PyObject *kwds, int return_string) { static const char *kwlist[] = { "", "altchars", NULL }; int use_alphabet = 0; char alphabet[2]; Py_buffer buffer; size_t out_len; PyObject* out_object; PyObject* in_object; PyObject* in_alphabet = NULL; char* dst; pybase64_state *state = (pybase64_state*)PyModule_GetState(self); if (state == NULL) { return NULL; } /* Parse the input tuple */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", KW_CONST_CAST kwlist, &in_object, &in_alphabet)) { return NULL; } if (parse_alphabet(in_alphabet, alphabet, &use_alphabet) != 0) { return NULL; } if (get_buffer(in_object, &buffer) != 0) { return NULL; } if (buffer.len > (3 * (PY_SSIZE_T_MAX / 4))) { PyBuffer_Release(&buffer); return PyErr_NoMemory(); } out_len = (size_t)(((buffer.len + 2) / 3) * 4); if (return_string) { out_object = PyUnicode_New((Py_ssize_t)out_len, 127); } else { out_object = PyBytes_FromStringAndSize(NULL, (Py_ssize_t)out_len); } if (out_object == NULL) { PyBuffer_Release(&buffer); return NULL; } if (return_string) { dst = (char*)PyUnicode_1BYTE_DATA(out_object); } else { dst = PyBytes_AS_STRING(out_object); } /* not interacting with Python objects from here, release the GIL */ Py_BEGIN_ALLOW_THREADS int const libbase64_simd_flag = state->libbase64_simd_flag; if (use_alphabet) { /* TODO, make this more efficient */ const size_t dst_slice = 16U * 1024U; const Py_ssize_t src_slice = (Py_ssize_t)((dst_slice / 4U) * 3U); Py_ssize_t len = buffer.len; const char* src = (const char*)buffer.buf; size_t remainder; while (out_len > dst_slice) { size_t dst_len = dst_slice; base64_encode(src, src_slice, dst, &dst_len, libbase64_simd_flag); translate_inplace(dst, dst_slice, alphabet); len -= src_slice; src += src_slice; out_len -= dst_slice; dst += dst_slice; } remainder = out_len; base64_encode(src, len, dst, &out_len, libbase64_simd_flag); translate_inplace(dst, remainder, alphabet); } else { base64_encode(buffer.buf, buffer.len, dst, &out_len, libbase64_simd_flag); } /* restore the GIL */ Py_END_ALLOW_THREADS PyBuffer_Release(&buffer); return out_object; } static PyObject* pybase64_encode(PyObject* self, PyObject* args, PyObject *kwds) { return pybase64_encode_impl(self, args, kwds, 0); } static PyObject* pybase64_encode_as_string(PyObject* self, PyObject* args, PyObject *kwds) { return pybase64_encode_impl(self, args, kwds, 1); } static PyObject* pybase64_decode_impl(PyObject* self, PyObject* args, PyObject *kwds, int return_bytearray) { static const char *kwlist[] = { "", "altchars", "validate", NULL }; int use_alphabet = 0; char alphabet[2]; char validation = 0; Py_buffer buffer; size_t out_len; PyObject* in_alphabet = NULL; PyObject* in_object; PyObject* out_object = NULL; const void* source = NULL; Py_ssize_t source_len; int source_use_buffer = 0; void* dest; pybase64_state *state = (pybase64_state*)PyModule_GetState(self); if (state == NULL) { return NULL; } /* Parse the input tuple */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Ob", KW_CONST_CAST kwlist, &in_object, &in_alphabet, &validation)) { return NULL; } if (parse_alphabet(in_alphabet, alphabet, &use_alphabet) != 0) { return NULL; } if (PyUnicode_Check(in_object)) { if ((PyUnicode_READY(in_object) == 0) && (PyUnicode_KIND(in_object) == PyUnicode_1BYTE_KIND)) { source = PyUnicode_1BYTE_DATA(in_object); source_len = PyUnicode_GET_LENGTH(in_object); } else { in_object = PyUnicode_AsASCIIString(in_object); if (in_object == NULL) { if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { PyErr_SetString(PyExc_ValueError, "string argument should contain only ASCII characters"); } return NULL; } } } else { Py_INCREF(in_object); } if (source == NULL) { if (get_buffer(in_object, &buffer) != 0) { Py_DECREF(in_object); return NULL; } source = buffer.buf; source_len = buffer.len; source_use_buffer = 1; } /* TRY: */ if (!validation && use_alphabet) { PyObject* translate_object; char* translate_dst; translate_object = PyBytes_FromStringAndSize(NULL, source_len); if (translate_object == NULL) { goto EXCEPT; } translate_dst = PyBytes_AS_STRING(translate_object); /* not interacting with Python objects from here, release the GIL */ Py_BEGIN_ALLOW_THREADS translate(source, translate_dst, source_len, alphabet); /* restore the GIL */ Py_END_ALLOW_THREADS if (source_use_buffer) { PyBuffer_Release(&buffer); Py_DECREF(in_object); } in_object = translate_object; if (get_buffer(in_object, &buffer) != 0) { Py_DECREF(in_object); return NULL; } source = buffer.buf; source_len = buffer.len; source_use_buffer = 1; } /* No overflow check needed, exact out_len recomputed at the end */ /* out_len is ceildiv(len / 4) * 3 when len % 4 != 0*/ /* else out_len is (ceildiv(len / 4) + 1) * 3 */ out_len = (size_t)((source_len / 4) * 3) + 3U; if (return_bytearray) { out_object = PyByteArray_FromStringAndSize(NULL, (Py_ssize_t)out_len); } else { out_object = PyBytes_FromStringAndSize(NULL, (Py_ssize_t)out_len); } if (out_object == NULL) { goto EXCEPT; } if (return_bytearray) { dest = PyByteArray_AS_STRING(out_object); } else { dest = PyBytes_AS_STRING(out_object); } if (!validation) { int result; /* not interacting with Python objects from here, release the GIL */ Py_BEGIN_ALLOW_THREADS result = decode_novalidate(source, source_len, dest, &out_len); /* restore the GIL */ Py_END_ALLOW_THREADS if (result != 0) { PyErr_SetString(state->binAsciiError, "Incorrect padding"); goto EXCEPT; } } else if (use_alphabet) { /* TODO, make this more efficient */ const Py_ssize_t src_slice = 16 * 1024; const size_t dst_slice = (src_slice / 4) * 3; char cache[16 * 1024]; Py_ssize_t len = source_len; const char* src = source; char* dst = dest; int result = 1; /* not interacting with Python objects from here, release the GIL */ Py_BEGIN_ALLOW_THREADS int const libbase64_simd_flag = state->libbase64_simd_flag; while (len > src_slice) { size_t dst_len = dst_slice; translate(src, cache, src_slice, alphabet); result = base64_decode(cache, src_slice, dst, &dst_len, libbase64_simd_flag); if (result <= 0) { break; } len -= src_slice; src += src_slice; out_len -= dst_slice; dst += dst_slice; } if (result > 0) { translate(src, cache, len, alphabet); result = base64_decode(cache, len, dst, &out_len, libbase64_simd_flag); } /* restore the GIL */ Py_END_ALLOW_THREADS if (result <= 0) { PyErr_SetString(state->binAsciiError, "Non-base64 digit found"); goto EXCEPT; } out_len += (dst - (char*)dest); } else { int result; /* not interacting with Python objects from here, release the GIL */ Py_BEGIN_ALLOW_THREADS result = base64_decode(source, source_len, dest, &out_len, state->libbase64_simd_flag); /* restore the GIL */ Py_END_ALLOW_THREADS if (result <= 0) { PyErr_SetString(state->binAsciiError, "Non-base64 digit found"); goto EXCEPT; } } if (return_bytearray) { PyByteArray_Resize(out_object, (Py_ssize_t)out_len); } else { _PyBytes_Resize(&out_object, (Py_ssize_t)out_len); } goto FINALLY; EXCEPT: if (out_object != NULL) { Py_DECREF(out_object); out_object = NULL; } FINALLY: if (source_use_buffer) { PyBuffer_Release(&buffer); Py_DECREF(in_object); } return out_object; } static PyObject* pybase64_decode(PyObject* self, PyObject* args, PyObject *kwds) { return pybase64_decode_impl(self, args, kwds, 0); } static PyObject* pybase64_decode_as_bytearray(PyObject* self, PyObject* args, PyObject *kwds) { return pybase64_decode_impl(self, args, kwds, 1); } static PyObject* pybase64_encodebytes(PyObject* self, PyObject* in_object) { Py_buffer buffer; size_t out_len; PyObject* out_object; pybase64_state *state = (pybase64_state*)PyModule_GetState(self); if (state == NULL) { return NULL; } if (get_buffer(in_object, &buffer) != 0) { return NULL; } if (((buffer.format[0] != 'c') && (buffer.format[0] != 'b') && (buffer.format[0] != 'B')) || buffer.format[1] != '\0' ) { PyBuffer_Release(&buffer); return PyErr_Format(PyExc_TypeError, "expected single byte elements, not '%s' from %R", buffer.format, Py_TYPE(in_object)); } if (buffer.ndim != 1) { PyBuffer_Release(&buffer); return PyErr_Format(PyExc_TypeError, "expected 1-D data, not %d-D data from %R", buffer.ndim, Py_TYPE(in_object)); } if (buffer.len > (3 * (PY_SSIZE_T_MAX / 4))) { PyBuffer_Release(&buffer); return PyErr_NoMemory(); } out_len = (size_t)(((buffer.len + 2) / 3) * 4); if (out_len != 0U) { if ((((out_len - 1U) / 76U) + 1U) > (PY_SSIZE_T_MAX - out_len)) { PyBuffer_Release(&buffer); return PyErr_NoMemory(); } out_len += ((out_len - 1U) / 76U) + 1U; } out_object = PyBytes_FromStringAndSize(NULL, (Py_ssize_t)out_len); if (out_object == NULL) { PyBuffer_Release(&buffer); return NULL; } if (out_len > 0) { const size_t dst_slice = 77U; const Py_ssize_t src_slice = (Py_ssize_t)((dst_slice / 4U) * 3U); Py_ssize_t len = buffer.len; const char* src = (const char*)buffer.buf; char* dst = PyBytes_AS_STRING(out_object); size_t remainder; /* not interacting with Python objects from here, release the GIL */ Py_BEGIN_ALLOW_THREADS int const libbase64_simd_flag = state->libbase64_simd_flag; while (out_len > dst_slice) { size_t dst_len = dst_slice - 1U; base64_encode(src, src_slice, dst, &dst_len, libbase64_simd_flag); dst[dst_slice - 1U] = '\n'; len -= src_slice; src += src_slice; out_len -= dst_slice; dst += dst_slice; } remainder = out_len - 1; base64_encode(src, len, dst, &remainder, libbase64_simd_flag); dst[out_len - 1] = '\n'; /* restore the GIL */ Py_END_ALLOW_THREADS } PyBuffer_Release(&buffer); return out_object; } static PyObject* pybase64_get_simd_path(PyObject* self, PyObject* arg) { pybase64_state *state = (pybase64_state*)PyModule_GetState(self); if (state == NULL) { return NULL; } return PyLong_FromUnsignedLong(state->active_simd_flag); } static PyObject* pybase64_get_simd_flags_runtime(PyObject* self, PyObject* arg) { pybase64_state *state = (pybase64_state*)PyModule_GetState(self); if (state == NULL) { return NULL; } return PyLong_FromUnsignedLong(state->simd_flags); } static PyObject* pybase64_get_simd_flags_compile(PyObject* self, PyObject* arg) { uint32_t result = 0U; #if BASE64_WITH_NEON64 || BASE64_WITH_NEON32 result |= PYBASE64_NEON; #endif #if BASE64_WITH_AVX512 result |= PYBASE64_AVX512VBMI; #endif #if BASE64_WITH_AVX2 result |= PYBASE64_AVX2; #endif #if BASE64_WITH_AVX result |= PYBASE64_AVX; #endif #if BASE64_WITH_SSE42 result |= PYBASE64_SSE42; #endif #if BASE64_WITH_SSE41 result |= PYBASE64_SSE41; #endif #if BASE64_WITH_SSSE3 result |= PYBASE64_SSSE3; #endif return PyLong_FromUnsignedLong(result); } static void set_simd_path(pybase64_state* state, uint32_t flag) { flag &= state->simd_flags; /* clean-up with allowed flags */ if (0) { } #if BASE64_WITH_NEON64 else if (flag & PYBASE64_NEON) { state->active_simd_flag = PYBASE64_NEON; state->libbase64_simd_flag = BASE64_FORCE_NEON64; } #endif #if BASE64_WITH_NEON32 else if (flag & PYBASE64_NEON) { state->active_simd_flag = PYBASE64_NEON; state->libbase64_simd_flag = BASE64_FORCE_NEON32; } #endif #if BASE64_WITH_AVX512 else if (flag & PYBASE64_AVX512VBMI) { state->active_simd_flag = PYBASE64_AVX512VBMI; state->libbase64_simd_flag = BASE64_FORCE_AVX512; } #endif #if BASE64_WITH_AVX2 else if (flag & PYBASE64_AVX2) { state->active_simd_flag = PYBASE64_AVX2; state->libbase64_simd_flag = BASE64_FORCE_AVX2; } #endif #if BASE64_WITH_AVX else if (flag & PYBASE64_AVX) { state->active_simd_flag = PYBASE64_AVX; state->libbase64_simd_flag = BASE64_FORCE_AVX; } #endif #if BASE64_WITH_SSE42 else if (flag & PYBASE64_SSE42) { state->active_simd_flag = PYBASE64_SSE42; state->libbase64_simd_flag = BASE64_FORCE_SSE42; } #endif #if BASE64_WITH_SSE41 else if (flag & PYBASE64_SSE41) { state->active_simd_flag = PYBASE64_SSE41; state->libbase64_simd_flag = BASE64_FORCE_SSE41; } #endif #if BASE64_WITH_SSSE3 else if (flag & PYBASE64_SSSE3) { state->active_simd_flag = PYBASE64_SSSE3; state->libbase64_simd_flag = BASE64_FORCE_SSSE3; } #endif else { state->active_simd_flag = PYBASE64_NONE; state->libbase64_simd_flag = BASE64_FORCE_PLAIN; } } static PyObject* pybase64_set_simd_path(PyObject* self, PyObject* arg) { pybase64_state *state = (pybase64_state*)PyModule_GetState(self); if (state == NULL) { return NULL; } set_simd_path(state, (uint32_t)PyLong_AsUnsignedLong(arg)); Py_RETURN_NONE; } static PyObject* pybase64_get_simd_name(PyObject* self, PyObject* arg) { uint32_t flags = (uint32_t)PyLong_AsUnsignedLong(arg); if (flags & PYBASE64_NEON) { return PyUnicode_FromString("NEON"); } if (flags & PYBASE64_AVX512VBMI) { return PyUnicode_FromString("AVX512VBMI"); } if (flags & PYBASE64_AVX2) { return PyUnicode_FromString("AVX2"); } if (flags & PYBASE64_AVX) { return PyUnicode_FromString("AVX"); } if (flags & PYBASE64_SSE42) { return PyUnicode_FromString("SSE42"); } if (flags & PYBASE64_SSE41) { return PyUnicode_FromString("SSE41"); } if (flags & PYBASE64_SSSE3) { return PyUnicode_FromString("SSSE3"); } if (flags & PYBASE64_SSE3) { return PyUnicode_FromString("SSE3"); } if (flags & PYBASE64_SSE2) { return PyUnicode_FromString("SSE2"); } if (flags != 0) { return PyUnicode_FromString("unknown"); } return PyUnicode_FromString("No SIMD"); } static PyObject* pybase64_import(const char* from, const char* object) { PyObject* subModules; PyObject* subModuleName; PyObject* moduleName; PyObject* imports; PyObject* importedObject; subModules = PyList_New(1); if (subModules == NULL) { return NULL; } moduleName = PyUnicode_FromString(from); if (moduleName == NULL) { Py_DECREF(subModules); return NULL; } subModuleName = PyUnicode_FromString(object); if (subModuleName == NULL) { Py_DECREF(moduleName); Py_DECREF(subModules); return NULL; } Py_INCREF(subModuleName); PyList_SET_ITEM(subModules, 0, subModuleName); imports = PyImport_ImportModuleLevelObject(moduleName, NULL, NULL, subModules, 0); Py_DECREF(moduleName); Py_DECREF(subModules); if (imports == NULL) { Py_DECREF(subModuleName); return NULL; } importedObject = PyObject_GetAttr(imports, subModuleName); Py_DECREF(subModuleName); Py_DECREF(imports); return importedObject; } static PyObject* pybase64_import_BinAsciiError() { PyObject* binAsciiError; binAsciiError = pybase64_import("binascii", "Error"); if (binAsciiError == NULL) { return NULL; } if (!PyObject_IsSubclass(binAsciiError, PyExc_Exception)) { Py_DECREF(binAsciiError); return NULL; } return binAsciiError; } static int _pybase64_exec(PyObject *m) { pybase64_state *state = (pybase64_state*)PyModule_GetState(m); if (state == NULL) { return -1; } state->binAsciiError = pybase64_import_BinAsciiError(); if (state->binAsciiError == NULL) { return -1; } Py_INCREF(state->binAsciiError); /* PyModule_AddObject steals a reference */ if (PyModule_AddObject(m, "_BinAsciiError", state->binAsciiError) != 0) { Py_DECREF(state->binAsciiError); return -1; } state->simd_flags = pybase64_get_simd_flags(); set_simd_path(state, state->simd_flags); return 0; } static int _pybase64_traverse(PyObject *m, visitproc visit, void *arg) { pybase64_state *state = (pybase64_state*)PyModule_GetState(m); if (state) { Py_VISIT(state->binAsciiError); } return 0; } static int _pybase64_clear(PyObject *m) { pybase64_state *state = (pybase64_state*)PyModule_GetState(m); if (state) { Py_CLEAR(state->binAsciiError); } return 0; } static void _pybase64_free(void *m) { _pybase64_clear((PyObject *)m); } static PyMethodDef _pybase64_methods[] = { { "b64encode", (PyCFunction)pybase64_encode, METH_VARARGS | METH_KEYWORDS, NULL }, { "b64encode_as_string", (PyCFunction)pybase64_encode_as_string, METH_VARARGS | METH_KEYWORDS, NULL }, { "b64decode", (PyCFunction)pybase64_decode, METH_VARARGS | METH_KEYWORDS, NULL }, { "b64decode_as_bytearray", (PyCFunction)pybase64_decode_as_bytearray, METH_VARARGS | METH_KEYWORDS, NULL }, { "encodebytes", (PyCFunction)pybase64_encodebytes, METH_O, NULL }, { "_get_simd_path", (PyCFunction)pybase64_get_simd_path, METH_NOARGS, NULL }, { "_set_simd_path", (PyCFunction)pybase64_set_simd_path, METH_O, NULL }, { "_get_simd_flags_compile", (PyCFunction)pybase64_get_simd_flags_compile, METH_NOARGS, NULL }, { "_get_simd_flags_runtime", (PyCFunction)pybase64_get_simd_flags_runtime, METH_NOARGS, NULL }, { "_get_simd_name", (PyCFunction)pybase64_get_simd_name, METH_O, NULL }, { NULL, NULL, 0, NULL } /* Sentinel */ }; static PyModuleDef_Slot _pybase64_slots[] = { {Py_mod_exec, _pybase64_exec}, #ifdef Py_mod_multiple_interpreters {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, #endif #ifdef Py_mod_gil {Py_mod_gil, Py_MOD_GIL_NOT_USED}, #endif {0, NULL} }; /* Initialize this module. */ static struct PyModuleDef _pybase64_module = { PyModuleDef_HEAD_INIT, "pybase64._pybase64", NULL, sizeof(pybase64_state), _pybase64_methods, _pybase64_slots, _pybase64_traverse, _pybase64_clear, _pybase64_free }; PyMODINIT_FUNC PyInit__pybase64(void) { return PyModuleDef_Init(&_pybase64_module); } pybase64-1.4.3/src/pybase64/_pybase64.pyi000066400000000000000000000012471511500755200177240ustar00rootroot00000000000000from ._typing import Buffer def _get_simd_flags_compile() -> int: ... def _get_simd_flags_runtime() -> int: ... def _get_simd_name(flags: int) -> str: ... def _get_simd_path() -> int: ... def _set_simd_path(flags: int) -> None: ... def b64decode( s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False ) -> bytes: ... def b64decode_as_bytearray( s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False ) -> bytearray: ... def b64encode(s: Buffer, altchars: str | Buffer | None = None) -> bytes: ... def b64encode_as_string(s: Buffer, altchars: str | Buffer | None = None) -> str: ... def encodebytes(s: Buffer) -> bytes: ... pybase64-1.4.3/src/pybase64/_pybase64_get_simd_flags.c000066400000000000000000000100541511500755200223700ustar00rootroot00000000000000#include "_pybase64_get_simd_flags.h" #include #if defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64) /* x86 version */ #if defined(_MSC_VER) #include /* cpuid */ static void cpuid_(uint32_t leaf, uint32_t subleaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) { int info[4]; __cpuidex(info, (int)leaf, (int)subleaf); *eax = (uint32_t)info[0]; *ebx = (uint32_t)info[1]; *ecx = (uint32_t)info[2]; *edx = (uint32_t)info[3]; } #elif defined(__GNUC__) #include /* __cpuid_count */ static void cpuid_(uint32_t leaf, uint32_t subleaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) { __cpuid_count(leaf, subleaf, *eax, *ebx, *ecx, *edx); } static uint64_t _xgetbv (uint32_t index) { uint32_t eax, edx; __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index)); return ((uint64_t)edx << 32) | eax; } #else /* not supported yet */ static void cpuid_(uint32_t leaf, uint32_t subleaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) { (void)subleaf; (void)ebx; (void)ecx; (void)edx; if (leaf == 0) { *eax = 0U; /* max-level 0 */ } } static uint64_t _xgetbv (uint32_t index) { (void)index; return 0U; } #endif #define PB64_SSE2_BIT_LVL1_EDX (UINT32_C(1) << 26) #define PB64_SSE3_BIT_LVL1_ECX (UINT32_C(1) << 0) #define PB64_SSSE3_BIT_LVL1_ECX (UINT32_C(1) << 9) #define PB64_SSE41_BIT_LVL1_ECX (UINT32_C(1) << 19) #define PB64_SSE42_BIT_LVL1_ECX (UINT32_C(1) << 20) #define PB64_AVX_BIT_LVL1_ECX (UINT32_C(1) << 28) #define PB64_AVX2_BIT_LVL7_EBX (UINT32_C(1) << 5) #define PB64_AVX512F_BIT_LVL7_EBX (UINT32_C(1) << 16) #define PB64_AVX512VL_BIT_LVL7_EBX (UINT32_C(1) << 31) #define PB64_AVX512VBMI_BIT_LVL7_ECX (UINT32_C(1) << 1) #define PB64_OSXSAVE_BIT_LVL1_ECX (UINT32_C(1) << 27) #define PB64_XCR0_SSE_BIT (UINT64_C(1) << 1) #define PB64_XCR0_AVX_BIT (UINT64_C(1) << 2) #define PB64_XCR0_OPMASK_BIT (UINT64_C(1) << 5) #define PB64_XCR0_ZMM_HI256_BIT (UINT64_C(1) << 6) #define PB64_XCR0_HI16_ZMM_BIT (UINT64_C(1) << 7) #define PB64_XCR0_AVX_SUPPORT_MASK (PB64_XCR0_SSE_BIT | PB64_XCR0_AVX_BIT) #define PB64_XCR0_AVX512_SUPPORT_MASK (PB64_XCR0_AVX_SUPPORT_MASK | PB64_XCR0_OPMASK_BIT | PB64_XCR0_ZMM_HI256_BIT | PB64_XCR0_HI16_ZMM_BIT) #define PB64_CHECK(reg_, bits_) (((reg_) & (bits_)) == (bits_)) uint32_t pybase64_get_simd_flags(void) { uint32_t result = 0U; uint32_t eax, ebx, ecx, edx; uint32_t max_level; uint64_t xcr0 = 0U; /* get max level */ cpuid_(0U, 0U, &max_level, &ebx, &ecx, &edx); if (max_level >= 1) { cpuid_(1U, 0U, &eax, &ebx, &ecx, &edx); if (PB64_CHECK(edx, PB64_SSE2_BIT_LVL1_EDX)) { result |= PYBASE64_SSE2; } if (PB64_CHECK(ecx, PB64_SSE3_BIT_LVL1_ECX)) { result |= PYBASE64_SSE3; } if (PB64_CHECK(ecx, PB64_SSSE3_BIT_LVL1_ECX)) { result |= PYBASE64_SSSE3; } if (PB64_CHECK(ecx, PB64_SSE41_BIT_LVL1_ECX)) { result |= PYBASE64_SSE41; } if (PB64_CHECK(ecx, PB64_SSE42_BIT_LVL1_ECX)) { result |= PYBASE64_SSE42; } if (PB64_CHECK(ecx, PB64_OSXSAVE_BIT_LVL1_ECX)) { /* OSXSAVE (implies XSAVE/XRESTOR/XGETBV) */ xcr0 = _xgetbv(0U /* XFEATURE_ENABLED_MASK/XCR0 */); if (PB64_CHECK(xcr0, PB64_XCR0_AVX_SUPPORT_MASK)) { /* XMM/YMM saved by OS */ if (ecx & PB64_AVX_BIT_LVL1_ECX) { result |= PYBASE64_AVX; } } } } if (max_level >= 7) { cpuid_(7U, 0U, &eax, &ebx, &ecx, &edx); if (result & PYBASE64_AVX) { /* check AVX supported for YMM saved by OS */ if (PB64_CHECK(ebx, PB64_AVX2_BIT_LVL7_EBX)) { result |= PYBASE64_AVX2; } if (PB64_CHECK(xcr0, PB64_XCR0_AVX512_SUPPORT_MASK)) {/* OpMask/ZMM/ZMM16-31 saved by OS */ if (PB64_CHECK(ebx, PB64_AVX512F_BIT_LVL7_EBX) && PB64_CHECK(ebx, PB64_AVX512VL_BIT_LVL7_EBX) && PB64_CHECK(ecx, PB64_AVX512VBMI_BIT_LVL7_ECX)) { result |= PYBASE64_AVX512VBMI; } } } } return result; } #else /* default version */ uint32_t pybase64_get_simd_flags(void) { #if BASE64_WITH_NEON64 || defined(__ARM_NEON__) || defined(__ARM_NEON) return PYBASE64_NEON; #endif return 0U; } #endif pybase64-1.4.3/src/pybase64/_pybase64_get_simd_flags.h000066400000000000000000000007061511500755200224000ustar00rootroot00000000000000#define PYBASE64_NONE 0x00000000 #define PYBASE64_SSE2 0x00000001 #define PYBASE64_SSE3 0x00000002 #define PYBASE64_SSSE3 0x00000004 #define PYBASE64_SSE41 0x00000008 #define PYBASE64_SSE42 0x00000010 #define PYBASE64_AVX 0x00000020 #define PYBASE64_AVX2 0x00000040 #define PYBASE64_AVX512VBMI 0x00000080 #define PYBASE64_NEON 0x00010000 #include uint32_t pybase64_get_simd_flags(void); pybase64-1.4.3/src/pybase64/_typing.py000066400000000000000000000013051511500755200174230ustar00rootroot00000000000000from __future__ import annotations import sys from typing import Protocol if sys.version_info < (3, 12): from typing_extensions import Buffer else: from collections.abc import Buffer class Decode(Protocol): __name__: str __module__: str def __call__( self, s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False ) -> bytes: ... class Encode(Protocol): __name__: str __module__: str def __call__(self, s: Buffer, altchars: Buffer | None = None) -> bytes: ... class EncodeBytes(Protocol): __name__: str __module__: str def __call__(self, s: Buffer) -> bytes: ... __all__ = ("Buffer", "Decode", "Encode", "EncodeBytes") pybase64-1.4.3/src/pybase64/_version.py000066400000000000000000000000671511500755200176020ustar00rootroot00000000000000from __future__ import annotations _version = "1.4.3" pybase64-1.4.3/src/pybase64/py.typed000066400000000000000000000000001511500755200170660ustar00rootroot00000000000000pybase64-1.4.3/tests/000077500000000000000000000000001511500755200143175ustar00rootroot00000000000000pybase64-1.4.3/tests/__init__.py000066400000000000000000000000001511500755200164160ustar00rootroot00000000000000pybase64-1.4.3/tests/conftest.py000066400000000000000000000006411511500755200165170ustar00rootroot00000000000000from __future__ import annotations import pytest from . import utils simd = utils.simd @pytest.fixture(autouse=True) def _autoskip_benchmark(request: pytest.FixtureRequest): marker = request.node.get_closest_marker("benchmark") benchmark_running = request.config.getoption("--codspeed", default=False) if marker is not None and not benchmark_running: pytest.skip("needs '--codspeed' to run") pybase64-1.4.3/tests/test_benchmark.py000066400000000000000000000025441511500755200176670ustar00rootroot00000000000000import pytest import pybase64 from . import utils pytestmark = pytest.mark.benchmark @pytest.fixture(scope="module") def encode_data_full(request: pytest.FixtureRequest) -> bytes: if not request.config.getoption("--codspeed", default=False): pytest.skip("needs '--codspeed' to run") data_ = bytearray(i % 256 for i in range(1024 * 1024)) data = bytearray(512 * 1024 * 1024) chunk_start = 0 chunk_end = len(data_) while chunk_start < len(data): data[chunk_start:chunk_end] = data_ chunk_start += len(data_) chunk_end += len(data_) return bytes(data) @pytest.fixture(scope="module", params=(1, 1024, 1024 * 1024, 512 * 1024 * 1024)) def encode_data(request: pytest.FixtureRequest, encode_data_full: bytes) -> bytes: return encode_data_full[: request.param] @pytest.fixture(scope="module") def decode_data(encode_data: bytes) -> bytes: return pybase64.b64encode(encode_data) @utils.param_simd def test_encoding(simd: int, encode_data: bytearray) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests pybase64.b64encode(encode_data) @utils.param_simd def test_decoding(simd: int, decode_data: bytearray) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests pybase64.b64decode(decode_data, validate=True) pybase64-1.4.3/tests/test_main.py000066400000000000000000000103161511500755200166550ustar00rootroot00000000000000from __future__ import annotations import re import sys from collections.abc import Iterator, Sequence from pathlib import Path import pytest import pybase64 from pybase64.__main__ import main @pytest.fixture def emptyfile(tmp_path: Path) -> Iterator[str]: _file = tmp_path / "empty" _file.write_bytes(b"") yield str(_file) _file.unlink() @pytest.fixture def hellofile(tmp_path: Path) -> Iterator[str]: _file = tmp_path / "helloworld" _file.write_bytes(b"hello world !/?\n") yield str(_file) _file.unlink() def idfn_test_help(args: Sequence[str]) -> str: if len(args) == 0: return "(empty)" return " ".join(args) @pytest.mark.parametrize( "args", [ [], ["-h"], ["benchmark", "-h"], ["encode", "-h"], ["decode", "-h"], ], ids=idfn_test_help, ) def test_help(capsys: pytest.CaptureFixture[str], args: Sequence[str]) -> None: command = "pybase64" if len(args) == 2: command += f" {args[0]}" usage = f"usage: {command} [-h]" with pytest.raises(SystemExit) as exit_info: main(args) captured = capsys.readouterr() assert captured.err == "" assert captured.out.startswith(usage) assert exit_info.value.code == 0 def test_version(capsys: pytest.CaptureFixture[str]) -> None: with pytest.raises(SystemExit) as exit_info: main(["-V"]) captured = capsys.readouterr() assert captured.err == "" assert captured.out.startswith("pybase64 " + pybase64.__version__) assert exit_info.value.code == 0 def test_license(capsys: pytest.CaptureFixture[str]) -> None: restr = "\n".join(x + "\n[=]+\n.*Copyright.*\n[=]+\n" for x in ["pybase64", "libbase64"]) regex = re.compile("^" + restr + "$", re.DOTALL) with pytest.raises(SystemExit) as exit_info: main(["--license"]) captured = capsys.readouterr() assert captured.err == "" assert regex.match(captured.out) assert exit_info.value.code == 0 def test_benchmark(capsys: pytest.CaptureFixture[str], emptyfile: str) -> None: main(["benchmark", "-d", "0.005", emptyfile]) captured = capsys.readouterr() assert captured.err == "" assert captured.out != "" @pytest.mark.parametrize( ("args", "expect"), [ ([], b"aGVsbG8gd29ybGQgIS8/Cg=="), (["-u"], b"aGVsbG8gd29ybGQgIS8_Cg=="), (["-a", ":,"], b"aGVsbG8gd29ybGQgIS8,Cg=="), ], ids=["0", "1", "2"], ) def test_encode( capsysbinary: pytest.CaptureFixture[bytes], hellofile: str, args: Sequence[str], expect: bytes ) -> None: main(["encode", *args, hellofile]) captured = capsysbinary.readouterr() assert captured.err == b"" assert captured.out == expect def test_encode_ouputfile( capsys: pytest.CaptureFixture[str], emptyfile: str, hellofile: str ) -> None: main(["encode", "-o", hellofile, emptyfile]) captured = capsys.readouterr() assert captured.err == "" assert captured.out == "" with open(hellofile, "rb") as f: data = f.read() assert data == b"" @pytest.mark.parametrize( ("args", "b64string"), [ ([], b"aGVsbG8gd29ybGQgIS8/Cg=="), (["-u"], b"aGVsbG8gd29ybGQgIS8_Cg=="), (["-a", ":,"], b"aGVsbG8gd29ybGQgIS8,Cg=="), (["--no-validation"], b"aGVsbG8gd29yb GQgIS8/Cg==\n"), ], ids=["0", "1", "2", "3"], ) def test_decode( capsysbinary: pytest.CaptureFixture[bytes], tmp_path: Path, args: Sequence[str], b64string: bytes, ) -> None: input_file = tmp_path / "in" input_file.write_bytes(b64string) main(["decode", *args, str(input_file)]) captured = capsysbinary.readouterr() assert captured.err == b"" assert captured.out == b"hello world !/?\n" @pytest.mark.skipif( sys.platform.startswith(("android", "emscripten", "ios")), reason="subprocess not supported" ) def test_subprocess() -> None: import subprocess # noqa: PLC0415 process = subprocess.Popen( [sys.executable, "-m", "pybase64", "encode", "-"], bufsize=4096, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) out, err = process.communicate() process.wait() assert process.returncode == 0 assert out == b"" assert err == b"" pybase64-1.4.3/tests/test_pybase64.py000066400000000000000000000362431511500755200173750ustar00rootroot00000000000000from __future__ import annotations import base64 import sys from base64 import encodebytes as b64encodebytes from binascii import Error as BinAsciiError from collections.abc import Callable from enum import IntEnum from typing import Any import pytest import pybase64 from pybase64._typing import Buffer, Decode, Encode from . import utils def b64encode_as_string(s: Buffer, altchars: str | Buffer | None = None) -> bytes: """helper returning bytes instead of string for tests""" return pybase64.b64encode_as_string(s, altchars).encode("ascii") def b64decode_as_bytearray( s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False ) -> bytes: """helper returning bytes instead of bytearray for tests""" return bytes(pybase64.b64decode_as_bytearray(s, altchars, validate)) param_encode_functions = pytest.mark.parametrize("efn", [pybase64.b64encode, b64encode_as_string]) param_decode_functions = pytest.mark.parametrize( "dfn", [pybase64.b64decode, b64decode_as_bytearray] ) class AltCharsId(IntEnum): STD = 0 URL = 1 ALT1 = 2 ALT2 = 3 ALT3 = 4 altchars_lut = [b"+/", b"-_", b"@&", b"+,", b";/"] enc_helper_lut: list[Callable[[Buffer], bytes]] = [ pybase64.standard_b64encode, pybase64.urlsafe_b64encode, ] ref_enc_helper_lut: list[Callable[[Buffer], bytes]] = [ base64.standard_b64encode, base64.urlsafe_b64encode, ] dec_helper_lut: list[Callable[[str | Buffer], bytes]] = [ pybase64.standard_b64decode, pybase64.urlsafe_b64decode, ] ref_dec_helper_lut: list[Callable[[str | Buffer], bytes]] = [ base64.standard_b64decode, base64.urlsafe_b64decode, ] std = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/A" std = std * (32 * 16) std_len_minus_12 = len(std) - 12 test_vectors_b64_list = [ # rfc4648 test vectors b"", b"Zg==", b"Zm8=", b"Zm9v", b"Zm9vYg==", b"Zm9vYmE=", b"Zm9vYmFy", # custom test vectors std[std_len_minus_12:], std, std[:72], std[:76], std[:80], std[:148], std[:152], std[:156], ] test_vectors_b64 = [] for altchars in altchars_lut: trans = bytes.maketrans(b"+/", altchars) test_vectors_b64.append([vector.translate(trans) for vector in test_vectors_b64_list]) test_vectors_bin = [] for altchars in altchars_lut: test_vectors_bin.append( [base64.b64decode(vector, altchars) for vector in test_vectors_b64_list] ) param_vector = pytest.mark.parametrize("vector_id", range(len(test_vectors_bin[0]))) param_validate = pytest.mark.parametrize("validate", [False, True], ids=["novalidate", "validate"]) param_altchars = pytest.mark.parametrize("altchars_id", list(AltCharsId), ids=lambda x: x.name) param_altchars_helper = pytest.mark.parametrize( "altchars_id", [AltCharsId.STD, AltCharsId.URL], ids=lambda x: x.name ) @utils.param_simd def test_version(simd: int) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests assert pybase64.get_version().startswith(pybase64.__version__) @utils.param_simd @param_vector @param_altchars_helper def test_enc_helper(altchars_id: int, vector_id: int, simd: int) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_bin[altchars_id][vector_id] test = enc_helper_lut[altchars_id](vector) base = ref_enc_helper_lut[altchars_id](vector) assert test == base @utils.param_simd @param_vector @param_altchars_helper def test_dec_helper(altchars_id: int, vector_id: int, simd: int) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_b64[altchars_id][vector_id] test = dec_helper_lut[altchars_id](vector) base = ref_dec_helper_lut[altchars_id](vector) assert test == base @utils.param_simd @param_vector @param_altchars_helper def test_dec_helper_unicode(altchars_id: int, vector_id: int, simd: int) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_b64[altchars_id][vector_id] test = dec_helper_lut[altchars_id](str(vector, "utf-8")) base = ref_dec_helper_lut[altchars_id](str(vector, "utf-8")) assert test == base @utils.param_simd @param_vector @param_altchars_helper def test_rnd_helper(altchars_id: int, vector_id: int, simd: int) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_b64[altchars_id][vector_id] test = dec_helper_lut[altchars_id](vector) test = enc_helper_lut[altchars_id](test) assert test == vector @utils.param_simd @param_vector @param_altchars_helper def test_rnd_helper_unicode(altchars_id: int, vector_id: int, simd: int) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_b64[altchars_id][vector_id] test = dec_helper_lut[altchars_id](str(vector, "utf-8")) test = enc_helper_lut[altchars_id](test) assert test == vector @utils.param_simd @param_vector def test_encbytes(vector_id: int, simd: int) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_bin[AltCharsId.STD][vector_id] test = pybase64.encodebytes(vector) base = b64encodebytes(vector) assert test == base @utils.param_simd @param_vector @param_altchars @param_encode_functions def test_enc(efn: Encode, altchars_id: int, vector_id: int, simd: int) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_bin[altchars_id][vector_id] altchars = altchars_lut[altchars_id] test = efn(vector, altchars) base = base64.b64encode(vector, altchars) assert test == base @utils.param_simd @param_vector @param_altchars @param_validate @param_decode_functions def test_dec(dfn: Decode, altchars_id: int, vector_id: int, validate: bool, simd: int) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_b64[altchars_id][vector_id] altchars = altchars_lut[altchars_id] if validate: base = base64.b64decode(vector, altchars, validate) else: base = base64.b64decode(vector, altchars) test = dfn(vector, altchars, validate) assert test == base @utils.param_simd @param_vector @param_altchars @param_validate @param_decode_functions def test_dec_unicode( dfn: Decode, altchars_id: int, vector_id: int, validate: bool, simd: int ) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = str(test_vectors_b64[altchars_id][vector_id], "utf-8") altchars = None if altchars_id == AltCharsId.STD else str(altchars_lut[altchars_id], "utf-8") if validate: base = base64.b64decode(vector, altchars, validate) else: base = base64.b64decode(vector, altchars) test = dfn(vector, altchars, validate) assert test == base @utils.param_simd @param_vector @param_altchars @param_validate @param_encode_functions @param_decode_functions def test_rnd( dfn: Decode, efn: Encode, altchars_id: int, vector_id: int, validate: bool, simd: int ) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_b64[altchars_id][vector_id] altchars = altchars_lut[altchars_id] test = dfn(vector, altchars, validate) test = efn(test, altchars) assert test == vector @utils.param_simd @param_vector @param_altchars @param_validate @param_encode_functions @param_decode_functions def test_rnd_unicode( dfn: Decode, efn: Encode, altchars_id: int, vector_id: int, validate: bool, simd: int ) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_b64[altchars_id][vector_id] altchars = altchars_lut[altchars_id] test = dfn(str(vector, "utf-8"), altchars, validate) test = efn(test, altchars) assert test == vector @utils.param_simd @param_vector @param_altchars @param_validate @param_decode_functions def test_invalid_padding_dec( dfn: Decode, altchars_id: int, vector_id: int, validate: bool, simd: int ) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests vector = test_vectors_b64[altchars_id][vector_id][1:] if len(vector) > 0: altchars = altchars_lut[altchars_id] with pytest.raises(BinAsciiError): dfn(vector, altchars, validate) params_invalid_altchars_values = [ [b"", AssertionError], [b"-", AssertionError], [b"-__", AssertionError], [3.0, TypeError], ["-€", ValueError], [memoryview(b"- _")[::2], BufferError], ] params_invalid_altchars = pytest.mark.parametrize( ("altchars", "exception"), params_invalid_altchars_values, ids=[str(i) for i in range(len(params_invalid_altchars_values))], ) @utils.param_simd @params_invalid_altchars @param_encode_functions def test_invalid_altchars_enc( efn: Encode, altchars: Any, exception: type[BaseException], simd: int ) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests with pytest.raises(exception): efn(b"ABCD", altchars) @utils.param_simd @params_invalid_altchars @param_decode_functions def test_invalid_altchars_dec( dfn: Decode, altchars: Any, exception: type[BaseException], simd: int ) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests with pytest.raises(exception): dfn(b"ABCD", altchars) @utils.param_simd @params_invalid_altchars @param_decode_functions def test_invalid_altchars_dec_validate( dfn: Decode, altchars: Any, exception: type[BaseException], simd: int ) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests with pytest.raises(exception): dfn(b"ABCD", altchars, True) params_invalid_data_novalidate_values = [ [b"A@@@@FG", None, BinAsciiError], ["ABC€", None, ValueError], [3.0, None, TypeError], [memoryview(b"ABCDEFGH")[::2], None, BufferError], ] params_invalid_data_validate_values = [ [b"\x00\x00\x00\x00", None, BinAsciiError], [b"A@@@@FGHIJKLMNOPQRSTUVWXYZabcdef", b"-_", BinAsciiError], [b"A@@@=FGHIJKLMNOPQRSTUVWXYZabcdef", b"-_", BinAsciiError], [b"A@@=@FGHIJKLMNOPQRSTUVWXYZabcdef", b"-_", BinAsciiError], [b"A@@@@FGHIJKLMNOPQRSTUVWXYZabcde@=", b"-_", BinAsciiError], [b"A@@@@FGHIJKLMNOPQRSTUVWXYZabcd@==", b"-_", BinAsciiError], [b"A@@@@FGH" * 10000, b"-_", BinAsciiError], # [std, b'-_', BinAsciiError], TODO does no fail with base64 module ] params_invalid_data_all = pytest.mark.parametrize( ("vector", "altchars", "exception"), params_invalid_data_novalidate_values + params_invalid_data_validate_values, ids=[ str(i) for i in range( len(params_invalid_data_novalidate_values) + len(params_invalid_data_validate_values) ) ], ) params_invalid_data_novalidate = pytest.mark.parametrize( ("vector", "altchars", "exception"), params_invalid_data_novalidate_values, ids=[str(i) for i in range(len(params_invalid_data_novalidate_values))], ) params_invalid_data_validate = pytest.mark.parametrize( ("vector", "altchars", "exception"), params_invalid_data_validate_values, ids=[str(i) for i in range(len(params_invalid_data_validate_values))], ) @utils.param_simd @params_invalid_data_novalidate @param_decode_functions def test_invalid_data_dec( dfn: Decode, vector: Any, altchars: Buffer | None, exception: type[BaseException], simd: int ) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests with pytest.raises(exception): dfn(vector, altchars) @utils.param_simd @params_invalid_data_validate @param_decode_functions def test_invalid_data_dec_skip( dfn: Decode, vector: Any, altchars: Buffer | None, exception: type[BaseException], simd: int ) -> None: utils.unused_args(exception, simd) # simd is a parameter in order to control the order of tests test = dfn(vector, altchars) if sys.implementation.name == "graalpy" and vector.startswith((b"A@@@=F", b"A@@=@")): pytest.xfail(reason="graalpy fails decoding those entries") # pragma: no cover base = base64.b64decode(vector, altchars) assert test == base @utils.param_simd @params_invalid_data_all @param_decode_functions def test_invalid_data_dec_validate( dfn: Decode, vector: Any, altchars: Buffer | None, exception: type[BaseException], simd: int ) -> None: utils.unused_args(simd) # simd is a parameter in order to control the order of tests with pytest.raises(exception): dfn(vector, altchars, True) params_invalid_data_enc_values = [ ["this is a test", TypeError], [memoryview(b"abcd")[::2], BufferError], ] params_invalid_data_encodebytes_values = [ *params_invalid_data_enc_values, [memoryview(b"abcd").cast("B", (2, 2)), TypeError], [memoryview(b"abcd").cast("I"), TypeError], ] params_invalid_data_enc = pytest.mark.parametrize( ("vector", "exception"), params_invalid_data_enc_values, ids=[str(i) for i in range(len(params_invalid_data_enc_values))], ) params_invalid_data_encodebytes = pytest.mark.parametrize( ("vector", "exception"), params_invalid_data_encodebytes_values, ids=[str(i) for i in range(len(params_invalid_data_encodebytes_values))], ) @params_invalid_data_enc @param_encode_functions def test_invalid_data_enc(efn: Encode, vector: Any, exception: type[BaseException]) -> None: with pytest.raises(exception): efn(vector) @params_invalid_data_encodebytes def test_invalid_data_encodebytes(vector: Any, exception: type[BaseException]) -> None: with pytest.raises(exception): pybase64.encodebytes(vector) @param_encode_functions def test_invalid_args_enc_0(efn: Encode) -> None: with pytest.raises(TypeError): efn() # type: ignore[call-arg] @param_decode_functions def test_invalid_args_dec_0(dfn: Decode) -> None: with pytest.raises(TypeError): dfn() # type: ignore[call-arg] def test_flags(request: pytest.FixtureRequest) -> None: cpu = request.config.getoption("--sde-cpu", skip=True) assert { "p4p": 1 | 2, # SSE3 "mrm": 1 | 2 | 4, # SSSE3 "pnr": 1 | 2 | 4 | 8, # SSE41 "nhm": 1 | 2 | 4 | 8 | 16, # SSE42 "snb": 1 | 2 | 4 | 8 | 16 | 32, # AVX "hsw": 1 | 2 | 4 | 8 | 16 | 32 | 64, # AVX2 "spr": 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, # AVX512VBMI }[cpu] == utils.runtime_flags @param_encode_functions def test_enc_multi_dimensional(efn: Encode) -> None: source = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV" vector = memoryview(source).cast("B", (4, len(source) // 4)) assert vector.c_contiguous test = efn(vector, None) base = base64.b64encode(source) assert test == base @param_decode_functions def test_dec_multi_dimensional(dfn: Decode) -> None: source = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV" vector = memoryview(source).cast("B", (4, len(source) // 4)) assert vector.c_contiguous test = dfn(vector, None) base = base64.b64decode(source) assert test == base pybase64-1.4.3/tests/utils.py000066400000000000000000000034041511500755200160320ustar00rootroot00000000000000from __future__ import annotations import os from collections.abc import Iterator from typing import Any import pytest import pybase64 _has_extension = hasattr(pybase64, "_set_simd_path") assert _has_extension or os.environ.get("CIBUILDWHEEL", "0") == "0" compile_flags = [0] runtime_flags = 0 if _has_extension: runtime_flags = pybase64._get_simd_flags_runtime() # type: ignore[attr-defined] flags = pybase64._get_simd_flags_compile() # type: ignore[attr-defined] for i in range(31): if flags & (1 << i): compile_flags += [(1 << i)] def _get_simd_name(simd_id: int) -> str: if _has_extension: simd_flag = compile_flags[simd_id] simd_name = "C" if simd_flag == 0 else pybase64._get_simd_name(simd_flag) # type: ignore[attr-defined] else: simd_name = "PY" return simd_name param_simd = pytest.mark.parametrize( "simd", range(len(compile_flags)), ids=lambda x: _get_simd_name(x), indirect=True ) @pytest.fixture def simd(request: pytest.FixtureRequest) -> Iterator[int]: simd_id = request.param if not _has_extension: assert simd_id == 0 yield simd_id return flag = compile_flags[simd_id] if flag != 0 and not flag & runtime_flags: # pragma: no branch simd_name = _get_simd_name(simd_id) # pragma: no cover pytest.skip(f"{simd_name!r} SIMD extension not available") # pragma: no cover old_flag = pybase64._get_simd_path() # type: ignore[attr-defined] pybase64._set_simd_path(flag) # type: ignore[attr-defined] assert pybase64._get_simd_path() == flag # type: ignore[attr-defined] yield simd_id pybase64._set_simd_path(old_flag) # type: ignore[attr-defined] def unused_args(*args: Any) -> None: # noqa: ARG001 return None pax_global_header00006660000000000000000000000064150064513040014510gustar00rootroot0000000000000052 comment=9e8ed65048ff0f703fad3deb03bf66ac7f78a4d7 pybase64-1.4.3/base64/000077500000000000000000000000001500645130400142365ustar00rootroot00000000000000pybase64-1.4.3/base64/.editorconfig000066400000000000000000000004671500645130400167220ustar00rootroot00000000000000# https://EditorConfig.org root = true [*] charset = utf-8 insert_final_newline = true trim_trailing_whitespace = true indent_style = tab tab_width = 8 indent_size = 8 [CMakeLists.txt] tab_width = 4 indent_style = space [*.cmake] tab_width = 4 indent_style = space [*.py] tab_width = 4 indent_style = space pybase64-1.4.3/base64/.github/000077500000000000000000000000001500645130400155765ustar00rootroot00000000000000pybase64-1.4.3/base64/.github/workflows/000077500000000000000000000000001500645130400176335ustar00rootroot00000000000000pybase64-1.4.3/base64/.github/workflows/test.yml000066400000000000000000000202671500645130400213440ustar00rootroot00000000000000name: Test on: [push, pull_request] jobs: makefile-analysis: name: makefile-analysis runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: "Install analysis tools" run: | sudo apt-get update sudo apt-get install -y clang-tools valgrind - name: Run tests run: ./test/ci/analysis.sh makefile-test: name: makefile-${{ matrix.runner }}-amd64-${{ matrix.compiler }} ${{ ((matrix.openmp == 1) && '+openmp') || '' }} needs: makefile-analysis runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: runner: ["ubuntu-22.04"] compiler: ["gcc", "clang"] openmp: ["0", "1"] include: - runner: "macos-13" compiler: "clang" openmp: "0" env: OPENMP: ${{ matrix.openmp }} OMP_NUM_THREADS: ${{ ((matrix.openmp == 1) && '2') || '0' }} CC: ${{ matrix.compiler }} OBJCOPY: ${{ (startsWith(matrix.runner, 'macos') && 'echo') || 'objcopy' }} steps: - name: Checkout uses: actions/checkout@v4 - name: Install Ubuntu libomp support if: runner.os == 'Linux' && matrix.compiler == 'clang' && matrix.openmp == 1 run: | sudo apt-get update sudo apt-get install -y libomp-dev - name: Run tests run: ./test/ci/test.sh cmake-test: name: cmake-${{ matrix.runner }}-${{ matrix.platform }} needs: makefile-analysis runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: runner: ["ubuntu-22.04", "windows-2019"] platform: ["x86_64", "i686"] include: - runner: "macos-13" platform: "x86_64" - runner: "macos-14" platform: "arm64" - runner: "ubuntu-22.04-arm" platform: "aarch64" - runner: "windows-11-arm" platform: "ARM64" steps: - name: Checkout uses: actions/checkout@v4 - name: Install Ubuntu i686 support if: runner.os == 'Linux' && matrix.platform == 'i686' run: | sudo apt-get update sudo apt-get install -y libc6-dev-i386 echo "CFLAGS=-m32" >> $GITHUB_ENV echo "LDFLAGS=-m32" >> $GITHUB_ENV - name: CMake Configure run: > cmake -B out -Werror=dev -DBASE64_BUILD_TESTS=ON ${{ runner.os != 'Windows' && '-DCMAKE_BUILD_TYPE=Release' || '' }} ${{ runner.os == 'Windows' && matrix.platform == 'i686' && '-A Win32' || '' }} - name: CMake Build run: cmake --build out --config Release --verbose - name: CTest run: ctest --no-tests=error --test-dir out -VV --build-config Release env: BASE64_TEST_SKIP_AVX512: "1" alpine-makefile-test: name: makefile-alpine-amd64-gcc needs: makefile-analysis runs-on: ubuntu-latest container: image: alpine:3.12 env: CC: gcc steps: - name: Install deps run: apk add --update bash build-base git - name: Checkout uses: actions/checkout@v4 - name: Run tests run: ./test/ci/test.sh alpine-cmake-test: name: cmake-alpine-amd64-gcc needs: makefile-analysis runs-on: ubuntu-latest container: image: alpine:3.12 steps: - name: Install deps run: apk add --update bash build-base cmake git - name: Checkout uses: actions/checkout@v4 - name: CMake Configure run: > cmake -B out -Werror=dev -DBASE64_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release - name: CMake Build run: cmake --build out --config Release --verbose - name: CTest run: ctest --no-tests=error -VV --build-config Release working-directory: ./out env: BASE64_TEST_SKIP_AVX512: "1" alpine-alt-arch-makefile-test: name: makefile-alpine-${{matrix.arch}}-${{matrix.cc}} needs: makefile-analysis runs-on: ubuntu-latest strategy: fail-fast: false matrix: arch: [armv7, aarch64, s390x, ppc64le] cc: [gcc, clang] steps: - name: Checkout uses: actions/checkout@v4 - uses: uraimo/run-on-arch-action@v3 with: arch: ${{matrix.arch}} distro: alpine_latest env: | CC: ${{matrix.cc}} install: apk add --update bash build-base cmake git ${{matrix.cc}} run: ./test/ci/test.sh alpine-alt-arch-cmake-test: name: cmake-alpine-${{matrix.arch}}-${{matrix.cc}} needs: makefile-analysis runs-on: ubuntu-latest strategy: fail-fast: false matrix: arch: [armv7, aarch64, s390x, ppc64le] cc: [gcc, clang] steps: - name: Checkout uses: actions/checkout@v4 - uses: uraimo/run-on-arch-action@v3 with: arch: ${{matrix.arch}} distro: alpine_latest env: | CC: ${{matrix.cc}} install: apk add --update bash build-base cmake git ${{matrix.cc}} run: | echo "::group::CMake Configure" cmake -B out -Werror=dev -DBASE64_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release echo "::endgroup::CMake Configure" echo "::group::CMake Build" cmake --build out --config Release --verbose echo "::endgroup::CMake Build" echo "::group::CTest" ctest --no-tests=error --test-dir out -VV --build-config Release echo "::endgroup::CTest" msys2-cmake-test: name: msys2-cmake-${{ matrix.msystem }} needs: makefile-analysis runs-on: windows-2022 strategy: fail-fast: false matrix: include: - { msystem: msys, toolchain: "gcc" } - { msystem: mingw32, env: mingw-w64-i686- } - { msystem: mingw64, env: mingw-w64-x86_64- } - { msystem: ucrt64, env: mingw-w64-ucrt-x86_64- } - { msystem: clang64, env: mingw-w64-clang-x86_64- } steps: - name: Checkout uses: actions/checkout@v4 - name: Setup MSYS2 ${{matrix.msystem}} uses: msys2/setup-msys2@v2 with: msystem: ${{matrix.msystem}} update: true install: >- make ${{ matrix.env }}${{ matrix.toolchain || 'toolchain' }} ${{ matrix.env }}cmake - name: CMake Configure shell: msys2 {0} run: > cmake -B out -Werror=dev -DBASE64_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release - name: CMake Build shell: msys2 {0} run: cmake --build out --config Release --verbose - name: CTest shell: msys2 {0} run: ctest --no-tests=error --test-dir out -VV --build-config Release env: BASE64_TEST_SKIP_AVX512: "1" - name: Test demo utility with unicode filenames and file contents on Windows shell: msys2 {0} run: | out/bin/base64 test/ci/πŸ˜΅β€πŸ’«.bin > test/ci/πŸ˜΅β€πŸ’«.bin.b64 out/bin/base64 -d test/ci/πŸ˜΅β€πŸ’«.bin.b64 > test/ci/πŸ˜΅β€πŸ’«.bin cd test/ci sha256sum -c checksums.txt msys2-makefile-test: name: msys2-makefile-${{ matrix.msystem }} needs: makefile-analysis runs-on: windows-2022 strategy: fail-fast: false matrix: include: - { msystem: msys, toolchain: "gcc" } - { msystem: mingw32, env: mingw-w64-i686- } - { msystem: mingw64, env: mingw-w64-x86_64- } - { msystem: ucrt64, env: mingw-w64-ucrt-x86_64- } # - { msystem: clang32, env: mingw-w64-clang-i686- } disabled, lld does not support the "-r" option # - { msystem: clang64, env: mingw-w64-clang-x86_64- } disabled, lld does not support the "-r" option env: CC: cc.exe steps: - name: Checkout uses: actions/checkout@v4 - name: Setup MSYS2 ${{matrix.msystem}} uses: msys2/setup-msys2@v2 with: msystem: ${{matrix.msystem}} update: true install: >- make ${{ matrix.env }}${{ matrix.toolchain || 'toolchain' }} - name: Run tests shell: msys2 {0} run: ./test/ci/test.sh pybase64-1.4.3/base64/.gitignore000066400000000000000000000002741500645130400162310ustar00rootroot00000000000000*.o bin/base64 lib/config.h test/benchmark test/test_base64 # visual studio symbol db, etc. .vs/ # build directory used by CMakePresets out/ # private cmake presets CMakeUserPresets.json pybase64-1.4.3/base64/CMakeLists.txt000066400000000000000000000242431500645130400170030ustar00rootroot00000000000000# Written in 2016-2017, 2021 by Henrik Steffen Gaßmann henrik@gassmann.onl # # To the extent possible under law, the author(s) have dedicated all # copyright and related and neighboring rights to this software to the # public domain worldwide. This software is distributed without any warranty. # # You should have received a copy of the CC0 Public Domain Dedication # along with this software. If not, see # # http://creativecommons.org/publicdomain/zero/1.0/ # ######################################################################## cmake_minimum_required(VERSION 3.10.2) # new dependent option syntax. We are already compliant if (POLICY CMP0127) cmake_policy(SET CMP0127 NEW) endif() project(base64 LANGUAGES C VERSION 0.5.2) include(GNUInstallDirs) include(CMakeDependentOption) include(CheckIncludeFile) include(FeatureSummary) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") ####################################################################### # platform detection include(TargetArch) detect_target_architecture(_TARGET_ARCH) check_include_file(getopt.h HAVE_GETOPT_H) cmake_dependent_option(BASE64_BUILD_CLI "Build the cli for encoding and decoding" ON "HAVE_GETOPT_H" OFF) add_feature_info(CLI BASE64_BUILD_CLI "enables the CLI executable for encoding and decoding") ################################################################### # optional/conditional dependencies find_package(OpenMP) set_package_properties(OpenMP PROPERTIES TYPE OPTIONAL PURPOSE "Allows to utilize OpenMP" ) ######################################################################## # Compilation options option(BASE64_WERROR "Treat warnings as error" ON) option(BASE64_BUILD_TESTS "add test projects" OFF) cmake_dependent_option(BASE64_WITH_OpenMP "use OpenMP" OFF "OpenMP_FOUND" OFF) add_feature_info("OpenMP codec" BASE64_WITH_OpenMP "spreads codec work accross multiple threads") cmake_dependent_option(BASE64_REGENERATE_TABLES "regenerate the codec tables" OFF "NOT CMAKE_CROSSCOMPILING" OFF) set(_IS_X86 "_TARGET_ARCH_x86 OR _TARGET_ARCH_x64") cmake_dependent_option(BASE64_WITH_SSSE3 "add SSSE 3 codepath" ON ${_IS_X86} OFF) add_feature_info(SSSE3 BASE64_WITH_SSSE3 "add SSSE 3 codepath") cmake_dependent_option(BASE64_WITH_SSE41 "add SSE 4.1 codepath" ON ${_IS_X86} OFF) add_feature_info(SSE4.1 BASE64_WITH_SSE41 "add SSE 4.1 codepath") cmake_dependent_option(BASE64_WITH_SSE42 "add SSE 4.2 codepath" ON ${_IS_X86} OFF) add_feature_info(SSE4.2 BASE64_WITH_SSE42 "add SSE 4.2 codepath") cmake_dependent_option(BASE64_WITH_AVX "add AVX codepath" ON ${_IS_X86} OFF) add_feature_info(AVX BASE64_WITH_AVX "add AVX codepath") cmake_dependent_option(BASE64_WITH_AVX2 "add AVX 2 codepath" ON ${_IS_X86} OFF) add_feature_info(AVX2 BASE64_WITH_AVX2 "add AVX2 codepath") cmake_dependent_option(BASE64_WITH_AVX512 "add AVX 512 codepath" ON ${_IS_X86} OFF) add_feature_info(AVX512 BASE64_WITH_AVX512 "add AVX512 codepath") cmake_dependent_option(BASE64_WITH_NEON32 "add NEON32 codepath" OFF _TARGET_ARCH_arm OFF) add_feature_info(NEON32 BASE64_WITH_NEON32 "add NEON32 codepath") cmake_dependent_option(BASE64_WITH_NEON64 "add NEON64 codepath" ON _TARGET_ARCH_arm64 OFF) add_feature_info(NEON64 BASE64_WITH_NEON64 "add NEON64 codepath") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") ######################################################################## # Regenerate headers if (BASE64_REGENERATE_TABLES) # Generate tables in build folder and copy to source tree. # Don't add the tables in the source tree to the outputs, to avoid `make clean` removing them. add_executable(table_generator lib/tables/table_generator.c ) add_custom_command(OUTPUT table_dec_32bit.h "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_dec_32bit.h" COMMAND table_generator > table_dec_32bit.h COMMAND "${CMAKE_COMMAND}" -E copy table_dec_32bit.h "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_dec_32bit.h" DEPENDS table_generator ) set(Python_ADDITIONAL_VERSIONS 3) find_package(PythonInterp REQUIRED) add_custom_command(OUTPUT table_enc_12bit.h "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_enc_12bit.h" COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_enc_12bit.py" > table_enc_12bit.h COMMAND "${CMAKE_COMMAND}" -E copy table_enc_12bit.h "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_enc_12bit.h" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_enc_12bit.py" ) endif() ######################################################################## # library project add_library(base64 # library files lib/lib.c lib/codec_choose.c include/libbase64.h lib/tables/tables.c # Add generated headers explicitly to target, to insert them in the dependency tree lib/tables/table_dec_32bit.h lib/tables/table_enc_12bit.h # codec implementations lib/arch/generic/codec.c lib/arch/ssse3/codec.c lib/arch/sse41/codec.c lib/arch/sse42/codec.c lib/arch/avx/codec.c lib/arch/avx2/codec.c lib/arch/avx512/codec.c lib/arch/neon32/codec.c lib/arch/neon64/codec.c ) target_include_directories(base64 PUBLIC $ $ PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" ) #################################################################### # platform/compiler specific configuration set_target_properties(base64 PROPERTIES C_STANDARD 99 C_STANDARD_REQUIRED YES C_EXTENSIONS OFF DEFINE_SYMBOL BASE64_EXPORTS VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) #generate_export_header(base64) # the following definitions and those in libbase64.h have been # kept forward compatible in case we ever switch to generate_export_header if (BUILD_SHARED_LIBS) set_target_properties(base64 PROPERTIES C_VISIBILITY_PRESET hidden ) else() target_compile_definitions(base64 PUBLIC BASE64_STATIC_DEFINE ) endif() target_compile_options(base64 PRIVATE $<$: /W4 /we4013 # Error warning C4013: 'function' undefined; assuming extern returning int /we4700 # Error warning C4700: uninitialized local variable /we4715 # not all control paths return a value /we4003 # not enough actual parameters for macro /wd4456 # disable warning C4456: declaration of 'xxx' hides previous local declaration > $<$>: -Wall -Wextra -Wpedantic > $<$:$,/WX,-Werror>> ) target_compile_definitions(base64 PRIVATE $<$: # remove unnecessary warnings about unchecked iterators _SCL_SECURE_NO_WARNINGS > ) ######################################################################## # SIMD settings include(TargetSIMDInstructionSet) define_SIMD_compile_flags() if (_TARGET_ARCH STREQUAL "x86" OR _TARGET_ARCH STREQUAL "x64") macro(configure_codec _TYPE) if (BASE64_WITH_${_TYPE}) string(TOLOWER "${_TYPE}" _DIR) set_source_files_properties("lib/arch/${_DIR}/codec.c" PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS_${_TYPE}}" ) if (${ARGC} GREATER 1 AND MSVC) set_source_files_properties("lib/arch/${_DIR}/codec.c" PROPERTIES COMPILE_DEFINITIONS ${ARGV1} ) endif() endif() endmacro() configure_codec(SSSE3 __SSSE3__) configure_codec(SSE41 __SSSE4_1__) configure_codec(SSE42 __SSSE4_2__) configure_codec(AVX) configure_codec(AVX2) configure_codec(AVX512) elseif (_TARGET_ARCH STREQUAL "arm") set(BASE64_NEON32_CFLAGS "${COMPILE_FLAGS_NEON32}" CACHE STRING "the NEON32 compile flags (for 'lib/arch/neon32/codec.c')") mark_as_advanced(BASE64_NEON32_CFLAGS) if (BASE64_WITH_NEON32) set_source_files_properties("lib/arch/neon32/codec.c" PROPERTIES COMPILE_FLAGS "${BASE64_NEON32_CFLAGS} " ) endif() #elseif (_TARGET_ARCH STREQUAL "arm64" AND BASE64_WITH_NEON64) endif() configure_file("${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/config.h" @ONLY) ######################################################################## # OpenMP Settings if (BASE64_WITH_OpenMP) target_link_libraries(base64 PRIVATE OpenMP::OpenMP_C) endif() ######################################################################## if (BASE64_BUILD_TESTS) enable_testing() add_subdirectory(test) endif() ######################################################################## # base64 if (BASE64_BUILD_CLI) add_executable(base64-bin bin/base64.c ) target_link_libraries(base64-bin PRIVATE base64) set_target_properties(base64-bin PROPERTIES OUTPUT_NAME base64 ) if (WIN32) target_sources(base64-bin PRIVATE bin/base64.rc) endif () endif() ######################################################################## # cmake install install(DIRECTORY include/ TYPE INCLUDE) install(TARGETS base64 EXPORT base64-targets DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) if (BASE64_BUILD_CLI) install(TARGETS base64-bin EXPORT base64-targets DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() include(CMakePackageConfigHelpers) configure_package_config_file(cmake/base64-config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/base64-config.cmake" INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/base64-config-version.cmake" VERSION ${BASE64_VERSION} COMPATIBILITY SameMajorVersion ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/base64-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/base64-config-version.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) install(EXPORT base64-targets NAMESPACE aklomp:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) ######################################################################## feature_summary(WHAT PACKAGES_FOUND PACKAGES_NOT_FOUND ENABLED_FEATURES DISABLED_FEATURES) pybase64-1.4.3/base64/LICENSE000066400000000000000000000026161500645130400152500ustar00rootroot00000000000000Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015-2018, Wojciech MuΕ‚a Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) 2013-2022, Alfred Klomp 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. pybase64-1.4.3/base64/Makefile000066400000000000000000000050741500645130400157040ustar00rootroot00000000000000CFLAGS += -std=c99 -O3 -Wall -Wextra -pedantic -DBASE64_STATIC_DEFINE # Set OBJCOPY if not defined by environment: OBJCOPY ?= objcopy OBJS = \ lib/arch/avx512/codec.o \ lib/arch/avx2/codec.o \ lib/arch/generic/codec.o \ lib/arch/neon32/codec.o \ lib/arch/neon64/codec.o \ lib/arch/ssse3/codec.o \ lib/arch/sse41/codec.o \ lib/arch/sse42/codec.o \ lib/arch/avx/codec.o \ lib/lib.o \ lib/codec_choose.o \ lib/tables/tables.o HAVE_AVX512 = 0 HAVE_AVX2 = 0 HAVE_NEON32 = 0 HAVE_NEON64 = 0 HAVE_SSSE3 = 0 HAVE_SSE41 = 0 HAVE_SSE42 = 0 HAVE_AVX = 0 # The user should supply compiler flags for the codecs they want to build. # Check which codecs we're going to include: ifdef AVX512_CFLAGS HAVE_AVX512 = 1 endif ifdef AVX2_CFLAGS HAVE_AVX2 = 1 endif ifdef NEON32_CFLAGS HAVE_NEON32 = 1 endif ifdef NEON64_CFLAGS HAVE_NEON64 = 1 endif ifdef SSSE3_CFLAGS HAVE_SSSE3 = 1 endif ifdef SSE41_CFLAGS HAVE_SSE41 = 1 endif ifdef SSE42_CFLAGS HAVE_SSE42 = 1 endif ifdef AVX_CFLAGS HAVE_AVX = 1 endif ifdef OPENMP CFLAGS += -fopenmp endif TARGET := $(shell $(CC) -dumpmachine) .PHONY: all analyze clean all: bin/base64 lib/libbase64.o bin/base64: bin/base64.o lib/libbase64.o $(CC) $(CFLAGS) -o $@ $^ # Workaround: mangle exported function names on MinGW32. lib/exports.build.txt: lib/exports.txt ifeq (i686-w64-mingw32, $(TARGET)) sed -e 's/^/_/' $< > $@ else cp -f $< $@ endif lib/libbase64.o: lib/exports.build.txt $(OBJS) $(LD) -r -o $@ $(OBJS) $(OBJCOPY) --keep-global-symbols=$< $@ lib/config.h: @echo "#define HAVE_AVX512 $(HAVE_AVX512)" > $@ @echo "#define HAVE_AVX2 $(HAVE_AVX2)" >> $@ @echo "#define HAVE_NEON32 $(HAVE_NEON32)" >> $@ @echo "#define HAVE_NEON64 $(HAVE_NEON64)" >> $@ @echo "#define HAVE_SSSE3 $(HAVE_SSSE3)" >> $@ @echo "#define HAVE_SSE41 $(HAVE_SSE41)" >> $@ @echo "#define HAVE_SSE42 $(HAVE_SSE42)" >> $@ @echo "#define HAVE_AVX $(HAVE_AVX)" >> $@ $(OBJS): lib/config.h $(OBJS): CFLAGS += -Ilib lib/arch/avx512/codec.o: CFLAGS += $(AVX512_CFLAGS) lib/arch/avx2/codec.o: CFLAGS += $(AVX2_CFLAGS) lib/arch/neon32/codec.o: CFLAGS += $(NEON32_CFLAGS) lib/arch/neon64/codec.o: CFLAGS += $(NEON64_CFLAGS) lib/arch/ssse3/codec.o: CFLAGS += $(SSSE3_CFLAGS) lib/arch/sse41/codec.o: CFLAGS += $(SSE41_CFLAGS) lib/arch/sse42/codec.o: CFLAGS += $(SSE42_CFLAGS) lib/arch/avx/codec.o: CFLAGS += $(AVX_CFLAGS) %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< analyze: clean scan-build --use-analyzer=`which clang` --status-bugs make clean: rm -f bin/base64 bin/base64.o lib/libbase64.o lib/config.h lib/exports.build.txt $(OBJS) pybase64-1.4.3/base64/README.md000066400000000000000000000460571500645130400155310ustar00rootroot00000000000000# Fast Base64 stream encoder/decoder [![Build Status](https://github.com/aklomp/base64/actions/workflows/test.yml/badge.svg)](https://github.com/aklomp/base64/actions/workflows/test.yml) This is an implementation of a base64 stream encoding/decoding library in C99 with SIMD (AVX2, AVX512, NEON, AArch64/NEON, SSSE3, SSE4.1, SSE4.2, AVX) and [OpenMP](http://www.openmp.org) acceleration. It also contains wrapper functions to encode/decode simple length-delimited strings. This library aims to be: - FAST; - easy to use; - elegant. On x86, the library does runtime feature detection. The first time it's called, the library will determine the appropriate encoding/decoding routines for the machine. It then remembers them for the lifetime of the program. If your processor supports AVX2, SSSE3, SSE4.1, SSE4.2 or AVX instructions, the library will pick an optimized codec that lets it encode/decode 12 or 24 bytes at a time, which gives a speedup of four or more times compared to the "plain" bytewise codec. AVX512 support is only for encoding at present, utilizing the AVX512 VL and VBMI instructions. Decoding part reused AVX2 implementations. For CPUs later than Cannonlake (manufactured in 2018) supports these instructions. NEON support is hardcoded to on or off at compile time, because portable runtime feature detection is unavailable on ARM. Even if your processor does not support SIMD instructions, this is a very fast library. The fallback routine can process 32 or 64 bits of input in one round, depending on your processor's word width, which still makes it significantly faster than naive bytewise implementations. On some 64-bit machines, the 64-bit routines even outperform the SSSE3 ones. To the author's knowledge, at the time of original release, this was the only Base64 library to offer SIMD acceleration. The author wrote [an article](http://www.alfredklomp.com/programming/sse-base64) explaining one possible SIMD approach to encoding/decoding Base64. The article can help figure out what the code is doing, and why. Notable features: - Really fast on x86 and ARM systems by using SIMD vector processing; - Can use [OpenMP](http://www.openmp.org) for even more parallel speedups; - Really fast on other 32 or 64-bit platforms through optimized routines; - Reads/writes blocks of streaming data; - Does not dynamically allocate memory; - Valid C99 that compiles with pedantic options on; - Re-entrant and threadsafe; - Unit tested; - Uses Duff's Device. ## Acknowledgements The original AVX2, NEON and Aarch64/NEON codecs were generously contributed by [Inkymail](https://github.com/inkymail/base64), who, in their fork, also implemented some additional features. Their work is slowly being backported into this project. The SSSE3 and AVX2 codecs were substantially improved by using some very clever optimizations described by Wojciech MuΕ‚a in a [series](http://0x80.pl/notesen/2016-01-12-sse-base64-encoding.html) of [articles](http://0x80.pl/notesen/2016-01-17-sse-base64-decoding.html). His own code is [here](https://github.com/WojciechMula/toys/tree/master/base64). The AVX512 encoder is based on code from Wojciech MuΕ‚a's [base64simd](https://github.com/WojciechMula/base64simd) library. The OpenMP implementation was added by Ferry Toth (@htot) from [Exalon Delft](http://www.exalondelft.nl). ## Building The `lib` directory contains the code for the actual library. Typing `make` in the toplevel directory will build `lib/libbase64.o` and `bin/base64`. The first is a single, self-contained object file that you can link into your own project. The second is a standalone test binary that works similarly to the `base64` system utility. The matching header file needed to use this library is in `include/libbase64.h`. To compile just the "plain" library without SIMD codecs, type: ```sh make lib/libbase64.o ``` Optional SIMD codecs can be included by specifying the `AVX2_CFLAGS`, `AVX512_CFLAGS`, `NEON32_CFLAGS`, `NEON64_CFLAGS`, `SSSE3_CFLAGS`, `SSE41_CFLAGS`, `SSE42_CFLAGS` and/or `AVX_CFLAGS` environment variables. A typical build invocation on x86 looks like this: ```sh AVX2_CFLAGS=-mavx2 SSSE3_CFLAGS=-mssse3 SSE41_CFLAGS=-msse4.1 SSE42_CFLAGS=-msse4.2 AVX_CFLAGS=-mavx make lib/libbase64.o ``` ### AVX2 To build and include the AVX2 codec, set the `AVX2_CFLAGS` environment variable to a value that will turn on AVX2 support in your compiler, typically `-mavx2`. Example: ```sh AVX2_CFLAGS=-mavx2 make ``` ### AVX512 To build and include the AVX512 codec, set the `AVX512_CFLAGS` environment variable to a value that will turn on AVX512 support in your compiler, typically `-mavx512vl -mavx512vbmi`. Example: ```sh AVX512_CFLAGS="-mavx512vl -mavx512vbmi" make ``` The codec will only be used if runtime feature detection shows that the target machine supports AVX2. ### SSSE3 To build and include the SSSE3 codec, set the `SSSE3_CFLAGS` environment variable to a value that will turn on SSSE3 support in your compiler, typically `-mssse3`. Example: ```sh SSSE3_CFLAGS=-mssse3 make ``` The codec will only be used if runtime feature detection shows that the target machine supports SSSE3. ### NEON This library includes two NEON codecs: one for regular 32-bit ARM and one for the 64-bit AArch64 with NEON, which has double the amount of SIMD registers and can do full 64-byte table lookups. These codecs encode in 48-byte chunks and decode in massive 64-byte chunks, so they had to be augmented with an uint32/64 codec to stay fast on smaller inputs! Use LLVM/Clang for compiling the NEON codecs. The code generation of at least GCC 4.6 (the version shipped with Raspbian and used for testing) contains a bug when compiling `vstq4_u8()`, and the generated assembly code is of low quality. NEON intrinsics are a known weak area of GCC. Clang does a better job. NEON support can unfortunately not be portably detected at runtime from userland (the `mrc` instruction is privileged), so the default value for using the NEON codec is determined at compile-time. But you can do your own runtime detection. You can include the NEON codec and make it the default, then do a runtime check if the CPU has NEON support, and if not, force a downgrade to non-NEON with `BASE64_FORCE_PLAIN`. These are your options: 1. Don't include NEON support; 2. build NEON support and make it the default, but build all other code without NEON flags so that you can override the default at runtime with `BASE64_FORCE_PLAIN`; 3. build everything with NEON support and make it the default; 4. build everything with NEON support, but don't make it the default (which makes no sense). For option 1, simply don't specify any NEON-specific compiler flags at all, like so: ```sh CC=clang CFLAGS="-march=armv6" make ``` For option 2, keep your `CFLAGS` plain, but set the `NEON32_CFLAGS` environment variable to a value that will build NEON support. The line below, for instance, will build all the code at ARMv6 level, except for the NEON codec, which is built at ARMv7. It will also make the NEON codec the default. For ARMv6 platforms, override that default at runtime with the `BASE64_FORCE_PLAIN` flag. No ARMv7/NEON code will then be touched. ```sh CC=clang CFLAGS="-march=armv6" NEON32_CFLAGS="-march=armv7 -mfpu=neon" make ``` For option 3, put everything in your `CFLAGS` and use a stub, but non-empty, `NEON32_CFLAGS`. This example works for the Raspberry Pi 2B V1.1, which has NEON support: ```sh CC=clang CFLAGS="-march=armv7 -mtune=cortex-a7" NEON32_CFLAGS="-mfpu=neon" make ``` To build and include the NEON64 codec, use `CFLAGS` as usual to define the platform and set `NEON64_CFLAGS` to a nonempty stub. (The AArch64 target has mandatory NEON64 support.) Example: ```sh CC=clang CFLAGS="--target=aarch64-linux-gnu -march=armv8-a" NEON64_CFLAGS=" " make ``` ### OpenMP To enable OpenMP on GCC you need to build with `-fopenmp`. This can be by setting the the `OPENMP` environment variable to `1`. Example: ```sh OPENMP=1 make ``` This will let the compiler define `_OPENMP`, which in turn will include the OpenMP optimized `lib_openmp.c` into `lib.c`. By default the number of parallel threads will be equal to the number of cores of the processor. On a quad core with hyperthreading eight cores will be detected, but hyperthreading will not increase the performance. To get verbose information about OpenMP start the program with `OMP_DISPLAY_ENV=VERBOSE`, for instance ```sh OMP_DISPLAY_ENV=VERBOSE test/benchmark ``` To put a limit on the number of threads, start the program with `OMP_THREAD_LIMIT=n`, for instance ```sh OMP_THREAD_LIMIT=2 test/benchmark ``` An example of running a benchmark with OpenMP, SSSE3 and AVX2 enabled: ```sh make clean && OPENMP=1 SSSE3_CFLAGS=-mssse3 AVX2_CFLAGS=-mavx2 make && OPENMP=1 make -C test ``` ## API reference Strings are represented as a pointer and a length; they are not zero-terminated. This was a conscious design decision. In the decoding step, relying on zero-termination would make no sense since the output could contain legitimate zero bytes. In the encoding step, returning the length saves the overhead of calling `strlen()` on the output. If you insist on the trailing zero, you can easily add it yourself at the given offset. ### Flags Some API calls take a `flags` argument. That argument can be used to force the use of a specific codec, even if that codec is a no-op in the current build. Mainly there for testing purposes, this is also useful on ARM where the only way to do runtime NEON detection is to ask the OS if it's available. The following constants can be used: - `BASE64_FORCE_AVX2` - `BASE64_FORCE_AVX512` - `BASE64_FORCE_NEON32` - `BASE64_FORCE_NEON64` - `BASE64_FORCE_PLAIN` - `BASE64_FORCE_SSSE3` - `BASE64_FORCE_SSE41` - `BASE64_FORCE_SSE42` - `BASE64_FORCE_AVX` Set `flags` to `0` for the default behavior, which is runtime feature detection on x86, a compile-time fixed codec on ARM, and the plain codec on other platforms. ### Encoding #### base64_encode ```c void base64_encode ( const char *src , size_t srclen , char *out , size_t *outlen , int flags ) ; ``` Wrapper function to encode a plain string of given length. Output is written to `out` without trailing zero. Output length in bytes is written to `outlen`. The buffer in `out` has been allocated by the caller and is at least 4/3 the size of the input. #### base64_stream_encode_init ```c void base64_stream_encode_init ( struct base64_state *state , int flags ) ; ``` Call this before calling `base64_stream_encode()` to init the state. #### base64_stream_encode ```c void base64_stream_encode ( struct base64_state *state , const char *src , size_t srclen , char *out , size_t *outlen ) ; ``` Encodes the block of data of given length at `src`, into the buffer at `out`. Caller is responsible for allocating a large enough out-buffer; it must be at least 4/3 the size of the in-buffer, but take some margin. Places the number of new bytes written into `outlen` (which is set to zero when the function starts). Does not zero-terminate or finalize the output. #### base64_stream_encode_final ```c void base64_stream_encode_final ( struct base64_state *state , char *out , size_t *outlen ) ; ``` Finalizes the output begun by previous calls to `base64_stream_encode()`. Adds the required end-of-stream markers if appropriate. `outlen` is modified and will contain the number of new bytes written at `out` (which will quite often be zero). ### Decoding #### base64_decode ```c int base64_decode ( const char *src , size_t srclen , char *out , size_t *outlen , int flags ) ; ``` Wrapper function to decode a plain string of given length. Output is written to `out` without trailing zero. Output length in bytes is written to `outlen`. The buffer in `out` has been allocated by the caller and is at least 3/4 the size of the input. Returns `1` for success, and `0` when a decode error has occured due to invalid input. Returns `-1` if the chosen codec is not included in the current build. #### base64_stream_decode_init ```c void base64_stream_decode_init ( struct base64_state *state , int flags ) ; ``` Call this before calling `base64_stream_decode()` to init the state. #### base64_stream_decode ```c int base64_stream_decode ( struct base64_state *state , const char *src , size_t srclen , char *out , size_t *outlen ) ; ``` Decodes the block of data of given length at `src`, into the buffer at `out`. Caller is responsible for allocating a large enough out-buffer; it must be at least 3/4 the size of the in-buffer, but take some margin. Places the number of new bytes written into `outlen` (which is set to zero when the function starts). Does not zero-terminate the output. Returns 1 if all is well, and 0 if a decoding error was found, such as an invalid character. Returns -1 if the chosen codec is not included in the current build. Used by the test harness to check whether a codec is available for testing. ## Examples A simple example of encoding a static string to base64 and printing the output to stdout: ```c #include /* fwrite */ #include "libbase64.h" int main () { char src[] = "hello world"; char out[20]; size_t srclen = sizeof(src) - 1; size_t outlen; base64_encode(src, srclen, out, &outlen, 0); fwrite(out, outlen, 1, stdout); return 0; } ``` A simple example (no error checking, etc) of stream encoding standard input to standard output: ```c #include #include "libbase64.h" int main () { size_t nread, nout; char buf[12000], out[16000]; struct base64_state state; // Initialize stream encoder: base64_stream_encode_init(&state, 0); // Read contents of stdin into buffer: while ((nread = fread(buf, 1, sizeof(buf), stdin)) > 0) { // Encode buffer: base64_stream_encode(&state, buf, nread, out, &nout); // If there's output, print it to stdout: if (nout) { fwrite(out, nout, 1, stdout); } // If an error occurred, exit the loop: if (feof(stdin)) { break; } } // Finalize encoding: base64_stream_encode_final(&state, out, &nout); // If the finalizing resulted in extra output bytes, print them: if (nout) { fwrite(out, nout, 1, stdout); } return 0; } ``` Also see `bin/base64.c` for a simple re-implementation of the `base64` utility. A file or standard input is fed through the encoder/decoder, and the output is written to standard output. ## Tests See `tests/` for a small test suite. Testing is automated with [GitHub Actions](https://github.com/aklomp/base64/actions), which builds and tests the code across various architectures. ## Benchmarks Benchmarks can be run with the built-in benchmark program as follows: ```sh make -C test benchmark && test/benchmark ``` It will run an encoding and decoding benchmark for all of the compiled-in codecs. The tables below contain some results on random machines. All numbers measured with a 10MB buffer in MB/sec, rounded to the nearest integer. \*: Update needed x86 processors | Processor | Plain enc | Plain dec | SSSE3 enc | SSSE3 dec | AVX enc | AVX dec | AVX2 enc | AVX2 dec | |-------------------------------------------|----------:|----------:|----------:|----------:|--------:|--------:|---------:|---------:| | i7-4771 @ 3.5 GHz | 833\* | 1111\* | 3333\* | 4444\* | TBD | TBD | 4999\* | 6666\* | | i7-4770 @ 3.4 GHz DDR1600 | 1790\* | 3038\* | 4899\* | 4043\* | 4796\* | 5709\* | 4681\* | 6386\* | | i7-4770 @ 3.4 GHz DDR1600 OPENMP 1 thread | 1784\* | 3041\* | 4945\* | 4035\* | 4776\* | 5719\* | 4661\* | 6294\* | | i7-4770 @ 3.4 GHz DDR1600 OPENMP 2 thread | 3401\* | 5729\* | 5489\* | 7444\* | 5003\* | 8624\* | 5105\* | 8558\* | | i7-4770 @ 3.4 GHz DDR1600 OPENMP 4 thread | 4884\* | 7099\* | 4917\* | 7057\* | 4799\* | 7143\* | 4902\* | 7219\* | | i7-4770 @ 3.4 GHz DDR1600 OPENMP 8 thread | 5212\* | 8849\* | 5284\* | 9099\* | 5289\* | 9220\* | 4849\* | 9200\* | | i7-4870HQ @ 2.5 GHz | 1471\* | 3066\* | 6721\* | 6962\* | 7015\* | 8267\* | 8328\* | 11576\* | | i5-4590S @ 3.0 GHz | 3356 | 3197 | 4363 | 6104 | 4243\* | 6233 | 4160\* | 6344 | | Xeon X5570 @ 2.93 GHz | 2161 | 1508 | 3160 | 3915 | - | - | - | - | | Pentium4 @ 3.4 GHz | 896 | 740 | - | - | - | - | - | - | | Atom N270 | 243 | 266 | 508 | 387 | - | - | - | - | | AMD E-450 | 645 | 564 | 625 | 634 | - | - | - | - | | Intel Edison @ 500 MHz | 79\* | 92\* | 152\* | 172\* | - | - | - | - | | Intel Edison @ 500 MHz OPENMP 2 thread | 158\* | 184\* | 300\* | 343\* | - | - | - | - | | Intel Edison @ 500 MHz (x86-64) | 162 | 119 | 209 | 164 | - | - | - | - | | Intel Edison @ 500 MHz (x86-64) 2 thread | 319 | 237 | 412 | 329 | - | - | - | - | ARM processors | Processor | Plain enc | Plain dec | NEON32 enc | NEON32 dec | NEON64 enc | NEON64 dec | |-------------------------------------------|----------:|----------:|-----------:|-----------:|-----------:|-----------:| | Raspberry PI B+ V1.2 | 46\* | 40\* | - | - | - | - | | Raspberry PI 2 B V1.1 | 85 | 141 | 300 | 225 | - | - | | Apple iPhone SE armv7 | 1056\* | 895\* | 2943\* | 2618\* | - | - | | Apple iPhone SE arm64 | 1061\* | 1239\* | - | - | 4098\* | 3983\* | PowerPC processors | Processor | Plain enc | Plain dec | |-------------------------------------------|----------:|----------:| | PowerPC E6500 @ 1.8GHz | 270\* | 265\* | Benchmarks on i7-4770 @ 3.4 GHz DDR1600 with varrying buffer sizes: ![Benchmarks](base64-benchmarks.png) Note: optimal buffer size to take advantage of the cache is in the range of 100 kB to 1 MB, leading to 12x faster AVX encoding/decoding compared to Plain, or a throughput of 24/27GB/sec. Also note the performance degradation when the buffer size is less than 10 kB due to thread creation overhead. To prevent this from happening `lib_openmp.c` defines `OMP_THRESHOLD 20000`, requiring at least a 20000 byte buffer to enable multithreading. ## License This repository is licensed under the [BSD 2-clause License](http://opensource.org/licenses/BSD-2-Clause). See the LICENSE file. pybase64-1.4.3/base64/base64-benchmarks.png000066400000000000000000000520121500645130400201430ustar00rootroot00000000000000‰PNG  IHDR‚lXVΨzbKGD��� ½§“ pHYs  šœtIMEΰ-Β²ΰ‹tEXtCommentCreated with GIMPW IDATxΪμέ}|υγΗρΧuvs6Ζζfξ…PΉ…ξ5‘€±ιΧέιξ›T_|λۍ€"Q’τ­€¨δ[ 5mtC‘h©&’…3vΆσωύ±mvsΞ »y?σ(ηΊ�ΟΉΞηϊœsήϋ\ŸλsYΖƒˆˆˆˆΤ86Uˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(ŠˆˆˆH΅ ‚Nv/Œ ž½‘Ι…—δ$�ερލ±Y~΄μ3ž΅‰.·–UQ刈ˆˆH…A‡c&3aC#šΨ‹.KcΛ³cX7`ϋŽΔ³τΪuŒΌ™τ2—�rDDDD€β‚`z,Ζ†2sΚυ4ρ*²,s'‘Q6ϊ ΎˆfAMιΦ+j;3ΛXΖi*GDDDD*0ϊ‡0jt‚½‹Y–•ΐφ€@Ξ φΐ7Έ=‰ΫIΘ*cΩι*GDDDDŠε]α%Ί²HqzSΫΧΐς ΐΫ™B¦  ΄e§©9CAΠf§Žo6©Y°pe₯ν€έPΪ²ΣSΞͺU«t”₯�šΈ"™§ͺ"Tͺ?Υc¦J¨VAΠ·]&w0 ΫqˆΓBs;`JYvšΚ)�­Z΅J οτΉ˜M―SETΘΘb΅E՟κOυXc©³ζμ«ψyνm<Φ|Ό‰„δ6GFα50œΆΎe,;]刈ˆˆHΑδHϊXVP1Ž"‚,,+>AΊ›C�˜[it.CΏΘάΗBπ£¬eyεΦ«€rDDDD€Lε;5N΄1%§Λ‘LŽήΗd—e'Εγ°`;΅rDDDDδtΑΣ!ηoV>υ*υ¦�%΄ŽŒˆˆˆHΝ ‚^M²(Ž!:&""""g„MU """’ ("""" ‚""""’ ("""" ‚""""’ ("""" ‚""""’ ("""" ‚""""’ ("""" ‚""""’ ("""" ‚"5Jr$}, Λκƒ#λμοCdrε�£χ/9’Έ�―ΌοAΚΧΞ*{ΫQ©‚2bB[ Λ²°šα»΄šτ泉ŸέΛV•X«Γ{8›uSυw<¨}xΤφr†>»Šέ:*" ‚"•HκζyΌ± πφ/bΞ·5(MδμgΝ’­` <N΄1Mx`%άη’ϋWά{’oyΦ9e.’w}ΛϋO β’ϋ?爩 c/" ‚"§ΔaέΛοs€ΖŒxι^Zr„gFqΘUtΕ β?zŒλ.Κνα¨Χ‰ˆ‰«Ωοτp“Ζo‹Η�―C#μ–…Oγ^άυίXRJϋa,cs`—YV“{Yσε$ϊ4Ά°j‡ριQΘΨ΅Œ C.€y­ΌžΏfτ>“o»r{oΌ[qί&€"‚ςNΉύYάι·’Ύ™Ν]W΄&ΐ²°,šχΌ•©_$�φNμΗ(Φ�ώ)�?Ÿ@ΛΒ²Υ§ΛΝ/²αˆλδxπΧ[\jYXΎX~8χΉμ=σΈ(―'ις… ΈL]γƒeyΣwΑ»'φοΟήΓΡόo1Ξ}ŸπΔρ}i@Χ[f»/eΥ₯;Η.ϋ`4Σ‡_Β9Ήϋo«Χγ–±;3Ώόwsίoΰ-|όεl†_Τ_ΛΒͺہž_ORާm₯”6W�ρ-ψwN©λΈΚ<ζ% eΉΓ`ŒΑ˜2“�dΣ[Γh ψp>›SŠίͺΤφšΏΏΪfyڜˆxςY­\Ή�HωυΈgQ•Ϊߜύ‹L_ ηόΗl9ς“™ΠƒνrσΖήμkΉΜ‘/ο5ΝsϋL =:<ω£Is{“ψι|�:ΜŸ6.cŒq,7‘` Τ΄»}‘{Ϋ$ύΟτƒ½“ΉΌiώςP³όΰ/ζΉ }OΪΐΤ[bώ>œ�Z‘fωήϋ°ά‘[)›Ÿ4‹)ښœ»‡?ΚέŸ¦w«“Χ­7l9β*r2·›‰ν1ΠΒό{Sš1Ζe-½ΖψδmS+βSγ0Ƙ΄ζ¦θbfnύθΔών-ω=Τ­Μ%-έά—�κ�αΖqpΖ›W/χ.ΆΎΟσ9fŒ1IKΝ•` ΐ4ρ-ΊžΏπξ>“νn[)«Ν9J¨Gχ[Κ:‰(ϋ˜ε8Ήνγ2YGχš σo2 ΑPο6“RΜΊ™e΄ΧœbΆ)O›Σw’~Εm ‚RΝΏτœfΧμ‹ `.xφ“i²LάτΞ0]¦Η™¬γi1ΑΌšϋίξί«ΝΎ‡ωνέ[L#0Ύη?dΎOssμ?Ν—Z›KvGΊΓΔ½?Μ4γέ罓~θΪέΎΘΓm0΅ϋΎ`Ύω;έd₯₯˜¬’?€� sΰ«ρ¦=όΓΝκ£%όp}.ηoσΑ5Ή?Π "ζ™ο�N5ι‡~4oάlγέg‘I(²ήέ6Λγ&έρ›ωπžΦΉ?ΜυF˜u)EAŠωκ�†0½ήΨgrΜ1σε° ƒύb3όB/C“ϋΝΖTc²χΜ3‚‘εCfσίEφ―„χPΗγ})₯.n‡δOΜu>θhžΫvΜ8G͎%·›sμ¦ωϘΣ —8`Ί‰ΩsΤ€άbζߐ[\ψЉwΊΩVάisΕ37Β[ΞίζάζήeσRκ―€Gη [Lͺqcίάi―εjsϊNΤο±(ͺαιKΟc2bΝSν1p‘™ύ‡37ξ~Υ\ †ΦεώpcLJŒ„�fΦ.gρeΉ³Ξ±΅ζΦΊ%ό@6ΌΫ|ZLτh›6fόΆŒΒ=žIߚ—†]dšψ”Π3δNL‰1·ΥΛ 8ΟǏΗ&kΗtΣ AΓMΜ±‚Ϋ΅6㢞؏μ=σLw0XW›Θ“~π]&ργk/˜ aΡζXϊζΡV.™oΎz)ΔΐζΉί2MςšLm0unϊά$;< ‚EφeχάRφ₯”Ίtη8€�`Ιο•jΠΝ„ύσ 3gι7fΧ±œbΚοd^ψ½@]ΖMΛ­Λ:7›¨cnΎž;m�ΌA0%Ζ4°»qΜέ‚Ύ¦Q§kΝΏ^ϋΞ$e—όΊ·Χr΅9}'κχXά₯1‚R­₯ώπ*�ύΰΖ΄υΑ²,|ZίΗw»0oSή@¦μc8D‹ οβ sgœ4’RKΨΗ>ΞSέ¦%έ[Ψ ΐ;Θς»ϊσΠβ-όν<…ŠΚ>ΖίG�Ά‘Ορ§}΄‘!ΐ±+8ΆVτ:ηΔ~xΥmJ €qs=‚EΠ…ƒι8~ΨȞ=λY½.|]CϋsΏ±jγ_μϊj©Ψθή•vΎΘΎ6+e_J©KwŽƒ_γߟΚΐ–@�VV½1…Ρ7]ΞΉυ»1zΥίͺ"―f\\ .ž›[—iGHΛqσυάis§p̝Yžσ�ΖŒΙδΐΟ«™so/κ{•°Ι)΅WOڜˆΈKAPͺρX_ΟZLB‰+δƒYλr―nτͺMƒΪGΨ{$»ψΥέ\'8ΰbήޟSΰG�`œ«Ή>πT·±αSπG6υ'ή‹JšsΟGΏq8#‡œΏίεROλΚ».Mλ ξΰ‰Ι ³ύΞA€ΐ¦Τυ.ξlΏ=,«Τβ½_F�Φΐ_ςν—ΛΩN3�ι{uΫ ΰς@Ψϊρ:6¬Ϋt ¬W}Ώ˜<Ϋ—λ�­γ`#θ�q|²'„­«YψΒΈΉ[mpΖςΚ½SΨ’^0ΰ'°#ρDΪΙ:Έ#·.k7$ΐΛΝΧs§Ν•—w]||=9ζρ—Ω©΄ΧςgQ”Ιup5/-OΫΌωgv‘ΪμΏή¦·[9“ΟΈΐΏ=ύ:Y@,sf~ΑΎΤ£μXό[ήmΗ°1 ·ΧΉΊ“|nj9ΡμΟp£―’<Ϋ»N2œ~ΤoάΗO,7 €p(₯`—ΞnΦύ˜HfFΞ’/αa½μ@3Ζ½ΕζΏΣH;°‰7{‘ίΏ^a\ΰ Γ―ύ/ „¬ο™σ�7δΤΉœAψC@gΒ/τ"-z&―l1Πμj�jαSJA₯Ό‡SεΞqΘΨΞ‹ƒ:Ρ$¨νhΟ�=87>AG€Δ]$κεϊ™gΗΞεΫύ©€'ώΘΫOΌΔo„�ΞίΝΧs§ΝyT7Φρ»€ `ŸΣwΜOΉ½ŠΘ™ι4ј©–γaœ&~n/ΏšE½η4�θgΣγ•]ΖirLβ§·s'ζ‚ρ›sΎ»ΉΞ‘UΓs―œ,τ°Lπ΅―›]Y¦Ψ«†=Ω¦Π80η.σJΟ’Ϋ΅2=σ―†­?Δ|Ά�Λ"cъΏj8uΛS¦KqcΏ¬�ζι-©₯G+sœšΛx?Τxε•ιϊΎ9{�ΩωR—WŽή°:χ β’ε+ώ=Τ)ΟΎ”Έάγΰr˜/�ΩΈΨq}φ«ί2{³ –οeNZ/ΠόίGLŽ»―ηN›+�nŠΎοΦΉpȐ²yyΖ$–΄�;νυO7Ζ‡zΊϊNΤο±hŒ Τ0Y;xwφχ@ΒFχ#ΈhK·5€οΏQΨ<η]vdΩh0ΰ5ΦΏϋ½[εuƒu$ό™ΟXϋΜEΤΚλ@wg†_cύΒϋO¬γ݈n7NbΡ‚;hγS|ΗΌηΫδŸήkÝ _gX§:ΉHmϊσψ'λYφϊH:ϊΨ΄uκ^Β„)ΗΛ ιJp1§όj]ψ_~=“—΄ΐ/χΞΉμNfΝ“Φ:ΕbQ―GςώΥ)’υ-ošχξG‹ΌηCw₯Nq›ΈχNυI™ΗΑ $tζZάwmς2ϊ·ΰβα3ˆϊp- žjΆ�`φͺΈ©s½Ό&w!·Νύ’·"坊qηΈ»Ρζά©›Φ±5ry9Ϋ«—ΎΎDΞ$ΛSγΖΩ�Z΅Š°°0ύrκ9r1›^¦ŠP]ͺώŠ“IŸ beΉ£rίCνOυ¨ίcQ ˆˆˆˆ‚ ˆˆˆˆ(ŠˆˆˆH΅η­*©@αDMq,"UƒzEDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAPDDDDEDDDDAP*Xίΐά‡ˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ Τ(=G.fΣλΓT"""Υ€·ͺ š*xΑΗΪdΥ‡ˆˆˆœD=‚"""" ‚"R!4ˆˆ(Š(Π‰ˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(ŠˆˆˆHU‚Nv/Œ ž½‘Eζ2ΞI\Λγ½c³όhΩg+ ՟κOυ¨-§ΝΞθ«ω6£kΓdβζžΓuˆΓBs»‡λzRŽˆˆˆˆT‚ hoΛΰ°ζγM$$'°92 ―α΄υυp]OΚ‘3“#ιcYXAΔ8bˆ²°¬όωύι>nύcn₯MΠΉ ύj s Α―ΰΆυάY·Œrͺ«ό+yu5oΥ:^"""•Tŏ 'ژ’“gƒP&Gοcr1Λ²“βqΨƒ °•½niΛDDDDδlΑςΚω›•O½J½©k ­£#"""Rs‚ W†,ŠcˆŽ‰ˆˆˆΘaSˆˆˆˆ(ŠTΊ€C€f9·θQQ€QA‘ΚΙΙή₯pY3,ΛΒjr _+ξΉ3Ό[ωσ3Ÿ“YA°jΣιΡo]£“ώ;qΝ¨yl<œγyΉ©yϊΎylHΘΞύχƒ€₯σœ«z*χƒΰΡΥ ς³°¬Kyχ€K\DDD‘�RΙ8ψ Qσ χ7Ω“ναΖهٝΒΜ_Rp:?gP­bž;ΣU‘w£c’ ? ―ν~τ’E@&)™F ©:t‹Ξj(”εƒ1Ήμ΄ƒΔΎ'Νη†εlOΛ[­€S«Ÿ�3’>AΔ°;ΰγs!!'=ן•Ι€Iγ·ΕcιΧ‘vΛΒ§q/ξϊo,)yρΘXΔe–…Υδ^Φ|9‰>-¬Ϊa|z΄˜όy0šιΓ/αœ€ά^M[½ ·Œέ™%μ)=’…ήcϋθy¬Υ“g?œJDΫ8žΌ{ +>@ZŽš‘θ/S9ϋ,ΛΒΒ`Ϊτβϋιz%I«ο£χπΩ¬ύνY@φΑM,ُ1QG0€ε㏀γžώ41΄TœEϋΡ²wσΖ ύylρwό™š—ίΏρΩ΄ΈκΡoI9ϋθy<͘ۦ°zOIQO3ΈKj{—’DΕ½ΏNEDDίΥR1DΘ ^ώΑtώΗۘΛογνeΠΙ“ X7œhΗrB=±Δžτ\4αϋYώμ»’1#–μΐ‘ξ ξύa4β οN]ΝAΰ坰2·³΅γ |σw:Yi«X·Θλ¦ύŠﳁŽ<·νNηQv,Ήsμδόπ;3ŠΩΧ㧊σ9‡YχxwΌπζΒ'&Ρ»γΖ>ζq�s�Tφ¦‘–'"""•Τίί,eφsνh7k,—7πͺψHίAΤvΰ[Ξ㝂ΛbΧ²3γ4>ώDΖΎ4šΛ—J}›�Ή|ΆηΖ_}%ίΉžk―ILβ[΄ Θλ«Λ,-›αλ§�‘οΤXBΖIΤ€+©gRάΨΗZΉ�tΏG00ŒΟRΣΘtζœH‘'=NΟ@F ‘Β t9ΣHΪύ=‹F7cΫβ�Πχζwψ³΄!l.εΊβ!'€Τ–9φαp|’%έ[”�5ιΒψχ§2°%΄•UoLaτM—snύnŒ^υ7₯Žΐs9ψζ™ώ\=e+]_KΤ³y!ΠΓ}τ`ϊ/όjωγλ­g€Πΐo)ΐςφ§~«ž π(™_-%6ΐΒf$³?ωD΄Κά»‰½εy!―Ϊ\ΜΫϋ‹tŽ9Ws}‘ΏUlψ”Ϊ)i#θ�q|²'„­«YψΒΈΉ[mpΖςΚ½SΨ’^RLfΓ³Χrυ³?�ωρ/‰šάϋDτp=LuΩόz.χθBΏΌσς΅šΣ}πΓ,άzM*#""RΝ�―¬Œ“Τ±|<νΎlJ]/ΐ+f?2ύΉHvΛδθΞ•~ Ψ©ύhξoΛۍό—x§eΩ[pQ“$έΝ;7·%ΐΫ›:!γω°_q#]j³ΝΡΖ=΅‘,rΨϊ|( ΌŠΉhΧƒ}t?fΗσΞ#σΩ 4½y._Ε;Θtf΄#Š5~fκΨEμΝV»‘3.DNR‡sz αΡE?πΕΓρ°κqνά•φ Ϋ3έάW7”}j89’>AΔ"w&οbωΧ£–nE|Φ? €ξπ""ϊ.Τw‘'=–cC™9ε(7/yΉπ²ΜDFΩθ·δ"šΩiΦλΦμΜμE{nˆ<΄ϊy>οr=v}WxΫ¬}l=ܞα ΄[ԍJϋq ω+ Ίω€p0½λ”>CtNΒΗ<ό’y#ΝΌ€μ?Yωξ~.›wmύaψv ww_έSvl«ΥƒΗ_ώ77^ά΄τυ|Z>ω . P‘JΚ?„Q£ϋ\\WXVΫ“9/Ψίΰφ&n'!Ψ[Φο,˜OΔ¨ 9ιξo΅:ήi/‹>ϊ™δΜcΔ­ZΚώΞƒιT ΘIαΠα8^½Ύ)–er' /z 5•Νӟαa/q{뼝ΛΨΝΖύ4ϊαΊXψ΄ΔK?δέΞ·¬}­° θӜώcg²tΝ«„Κr‡9ή΅yό‘ΟςѝΠ4‚ϋνΙ]Ϊ"""rZΈ²HqzSΫ7χΜ§ε€·3…L€!ωλιΌU{·΅/¦ΛΝ»5wΜΓ±‡ΊδW—£ΈgΞ΄φΌ‚θrέ†½ψΗΌwυFΖήωN‘ΫςΊ­ζΉmyβ_]ro“JβΝ|πΫu,ί€uwνg�Θ7Ω•]ΦΎVdΜwόv4αj+ε t u""δήκ¬―~H€²Ω©γ›Mj–ΙΛ…)dϋ`·Ω{Y2)šn…ΣΌΈήΔμ]ΌyίκΞάΖ‘τ#ΔΎ�ˆΧFΞg§ποΞγ ίΰ‘ώm <—λy”q+؞v<r`υgGZϋzZ‚ €s?«'έHΟπujήs)λ�πgV³ί©6$"""U”o3Ί6L&ξ`ξωUη8Α!4·©[ω`}ζΫΓ»IΚV;n}«%άυ§*CDDj4σωγwΝCIl B™½Ιe•q$Όθ–Τού$Ÿν~²ΈR Ίt<Ÿν_|yuς鑁ΕοOΠ₯<±fO”w_+,Ϊ[Ρ«¬ήΉ‘η§,₯γcΧΣΉ±/ ?±bκslhq!-νj t""£`οœζ, ΏΧ|m²κBN‰A°£¦ήΜΌ›>$vΦ-t?ιfΓAD<{«AT89{?ψϊ±/ζΗ^?ψ"ršxp±ˆMo|—­Q/qOΏŽ4Κ|^υhwεm<χΙVG†“ IDATήΪΒƒdYΙΎlϋz6V₯θ6•dŒ‹H₯όl‰ˆH₯δanσ₯yίy½οƒΌ�Ί«rN[OgΑϊYυs�Ϋ9^.§¦ΰWjO"₯Nτ‘rͺ;g'όπ «έSΔfͺR%7tζΟR€z‹ͺ₯―•3CŸ-q“G=‚�Γ_σΒ?Gςά²_9Zά GNΜ/X ^οaaY'υo_O*œΈε]‘G²3w±ψŸέ ²,l―δ±ΟQ‘—cΈύ;0θ?πφΕ+ +Γ� ’x/Ό9 /›N<ΐ}hη―ζ%"r*tΏ[ΘΚ�«L;ΜΏRΎ€…Ϋα˜ΙLΨЈ&'έ#-ώaέ€eμ;Ο�kΧ1vςf� �’Λk³cqZE6͈eڈδ<ϊ=Ž ›ΖΑ¬;¦ηž)Ν9Ζ‘œ&nΟΔƒ1†Γ {SŽίς.χω,vΞΉ’Vαχ�3 7°ξϊο=Μ©?•ΙΔΝhΖ�Η^a{vΊΉmΑ šσ·_Υ–:ή ψκJ¦ήΠ‰ |hzΙ=,ψp ηϋκ$'ϊ™δΜcΔ­ZΚώΞƒιT+7:Η«Χ7Ε²,CξdαοE/ͺHeστgψcΨKάή:oη2v³q ~x„ξ>­ρ�):sIιA0u=·Χ·°¬+ωπεyη°O>Ÿ.R‘?ΕύœΚ—ŸΎEDΔ-�,RœήΤφΝνΦ²|πv¦ι0$=·jβΆφΕtΙy·ζŽyc8φPW‚όκ�aTχΜΉƒΦή€W]�Β°ΏΓαψƒχ�ήΘΨ;ίaov—>΄šηV΄ε‰uΑ/�ɜTlζƒί�cωώ¬»k?“FΎΙ�μŠ{Λ₯Ο#˜}”„£GΨ›δT)%tζ«φsLjbγr΅ £ϊ©όlvκψf“še WV ΩΎΨm@φ^–LŠ¦Ϋ£/Πάϋ«b2Σ.ήΌougnγΘνη°oΡ„œΟλ�M;�ξ<Ύπγ«^χΘ£tωˆνi#9§.€‹«η{ρc h\ ΞςΑ? =�wχ5΄ͺλKΛ{ΗΠρ•Ω‘6–Άu+θ-—ΊΤ·4ΨΞ#ίL 1D½Ί₯˜«\DDD€ΖύαS₯ΟΒψ6£kΓdβζž vˆΓBs;Ί•ΦΗ³δϊΨ‚"ˆqδε‘ξsΩ“ €ώŠν-:€ A~At Ώ…;>γ·4ΐ•Βs0―OΝΈ²1ή~ΉSρ˜Γ|ϋήοtΎ΅'…ς½];ILΝ»NΨπςΕ«Ηα•ύ/δ‘wΡUΓZ€?π:]+’a©ΊͺυxN{[€5o"!9Ν‘Qx §­/Ξ—�Ό«{Λ eΉΓ`~|€Vή€½9!υvπ^δ/$gγ·•π{ύn΄°Ξέ,Έ΅7·Ό²…€£{XσβKμμAηό»±eμ"fg�Έ  π΅φφ Ήή‹ΥοD³ϋΘ~Ύzu6ΏwLΗ Ό‹[‹xΣςΦ7ΩζΘ{Σδ½qSά#šp…F…ΊΚ*ήΎ‚½zΗΟhϊΣ}άϊΗάJ› sϊΥ@ζ>rbΜ^iόBχΦhr¦\D_]ΊMΜΰώ7₯«`οΘƒoώΏ—/₯a`k†Κά7n¦iώEΔΞDώpΤ‘Uύ’#φόι>αmFμI»ϊΝψΏNL›�ZTΰmάάΏΧpή<7""""•ΚZΖ₯•‘gl B™½Ιe•q$Όθ–Τού$Ÿν~²ΈR Ίt<Ÿν_|yuς鑁ΕοOΠ₯<±fOœ¦ͺ³©υˆˆˆˆΤLήͺ‘ͺ­ΰιέξϊS"nS ˆˆˆH ₯AΡ_™"""5”G=‚�#™}ΗeœS[σŠˆ'nχs›“e‹H•α~ λ ΛξΌ†±‘)ͺ5δχͺͺGUͺ““ξ˜""Υ<¦nγ½/rC`Ϋ{σΡδ!tiδ―A†"’P\τ-0 μ¬ϊΉΗλϋάšž·Ν.Υ“H ‚&§ ΰbžœt+!EDͺ:υμ‰Τlξ§ΉΪ]Έα ™ΏΩͺ99Iu½SEΌ‡(β՜‘oΏΛέμbςmγYϊΣA2\ͺ@ύΰ‹κ]€“.œΙ?V:^g νζ_¬T�γ$Nv/Œ žύδ‹\sΧςxοΖΨ,?ZφΟΪΔa'=nwv Β²,|[φγΙ΅‡Θ9©μώZΨ»wα²K+·΄e•'ϋ‚Ϋ―Ό›EqY€ožΑΝ!ρχ�UΓ"U…Υjξi@]εYα?ψ"ω§ΨKς΄u.O[η–όyT{:ƒ\Ž™Μ„ hb/Ί,-ώaέ€eμ;Ο�kΧ1vςf�œΏ3oθΓόzC$ϋŽ&±εI?揜ƢŒ"EdΔςΪμXœ–›ε–Ί¬2AW�™J¦’ˆH �eύΰ‹H%—Λ‡±‘̜r=MΌŠ,ΛάId”~ƒ/’YPSΊ‡υŊZΑΞL€Zt;Ÿ7κMσ:υι|ΓpΞOώ™„¬Β!σΠκηωΌΛ]τp³άR_³2Αΐ0>KM'3;cL hΒΥΖDDD€’ςaΤθ>wΉlVΫ“9/Ψίΰφ&nΟ {>ΝΉfčt °Iί.coΫœο_pϋίY0-žˆQRΫέrK[vxpg/όjy©‰ˆTέ΅G€re‘βτ¦Άoξy]Λ7og ™…†μ�ΆΟγΆϋwpΫΗo�ΦηΔσΙ_Oη­Ϊ£ˆjoηs·Λuη5Oη€ΙζΰΧsΉ@šψε ¬ΥœξƒfαΦ£θΪ©²lvκψf“šeςς[ ΩΎΨm'Βή±f0ΈίlšΝω„gzp|(`φ^–LЦΫCα4χφ ά2_στς GΠΕα/ώEΟώσΩ[πιτύl]9ƒ;V�aΗw˜\°RDDDΔ#šxύ,ςmFΧ†ΙΔΜ‚Ζvœβp‡Π<ο’ηήEŒ›C“Yίπڐf…CTκV>XOτΊ,Ι{*&Θ‚n―°ϋλ«J.Χ”ώš§=ϋΊ½fv<ο<’›ή<—―βd:3HΪΕ‹ƒ?3uμ"φjŠA©Šμm<Φ|Ό‰„δ6GFα50œΆΎ@Ξ~–Œό7ΏŒψσojOΡmΓω�•wΝ„c9‘A‘,w̏Πͺv)ε–φš•*¦ν$: gάΛ­ρυΆSΏ}_ΖΞ™H7ΐlύ”_ΣԎD€β{H4›ˆ”¨s|鏂’#ιcYXAΔ8bˆ*8ύ?έΗΝ‘Μ­΄ :—‘_ dξc!ψ€lfΑ‡Ω1­ΆόiσΞc�/ξ\ΥQJΉ₯.;ύά?5leδ]d0 eσΖ+o%Kη…Eͺ\ΘΚ§SQ"Rν†mJž ΟΦ ”ΙΡϋ˜|�vƒY›c܍#αξ•[Ζ²ΣΝύA�σιί ΰGžypλwΕ™“Ι‘ί£xω_ΨΠωΪΒ—Q‹ˆˆˆH₯ε~ w+†Ν|ˆΩWΎDάΗcΈκγ1EVΈ€‡_N+oUͺˆΤ,•}pΏz}E€$\œlxΕ lΨτ_Ζ θL£ό«YόšΠυϊykΛ¦]^WW ‹ˆˆˆTφίΩ¨ΧγŸΜϊμŸΜRέ‰ˆˆˆTi6Uˆˆˆˆ‚ΰΙς/±ΆϊΉ'��K{δ_~-""""U;ŠˆˆˆH΅UϊΑ"sν„£©&άο,xšΈΘι_s`—YΦyٞ₯J}Ϊ:—§­sU"""RM‚`‰²9χϋvodw†*UDDDΜόΫP–τ8™“έ #¨g?Ήs+'q-χnŒΝς£eŸρ¬MŒ eζ”λiβUdYζN"£lτ|Ν‚š�=¬/VΤ vfΤ’λΨωΌωPošΧ©Oη†s~ςΟ$d™‡V?Οη]ξ’G€»εVφ θӜώcg²tΝ«„Κr‡Α˜"¬x–ξ„n5,"""•–£Fχ!ΈΈΛe³؞ΘyΑΎψ·'0q{nΨσiΞ5#n€S€ΈHϊv{Ϋΰό‚Α'λwL‹'bΤ…Τv·άJσε]AlL4၅e'όπ «έSΔfͺ‰ˆˆHδΚ"ΕιMmίάσΊ–oήΞ2 η3€mŸΗmχοΰΆ9�€­Ο‰η“ΏžΞ[΅Gq[{{9Κ­μApώši7t$°ΘD�>ΝnbE*p4£9e•RςΝ’JXYY]ŠˆˆHe³SΗ7›Τ,“—ίRΘφ ΐn;φŽύ0ƒΑύfΣlΞ'<Σ+€γC³χ²dR4έ §Ή·§εV… h³ϊώAŒ[φ+G‹Yl;ˆρσ'Π³V©Q²”šE•6°²ςΊ‘*Κ·]&w0χœ­σ@ŽΰšηeηήEŒ›C“Y_ςڐf…'cNέΚλγYr}lAΔ8ς.�ν>—=Ά�Λ­A0υ'ή[γZρΰΚ·Έΐv5ΕΗ²πΆ˜]±τφΓ«΄2J YTi++ρ K91ŸͺζT•*Εή–Α`ΝΗ›HHN`sd^Γiλ δμgΙΘσˈ�1�¦ψέ60œ/]yΧM8–”wMŏΠͺv)εžeήn―™sŒΗZsE§zόh�,œφάSΜyw$oŒžΑύΧL§»_ eψ‡0j4Yφλε ¬Ό±ΠΐʏIΘ‚.”²Μ�v\]~D&š]ͺ )ΥwύιώΚΙ‘τ9>%ΔYδ^Mx ?έΗΝ‘�·�ζ™$_σ8‹—„ΰ²™_fǚ^LΛ/¬=·�ΜSΛJt₯”[e‚ w ΝκG,Ό|iR8ϊ++ΎM _πN’ώΪΖ_™”=QκΐJχ]�Z΅ͺB*ͺ<εx²MyχσtοWq۝Χ¬¬uQΫXύ§bržΟύΗ¬ϊάϊ}φρεηߝϋwgΟ•³4;ΰΔ6Ά[΅{N₯nη§£ή­ώS ΧG‘:Μ―Ώ�κpΥƒ‹ΟΪχDUh»ϊWάoJuϊ]8m°BΉ}nQΆ‘LŽήΗδ“ΆΜΪγώk w―ά*ύ;0θ?ήωΒ―€� »6–&ρ^xsήΛ_η‚>΄«¨ωc ¬΄Š ¬,mYaaaa�—“χRΡΫ·ŸεΪξ4ΏΦΔ‹O­.ΞdVzŸΈbq…ΦE±ο§Ά§ŠͺwOκ―΄: k=ϊΔ?:ΗW\ύUςΆ[ξϊΣηψ΄~Ž+Εϋ:CϋwΦC‘x0FΠΜ 9―qϋUm©γέ€―�dκ ΐ‡¦—άΓ‚Ηp~Eο.mΐ¦oεt)r6•|;%‘“y{²²½ννΌu{ξ?�dάG?3ξtνYή€Νϋ>ήΔύη΄eWd^_ΝXYΪ2‘S Σΰα˜#‘*ΚύΑ£«δgaY—ςξrΞΩWπΎΕω—U[ζLŽ€O½όη ¬ŒΉ•6Aη2τ«Μ},`eiΛDDDDΔ\,D‹ ΰ@&)™¦|―VΖΝμ€xφ`ςβii++λ K‘ͺΒύΑZ=yφΓ©D΄γΙ»§°ςη€εTΰžδόΝΚ§^₯ήΤ—­£#"""Ry‚ΰ±hΖά6…Υ{�HŠzšΑ]šPΫ»π­ζ ζυ”W†,ŠγΛ;[ΰ₯γ"""5œ&δ–3ΑύSΓ�Tφ¦‘:©aA00ŒΟRΣ°ωΪρυΆ©ζDDDDͺ8~΅όEDD€R)xoλβ's²{aυμ'iΛI\Λγ½c³όhΩgoΞωΙ?“U8dZύ<ŸwΉ‹Υ-¦mαŧאB}nž?‹K .3Y€dΒ±¨ˆMU+�»°EDD€Bψ‡0jt‚‹»J"+νIœœ{«2ίΰφ&nΟ {>ΝΉfčt °Iί.coΫœο_pϋίY0-žˆQR»ŠT‡ϋAΠ™Θ‰Ήακs(Ψ›jœι8R“Hu©‰ˆˆHδΚ"ΕιMmίάσΊ–oήΞ2 eCΪφyάv�n›σOΪϊœx>ωλιΌU{·΅·W™·μ~τ;‡-~cεϊ}dζΦ™Ž?X=c:Z^DK»Ϊ‘ˆˆˆTA6;u|³IΝ2yΉ0…lίμΆaοΨ3άo6Νζ|Β3½8>0{/K&EΣν‘pš{W·μώ�Ϊ;2κ™0^Ή}‹οχδzniέ.ο�ήDBr›#£πN[_ g?KFώ›_Fόω7΅ΐ§θΆα|ι2c0Žε„…²άa0?Vή˜›ξ<βGλ°'Xφ„‹ˆˆˆT υ 'G�'(‚˜ΌΖY@(ΛΡ„ϊΣ}άϊίx+mžI’ρ5³xI~)›YπΕav¬ιEΐ΄όΒΪ3qϋΟ<ΥΡ·Κ֝:πDDD€ζ 'Ϊ”<ם­A(“£χ1ω€ν³6ΗΈ�GΒ«DuΨΚLΝ–…εφ£jΜ’-""""ίYDD€fΠ8K© J?5\Fχ©ˆˆˆˆT]κ”jC=8ͺC9­A0“?Ώ˜Ι¨λΊΡ2Π Λή7wL`ΪχLΈε1VΜQκ‡[DDDͺ�v²λυpBξ]CΚρηςξΉ’ΔΆΘιΜΞΉ‚ψ₯ƒh`©bEDδΜύAœOQkRnρŒϋ=‚i[xρι5€PŸ›ηΟβ�‚ΛL)™p,κbSU©""""Υ+:ω# #7\}ο$gœι8R“Hu©REDDDͺWτ;‡-~cεϊ}dΰ"Σρ«gLg#@Λ‹h©{ ‹ˆˆˆT wdΤ3aΌrϋ*ί=:οΙυά�Ί]ή�2x�(:*ŠΤ($"RuypΥ°7-G,eΫΚΙ »΄5uςŸφi@ϋή#xnΥV– k©{Φ‰HΕΊŠ_Dͺs›­Γž`QΨͺΉ*ώcκΑQQ(V0}κ{°FςlBiη~VOΊ‘ž=ΰλόibRΦ32€αΟ¬fΏS*""U'όθTΎΤtτ¦³uR_�›όψ\ΗΡό›ˆΈŽρη―ΫXύΣuΔΫ~βϋ§Ίΰ§z©τ<˜PϊζΞ� ¨ΟM ηΡ7�j‘:ύ˜·ΰ‚€Ψyσؚ¦J‘�εχΔ¨7¦p}ˆˆTή ˜ν`Ÿΰ"ϊ΅Βž9ΛNλkn #ΐαέ$e«RE?ά"""Υ+Ϊ[Ρ«ΐFžŸ²”­ ©d»œ€ό΅…χ'=Η€jBi‘τ±ώ(�Ϊ<˜PΊ£¦ήΜΌ›>$vΦ-tŸUt… "ž½OJ‹ˆˆˆT\5μEΣίekΤKάΣ―#ςŸW=Ϊ]yΟ}²•χ‡ΆΠ|4""g€zbD€"x˜Ϋ|iήχA^οϋ ―«ξDDDDͺ4›ͺ@DDDDA°lšPZDDD€ΪΠ„�""""5”&”Q,ƒ&”©‘APJ‹ˆˆˆT+šPZDDD€†�„�""""5”&”©‘*dBιΗ―|2{ /Κκ£ͺT‘ͺ όgrM{ΎZΒλσζ1Ιf’ε^£J©–AΠyθGVΌ5Ή―ΎMτžόΉbκ�yНά3r$}κ¨R««ž#³ιυaͺ‘s޲cν"^›;7VlηX‘…½xcο7άέR—‰ˆˆˆH鞢Ξ`’Ω₯Κ¨A0υkξνr%―ΗηώΣ~ξΥάsΟ½άax€Γ­¬£ λ*ŠΈϋε§/@©:A0;‰ρ€­·ΌΌˆWΈ˜z6 9Kυ'"R%� Ρ#"ξ\5μ݈�}ΐ΅“%c.‘a«+ΉγΩχΨΈ/]RsDDDjκw Ύ₯fΑΪ—2ληdφ¬_ΐ·\D½}_³π©a\Ϊω¬ •ƒ§jRDτ#,"Rν‚ €εΟ9WήΑδ6sΰΘΟ¬xι~ϊ·ΛΏ΅Θ&FΆ�O§Ac™½κŽΊT©""""Υ'ΰΤ‰AΞeΝϋΎy‡§†φ"˜~Y5›±ƒ ϊ˜*UDDD€ZΑγ,?š_vG‚γ>™5šλz5Ε�+HDDDDͺ„ ™χΕ+°ΗΜfΰU¨ˆˆˆHUaSˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Šˆˆˆˆ‚ ˆˆˆˆ(Ί+'q-χnŒΝς£eŸρ¬Mt•²Ά“έ #¨gοCdς©”#""""g9¦±εΩ1¬°Œ}GβYzν:ΖNήLz±λΊ83™ ΡΔ~*刈ˆˆΘΩ‚™;‰Œ²ΡoπE4 jJχ°ΎXQ+Ψ™YΜΊι±|ΚΜ)ΧΣΔλΚ‘J³؞ΘyΑΎψ·'0q; YΕ¬λΒ¨Ρ}φ>ΕrDDDD€X–1Ɯ±WK^IΏsgπΐΞ†ΤŽ,#΄έ<ώ³λ –΄M$}ZΏΜΏwGθy9«V­�Q� W$στΰ@U„κTυ§ϊΥc… S%œMζL:ΊΖD4ΉάΌϋ·ΛcLΞίο˜Λ›D˜5GKΩΖ±ά„…šεŽS,§€•+W–kχΛ³]uz­χ,R]Tπk¬ΣκπΎΞτώyZj»%¦υ9�ܟcΥ»œ.gφΤ°o3Ί6L&ξ`ξ9\η8Α!4·Ÿ₯rDDDDj°3νm<Φ|Ό‰„δ6GFα50œΆΎg©Α3şξγζΠ?ζVڝΛΠ―2χ±ός'G�§^ޜΙ‘τ±,¬ b1DYXVώ|‚e”#""""eς>γΙ³A(“£χ1Ή˜eΩIρ8μΑΨ€:αD—rKi刈ˆˆH% ‚%Κω›•O½J½©k ­£#"""rΊΩιc€Jλ9r1›^¦ŠPͺώT’z”jΒ¦*QAQ,*Z—b}ˆό³ΐ0gJςYxM‘s§u1Ζ`Λ eΉ#οί&šπΊU³"rΧςxοΖΨ,?ZφΟΪD—[9Ω½0‚zvχChzάξμ„eYψΆμΗ“k‘SζV†ΤΨΧΦ΅6ΛΒήϊZž‰Ntc;€ώZΨ»·»ϋθΒ±ρ†œWΛ²¨Υn0SΏ=‚λ΄Τ_u¬ΓςΥί™lƒε«ΓS©ΏκW‡ϊλs¬Ορι«C©μAΠ –εdη›� ½έΒςi͐yΏ‘˜CοsU‹LΣƒZ΅ϊ³2œ{—r�%Mρ΅,κχόΛώΚΞ+%›„UΪ�ŽeYΨ]Μ�ϋg^cNωρ�kξ…U«w°'οy€ βήΊξ mΉŽ‘<ϊιίΜWβϊZIDATe4τ4Ά<;†u–±οHΗ§±₯ZARΰύύΓψ")•=K�ΰ»ΙΣΩ” –^IίπYƒ™μ9ς)ΧΧ9Hδ}χΥσ vω�φξ<Ύζ+�γψλ›εf•Ε"Α*D-QSUBΫ©ΦŒ5ΚPEι2ύiu‘ΥφΧκ(j{ύŠΪUŠΆΤ„–nh• ΦX$"ΛMrοηχG‚Œ‰+²εσ|<ςχ|—Όο9'ηžοχžοVwˆΰΕ±ΫΈ"@z$�|%œ€Y‡I1_εΰ‡>¬yωφ€–s¬~ω.Žϊ‰K‰�fpάJφ]Λ=vΚnήxm]Β/‘™ΔοοΦ`ν�Μ°]ωΜΗίnΗγέ[QΛ«&-Ί>†±ύKŽ™m};ΐš!L― >φ Ζ•fŸΟβqνρ­T™¦½ž‘Qrq™wYWβ‘ KXςςΓΤpυ’iο!^-ΐvXIψζΆ=K°{O1σ,‘—ˆ§“'=ΒΈΙΉΜbΞ―ΌfX˜όξi,d†…Ξ―CγλΟ—sπΔΧ5žˆ/Ύf¬ζdΤ΄°υόΉΜ8’/y�°ZΞÊMΥπLŒΆέ8\δω—:Rνn–δvτε‰Α½iβnV.ύψ§λw¦‘˝Ά«EΗώέhΰd]ζχUK9έ4”@Χ;5Δ£|ϊαIz<ί·χ-Mmršελ£H6§³y-η›v§‰k1ηW^3,L~χ²6ΓΒζW3Τv¬νXΫqΙe¨ΚɌ ½;Υάs?ΪΨ;b•«V;xQΫ+·Ζ[RHˆίΛθ:†c½—Ψ{:–ΛYٜί<Ώ4¬ŒΙ00ͺταϋ€ά½XRIΜp‘zξ1μ=|πΈήˆ\‚yΫ:Η/dp' »1yϋEΫ—†­™\ΛrΐΝ”3ίm˜άqΘΊ†ΉΔnf�’η2hτΝzŽϊŽά,9œŽ¦*΄z5—f‘žƒνc$οžΚ·ηpΧκ2dξΛ€Œk†—³Ÿcψ¬!Τu(Mω•β “_YΚπ�ς+οj;Φv¬νΈΨ3Tεd h“έυϋ <πρmΗ�8Kξ—MΙήFWO υgήΉ‚κoFp*9ƒΜψ΄υΌ~Φ.x›�Έx-gx—t–€μ›ϋw θΙ[Λwqβj2{ί¬Δ’Ώ½ΖO©ΆRp’’)›ΤLΙmΛΧΘ6ΉγT2σ₯€ό6ξB­Y[˜ό;½νΟP"Μ μ}ί™iϋ„[Ÿ2³O³ϊ4Šοέ4Όμ,5 ιϋΉ’~…³«3oΔ|Že•–όJy†…Ι―,ex7ω•λ ΅k;Φv\"ͺŠ0ΜΓ΅ ½ZΖ2{ޏ\LO"zI?wψˆC™€Ι‡ζψQΏQ]Ό-ΗΩ4{ %™“3—:ωηΣΟ#IJgΧ’Ο‰Ή~`F$o΄ lΩ!’,&ͺψϋα.f²m=HΟT‹fU“‰Ή˜Σ².ĐTνA|Š�WΞ:½œΑ]gα33‚y=kμaΟ™±l˜±ˆ_― †©*­Β†�ΰTGm݁œΙͺοO²ΊKμΌz°3i'=Ό Œs8•mk»ƒ|]›°žAx9{Ρ$΄΅|Να΄�‘_©Ο°0ω•… “_9ΞPΫ±ΆcmΗ%”‘ͺ`A£*]gΟβ‘m½πqυ¦Ωλρtu0 M€c†½ίŽ΅{γR»�ό1ΛF^e샽ω:͟°cpϋ8oοώ―ΦPBͺ€Ε 87eΤ[OϋJήN.ΤμA‡iο�ΦΦΝ­NυιήΆnΨK\rϋΒ·c�t(υMΕόϋZΞ³zΔ^Ηό>΅q,pN™[ϊ?Ό8ηΣ.³υUn…Ÿσ>ρYσYζηχ¨c«·pςεAο#|~ds ‡7­βhεζΤv*ω•… “_YΘ°0ω•Χ ΅k;Φv\rͺ{O”ˆˆXwΘλ!Ύβ„³ψ?ρΆμΊl±½A�F α?~Bdγιβ"“ςΫ&\:ΩέΊM€ΌmΎΓΩY%%ςιΣΘMqτ{B&νLΛυσΈέρςžλΚάLB.}χŽt�γ$€˜ό�"“s<|yρεg+C›ΏKρdhΨyK�-ΉD3Ό}~ωΙ›i±ΥΑ;c‘2΄Qοc†·ΦΙ{’aI΄γbΝ―ΰ9ΏΫfθ%―ΎGnYVπ\΄-ΏΜPέ?:,nwΥY—­γΩκ{TΑ3Υό4Ώ Π–ΛzXŠϊCu賆‹>§jcqk[ fƒεΒV&>ζ‡Ι00ω?ΙΫί]Ί±κΊωψ2ž}ΠΓ0pΘΒΓιE>^ir»σ”ΔU„ψχdތ09u}ˆ Νμφ’υ±ŽeVΉΘQϋ@ν•ή#X‘ΩZάΪjcΑlk"›Gγ«6Ÿq*5™θ«²tτ΄œ…―­ρl=Ž=O�γΜΥ‹lλ{‰/¬'ΞZ„γ•&6ΞΣppΖξβ6 ckb*±+Ϋ²ηύΨ—ZΑ3SJϋΐςٞ΅?Tz`—ςoιW«΅Μ=•-""Ω±³₯Ή{ξ4{Κ σ½ωZΦΙY�Ίήpω!υϊkΑ2;6+Ÿ}FΘίΌϋœ#Α΅ϊKDJŽWš.Ψ:Ο€R©•Μ?“σš5a•΄σκ$αIe3³’ΙΤ*)ΏM•Ξ΅μ—@yvήLy$Ο₯ΜSkdTqρ~A6œ½™Wvό7ςZ§ΪββθχίχμdϋL†6σ@ά‡Ι‚CiE>fiΏ$w»s·&¬”~=δ_ΣHC'{ι>λ € Λ²’c±΄ι Τ–HŽΪ*½4\Φ? ΫXάΪΦ‚Ω–.€ΉPέ=Ÿ―\Y�‘ξJJ7χι–‘Θ5KŽWͺ2»ΓyΪWΊρ»ŽΞ8\_Ό"gV�30TΠYΡ>PϋΓ²Ÿ�KΓχ?A‹[ΫZ0Ϋήƒš�Χ8—œΟύφ•¨αšJά՜ײ―Ζ‘κRJφE8^iRΨσ¬Θ™εeλ‹ΆۘŚ_j2|δ£Τtυ `ΐ NFΏOσΫbSt=^x±΅+U£ΝΠαΤ=Ό%gέ―Β³΄³u˜3bLξγ2;ζ<.σrφ²¬h9j¨ύ‘�`…fkqk[ f»5‘Wπ9ζΞψ–³i)[=ˆΊώΑ―ι€k =<ΝΌy»‰K‰η‡σ9ԝΖ�E8^iRΨσ¬Θ™•τ LEEΠΩν΅?,Ϋω)ή�Os6·Ά΅`ΆQ•nsΠεΧ!ψ»yΠhάyΝ}•ζ.€]uΊΟšFλ-έ¨εQ“Π―bϊœžΤ°+ΒρJ“ΒžgEΞ¬€g`*κ,‚ΞΖh¨ύaΩΞOή&©tΝΆ2–iV¬Μ}Θ[Z�ο>Ή’'o<$NΉ7{[δ‹΅%x�.ΉvE’χ•ΪO•ƒζœΧ6„V—€—Ύ’3©Wεθͺg€NΓq²οϊχ,dm—κ�τΥrώjœμœ$Υ:―’xKŽYΪλ€­sΏu}΅Ό�Ά•eΚQ۴樔Ξ*₯³ΠΉ3pAgc”Rœ!"ΊB*Φ#V°wΑ@ B3Υό4?₯9ͺrBg•RJ)₯t ¨”RJ)₯t ¨”RJ)₯t ¨”RJ)₯t ¨”RJ)₯t ¨*"ύVœRJiί¨t ¨”RJ)₯t ¨”RχΞΔ¨Β2ΗnδΝρq60 Γπ nΫ‘Μή›„΅ e’Γιh\-οOGΒ“…”ύ ώh=<ν Γ‰ZΖ’¨kθβ½J‚ͺDI�7τσΜν\žf}‚`9»„φF΅gΩ™rΛΧv1’†aΨQΕέΐ°kΑδ}y;+!υ·w v00Ζ±σδ|ά―• Γp₯nΗ—YuŽ>/_‡y 8Κ£s’%vΣ©B‹εh¦¦―Ο(-„€ΒόxHƒΗΗΘΚ#i·”Ισμίν³€ε΅ώU°:·Yžt@ ΅,>g)B™‚Χ3kΒ*i‚γS²%Yλž�g «’bM bξV�`μτ±ΙŽy[‰oBΖΕ—tΆ|΄–ΣΩΉε-gΨπΡ&Rρeθψ|Ždεϊψ]XN�ή3ˆΊΝΜή}ω,Ύ }—―αεΊ'ωςηphΑ3έαίζI’Ά“�ρ«’ȝU±\γΘ²'Έ΄}B§q0³»ς eΗυ™OMVέΒ₯>μeD‡�Œ~w›φž&Υz—e ʒāuK‰Ό»₯…›ΎJgU ±œ_&&KΤΥ(™€`΄•Eg²E2cdjςց 1GΏ#@š*17fτ�δڈ#ˆ»―»�pό.I²ήz΄L‰]ό„Έ€ΰ7Nφ₯kώ:#S”Α›³*Φ„•ςŽesr~e¬r5rΎ {ΈΆ8ƒ€£Τ|θYYuM¬ωμσΖlLεςιάAς€ ‚[ŒάpN²΄ώUHζΣ›eRΟfR9οLtNςfD‚d΄LΎ³Ω·Μζ)γΡv’μH΄h›W₯ŠΛ•l9³¨­ &E‰Y2$jR$xΞIΙ’l9Ώμ11Tώ½€X―Ι£j ˜δ±eηot~""’±_&ώ)·Sσ(Ϋώ벇YbW‘Ί ΰ.O/=U‘� κβbZR%fi¨x‚­gΚ±Μ|Κdό!“‚ώ$γw'Θω―†‰§H΄9Ÿς7ώ]Cz̏”#λϊŠ7ώγεΧt­™Υœ ‡Ώ_%Szωετw΅ΗώΧ‡ΪΫ–)θ₯α¬Λ²~7ρql�/9‘₯*Eτ�py’}†πy?"ΐ±·›βd8Στνcμ[Έ‘SΩφψt@oΈψω4ΆΫΑΗΛγΐ»Ίϊ`cGι˜9’N€ƒ—\YΑKοώ@ςo˜9Ύd­ϋ-%7ΪΏ·Οωγ ο€*’τπ20μέh4d+^Η±nνσΤwΜ§¨S“�ΘBδ8=R…κ-§ΐ‘ο8nσ?Ίt ’AϋžœδœήΈ_‘¦ͺ4z΄―ΟϋΆŸyχelrπ&¨Χ@‚€¬ŸΒ9˜¦Ή«�C‚εHVμμόώΑ―ιΉί^KίΗ8? rλOdax=ΚΈηκ@κf&½ϊ&_¦@ηΖρ¨—‘»+‰[ΗΠuΒΟX[½ΓΟ‡fJ°=1�μΑΘυqX°rιΫ1<6l ΤaΠςύlΨO­IͺΘς~σ2ΨˆiτͺcΊ]mημchοο†aΨαΰ3€έ–llίΒεN5w; “ ŽΦ;•WεRζf>α‹«©6W%Ŝ̑M«ˆμZu%Π΅€elɈδυ g £ίOܞ­hЎ?9λ[ t ¨ŠΏgγψš…όψυ #πzGγΘ€ΏΦ’YΌϊ(™84r,-±πΗ†H²hΙΨ‘A\/žyla½pΊj_V„ΏF«­x5|%ύ«%²z`_fύώ#ο ›Η)ΌψλͺY2°>Ϊ§©{.υ'^n&»ΞΤΰ;0_\Ι#šŠ*(SΓ¦ΏΗ°n|=¨!Ξ^4υ u{NbσΊΤs(`™rg³σ�#hnΖψ…Φ2uͺ‰o—εΨ΅Ζ’ucyΐ€o� *nζV,9 ψΡ7,0ΟΰΜ…&aΕ8²τsbΜΰX―?:η”pξ<ώυr�½Iςnήθ:ŠoΣ›ρζ–EτυΝιιjυfαW“i‘½›±‡πΙ€$ΦχχΕρ?PΥ·Aέ#ΦL�2sκwο,φΆ˜€q9UηψԝΈ7Β¬ocΈœ; mŽ'rΓdžςu,x™ίNΏυg‘žvx�y +~'S‘LΞ�Όˆa�ϊ¨RDoλ*/œ‚˜rL˜’ΟK.­gpVfδωŸτύ:Ύ·vžν˜zX˜š_§<‰ί,“4gU:TjΛ[SΊ²η•ΝL nΓwo~ΚϊιŽτ™°•;’~ΔӚ‘RJδc‘ˆθΣn”ΊOZX‘ISZ�”Rχ^VJ© JJ)TJ)₯”ͺ tFP)₯”RJ‚J)₯”RJ‚J)₯”RJ‚J)₯”RJ‚J)₯”RJ‚J)₯”RJ‚J)₯”RJ‚J)₯”RJ‚J)₯”Rͺ”ϋ%Σ#Š’{ηIEND�B`‚pybase64-1.4.3/base64/bin/000077500000000000000000000000001500645130400150065ustar00rootroot00000000000000pybase64-1.4.3/base64/bin/base64.c000066400000000000000000000362701500645130400162460ustar00rootroot00000000000000// Test for MinGW. #if defined(__MINGW32__) || defined(__MINGW64__) # define MINGW #endif // Test for Windows. #if defined(_WIN32) || defined(_WIN64) # define WIN #endif // Decide if the writev(2) system call needs to be emulated as a series of // write(2) calls. At least MinGW does not support writev(2). #ifdef MINGW # define EMULATE_WRITEV #endif // Include the necessary system header when using the system's writev(2). #ifndef EMULATE_WRITEV # define _XOPEN_SOURCE // Unlock IOV_MAX # include #endif #include #include #include #include #include #include #include #include // Include Windows-specific headers. #ifdef WIN # include # include #endif #include "../include/libbase64.h" // Size of the buffer for the "raw" (not base64-encoded) data in bytes. #define BUFFER_RAW_SIZE (1024 * 1024) // Size of the buffer for the base64-encoded data in bytes. The base64-encoded // data is 4/3 the size of the input, with some margin to be sure. #define BUFFER_ENC_SIZE (BUFFER_RAW_SIZE * 4 / 3 + 16) // Global config structure. struct config { // Name by which the program was called on the command line. const char *name; // Name of the input file for logging purposes. const char *file; // Input file handle. FILE *fp; // Wrap width in characters, for encoding only. size_t wrap; // Whether to run in decode mode. bool decode; // Whether to just print the help text and exit. bool print_help; // Whether to strip newlines from the input when decoding. bool strip_newlines; // Whether to ignore any character not in the base64 alphabet. bool ignore_garbage; }; // Input/output buffer structure. struct buffer { // Runtime-allocated buffer for raw (unencoded) data. char *raw; // Runtime-allocated buffer for base64-encoded data. char *enc; }; // Optionally emulate writev(2) as a series of write calls. #ifdef EMULATE_WRITEV // Quick and dirty definition of IOV_MAX as it is probably not defined. #ifndef IOV_MAX # define IOV_MAX 1024 #endif // Quick and dirty definition of this system struct, for local use only. struct iovec { // Opaque data pointer. void *iov_base; // Length of the data in bytes. size_t iov_len; }; static ssize_t writev (const int fd, const struct iovec *iov, int iovcnt) { ssize_t r, nwrite = 0; // Reset the error marker. errno = 0; while (iovcnt-- > 0) { // Write the vector; propagate errors back to the caller. Note // that this loses information about how much vectors have been // successfully written, but that also seems to be the case // with the real function. The API is somewhat flawed. if ((r = write(fd, iov->iov_base, iov->iov_len)) < 0) { return r; } // Update the total write count. nwrite += r; // Return early after a partial write; the caller should retry. if ((size_t) r != iov->iov_len) { break; } // Move to the next vector. iov++; } return nwrite; } #endif // EMULATE_WRITEV static bool buffer_alloc (const struct config *config, struct buffer *buf) { if ((buf->raw = malloc(BUFFER_RAW_SIZE)) == NULL || (buf->enc = malloc(BUFFER_ENC_SIZE)) == NULL) { free(buf->raw); fprintf(stderr, "%s: malloc: %s\n", config->name, strerror(errno)); return false; } return true; } static void buffer_free (struct buffer *buf) { free(buf->raw); free(buf->enc); } static bool writev_retry (const struct config *config, struct iovec *iov, size_t nvec) { // Writing nothing always succeeds. if (nvec == 0) { return true; } while (true) { ssize_t nwrite; // Try to write the vectors to stdout. if ((nwrite = writev(1, iov, nvec)) < 0) { // Retry on EINTR. if (errno == EINTR) { continue; } // Quit on other errors. fprintf(stderr, "%s: writev: %s\n", config->name, strerror(errno)); return false; } // The return value of `writev' is the number of bytes written. // To check for success, we traverse the list and remove all // written vectors. The call succeeded if the list is empty. while (true) { // Retry if this vector is not or partially written. if (iov->iov_len > (size_t) nwrite) { char *base = iov->iov_base; iov->iov_base = (size_t) nwrite + base; iov->iov_len -= (size_t) nwrite; break; } // Move to the next vector. nwrite -= iov->iov_len; iov++; // Return successfully if all vectors were written. if (--nvec == 0) { return true; } } } } static inline bool iov_append (const struct config *config, struct iovec *iov, size_t *nvec, char *base, const size_t len) { // Add the buffer to the IO vector array. iov[*nvec].iov_base = base; iov[*nvec].iov_len = len; // Increment the array index. Flush the array if it is full. if (++(*nvec) == IOV_MAX) { if (writev_retry(config, iov, IOV_MAX) == false) { return false; } *nvec = 0; } return true; } static bool write_stdout (const struct config *config, const char *buf, size_t len) { while (len > 0) { ssize_t nwrite; // Try to write the buffer to stdout. if ((nwrite = write(1, buf, len)) < 0) { // Retry on EINTR. if (errno == EINTR) { continue; } // Quit on other errors. fprintf(stderr, "%s: write: %s\n", config->name, strerror(errno)); return false; } // Update the buffer position. buf += (size_t) nwrite; len -= (size_t) nwrite; } return true; } static bool write_wrapped (const struct config *config, char *buf, size_t len) { static size_t col = 0; // Special case: if buf is NULL, print final trailing newline. if (buf == NULL) { if (config->wrap > 0 && col > 0) { return write_stdout(config, "\n", 1); } return true; } // If no wrap width is given, write the entire buffer. if (config->wrap == 0) { return write_stdout(config, buf, len); } // Statically allocated IO vector buffer. static struct iovec iov[IOV_MAX]; size_t nvec = 0; while (len > 0) { // Number of characters to fill the current line. size_t nwrite = config->wrap - col; // Do not write more data than is available. if (nwrite > len) { nwrite = len; } // Append the data to the IO vector array. if (iov_append(config, iov, &nvec, buf, nwrite) == false) { return false; } // Advance the buffer. len -= nwrite; buf += nwrite; col += nwrite; // If the line is full, append a newline. if (col == config->wrap) { if (iov_append(config, iov, &nvec, "\n", 1) == false) { return false; } col = 0; } } // Write the remaining vectors. if (writev_retry(config, iov, nvec) == false) { return false; } return true; } static bool encode (const struct config *config, struct buffer *buf) { size_t nread, nout; struct base64_state state; // Initialize the encoder's state structure. base64_stream_encode_init(&state, 0); // Read raw data into the buffer. while ((nread = fread(buf->raw, 1, BUFFER_RAW_SIZE, config->fp)) > 0) { // Encode the raw input into the encoded buffer. base64_stream_encode(&state, buf->raw, nread, buf->enc, &nout); // Append the encoded data to the output stream. if (write_wrapped(config, buf->enc, nout) == false) { return false; } } // Check for stream errors. if (ferror(config->fp)) { fprintf(stderr, "%s: %s: read error\n", config->name, config->file); return false; } // Finalize the encoding by adding proper stream terminators. base64_stream_encode_final(&state, buf->enc, &nout); // Append this tail to the output stream. if (write_wrapped(config, buf->enc, nout) == false) { return false; } // Print optional trailing newline. if (write_wrapped(config, NULL, 0) == false) { return false; } return true; } static inline size_t find_garbage (const char *p, const size_t avail) { // Use a lookup table to distinguish garbage from non-garbage. static const char lut[256] = { ['A'] = 1, ['B'] = 1, ['C'] = 1, ['D'] = 1, ['E'] = 1, ['F'] = 1, ['G'] = 1, ['H'] = 1, ['I'] = 1, ['J'] = 1, ['K'] = 1, ['L'] = 1, ['M'] = 1, ['N'] = 1, ['O'] = 1, ['P'] = 1, ['Q'] = 1, ['R'] = 1, ['S'] = 1, ['T'] = 1, ['U'] = 1, ['V'] = 1, ['W'] = 1, ['X'] = 1, ['Y'] = 1, ['Z'] = 1, ['a'] = 1, ['b'] = 1, ['c'] = 1, ['d'] = 1, ['e'] = 1, ['f'] = 1, ['g'] = 1, ['h'] = 1, ['i'] = 1, ['j'] = 1, ['k'] = 1, ['l'] = 1, ['m'] = 1, ['n'] = 1, ['o'] = 1, ['p'] = 1, ['q'] = 1, ['r'] = 1, ['s'] = 1, ['t'] = 1, ['u'] = 1, ['v'] = 1, ['w'] = 1, ['x'] = 1, ['y'] = 1, ['z'] = 1, ['0'] = 1, ['1'] = 1, ['2'] = 1, ['3'] = 1, ['4'] = 1, ['5'] = 1, ['6'] = 1, ['7'] = 1, ['8'] = 1, ['9'] = 1, ['+'] = 1, ['/'] = 1, ['"'] = 1, }; for (size_t len = 0; len < avail; len++) { if (lut[(unsigned char) p[len]] == 0) { return len; } } return avail; } static inline size_t find_newline (const char *p, const size_t avail) { // This is very naive and can probably be improved by vectorization. for (size_t len = 0; len < avail; len++) { if (p[len] == '\n') { return len; } } return avail; } static bool decode (const struct config *config, struct buffer *buf) { size_t avail; struct base64_state state; // Initialize the decoder's state structure. base64_stream_decode_init(&state, 0); // Read encoded data into the buffer. Use the smallest buffer size to // be on the safe side: the decoded output will fit the raw buffer. while ((avail = fread(buf->enc, 1, BUFFER_RAW_SIZE, config->fp)) > 0) { char *start = buf->enc; char *outbuf = buf->raw; size_t ototal = 0; // By popular demand, this utility tries to be bug-compatible // with GNU `base64'. That includes silently ignoring newlines // in the input. Tokenize the input on newline characters. while (avail > 0) { size_t outlen, len; // When stripping garbage or newlines in the input, // find the offset of the next garbage/newline // character, which is also the length of the next // chunk. Otherwise treat the entire input as a single // chunk. if (config->ignore_garbage) { len = find_garbage(start, avail); } else if (config->strip_newlines) { len = find_newline(start, avail); } else { len = avail; } // Ignore empty chunks. if (len == 0) { start++; avail--; continue; } // Decode the chunk into the raw buffer. if (base64_stream_decode(&state, start, len, outbuf, &outlen) == 0) { fprintf(stderr, "%s: %s: decoding error\n", config->name, config->file); return false; } // Update the output buffer pointer and total size. outbuf += outlen; ototal += outlen; // Bail out if the whole string has been consumed. if (len == avail) { break; } // Move the start pointer past the newline. start += len + 1; avail -= len + 1; } // Append the raw data to the output stream. if (write_stdout(config, buf->raw, ototal) == false) { return false; } } // Check for stream errors. if (ferror(config->fp)) { fprintf(stderr, "%s: %s: read error\n", config->name, config->file); return false; } return true; } static void usage (FILE *fp, const struct config *config) { const char *usage = "Usage: %s [OPTION]... [FILE]\n" "If no FILE is given or is specified as '-', " "read from standard input.\n" "Options:\n" " -d, --decode Decode a base64 stream.\n" " -h, --help Print this help text.\n" " -i, --ignore-garbage When decoding, ignore any " "non-base64 data.\n" " -n, --no-strip-newlines When decoding, do not strip " "newlines. Speeds up\n" " decoding of inputs that do not " "contain newlines.\n" " -w, --wrap=COLS Wrap encoded lines at this " "column. Default 76, 0 to\n" " disable.\n"; fprintf(fp, usage, config->name); } static bool get_wrap (struct config *config, const char *str) { char *eptr; // Reject empty strings. if (*str == '\0') { return false; } // Convert the input string to a signed long. const long wrap = strtol(str, &eptr, 10); // Reject negative numbers. if (wrap < 0) { return false; } // Reject strings containing non-digits. if (*eptr != '\0') { return false; } config->wrap = (size_t) wrap; return true; } static bool parse_opts (int argc, char **argv, struct config *config) { int c; static const struct option opts[] = { { "decode", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { "ignore-garbage", no_argument, NULL, 'i' }, { "no-strip-newlines", no_argument, NULL, 'n' }, { "wrap", required_argument, NULL, 'w' }, { NULL } }; // Remember the program's name. config->name = *argv; // Parse command line options. while ((c = getopt_long(argc, argv, ":dhinw:", opts, NULL)) != -1) { switch (c) { case 'd': config->decode = true; break; case 'h': config->print_help = true; return true; case 'i': config->ignore_garbage = true; break; case 'n': config->strip_newlines = false; break; case 'w': if (get_wrap(config, optarg) == false) { fprintf(stderr, "%s: invalid wrap value '%s'\n", config->name, optarg); return false; } break; case ':': fprintf(stderr, "%s: missing argument for '%c'\n", config->name, optopt); return false; default: fprintf(stderr, "%s: unknown option '%c'\n", config->name, optopt); return false; } } // Return successfully if no filename was given. if (optind >= argc) { return true; } // Return unsuccessfully if more than one filename was given. if (optind + 1 < argc) { fprintf(stderr, "%s: too many files\n", config->name); return false; } // For compatibility with GNU Coreutils base64, treat a filename of '-' // as standard input. if (strcmp(argv[optind], "-") == 0) { return true; } // Save the name of the file. config->file = argv[optind]; // Open the file. if ((config->fp = fopen(config->file, "rb")) == NULL) { fprintf(stderr, "%s: %s: %s\n", config->name, config->file, strerror(errno)); return false; } return true; } int main (int argc, char **argv) { // Default program config. struct config config = { .file = "stdin", .fp = stdin, .wrap = 76, .decode = false, .print_help = false, .strip_newlines = true, .ignore_garbage = false, }; struct buffer buf; // Parse options from the command line. if (parse_opts(argc, argv, &config) == false) { usage(stderr, &config); return 1; } // Return early if the user just wanted the help text. if (config.print_help) { usage(stdout, &config); return 0; } // Allocate buffers. if (buffer_alloc(&config, &buf) == false) { return 1; } #ifdef WIN // On Windows, ensure that stdout is binary-clean, and does not // silently convert newlines to CRLFs. This seems to be the portable // way to do it; freopen() and SetConsoleMode() occasionally result in // permission errors, whereas this always seems to work. _setmode(1, _O_BINARY); #endif // Encode or decode the input based on the user's choice. const bool ret = config.decode ? decode(&config, &buf) : encode(&config, &buf); // Free the buffers. buffer_free(&buf); // Close the input file. fclose(config.fp); // Close the output stream. fclose(stdout); // That's all, folks. return ret ? 0 : 1; } pybase64-1.4.3/base64/bin/base64.manifest000066400000000000000000000015661500645130400176320ustar00rootroot00000000000000 UTF-8 pybase64-1.4.3/base64/bin/base64.rc000066400000000000000000000001301500645130400164120ustar00rootroot00000000000000#include "winuser.h" CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "base64.manifest" pybase64-1.4.3/base64/cmake/000077500000000000000000000000001500645130400153165ustar00rootroot00000000000000pybase64-1.4.3/base64/cmake/Modules/000077500000000000000000000000001500645130400167265ustar00rootroot00000000000000pybase64-1.4.3/base64/cmake/Modules/TargetArch.cmake000066400000000000000000000022171500645130400217560ustar00rootroot00000000000000# Written in 2017 by Henrik Steffen Gaßmann henrik@gassmann.onl # # To the extent possible under law, the author(s) have dedicated all # copyright and related and neighboring rights to this software to the # public domain worldwide. This software is distributed without any warranty. # # You should have received a copy of the CC0 Public Domain Dedication # along with this software. If not, see # # http://creativecommons.org/publicdomain/zero/1.0/ # ######################################################################## set(TARGET_ARCHITECTURE_TEST_FILE "${CMAKE_CURRENT_LIST_DIR}/../test-arch.c") function(detect_target_architecture OUTPUT_VARIABLE) message(STATUS "${CMAKE_CURRENT_LIST_DIR}") try_compile(_IGNORED "${CMAKE_CURRENT_BINARY_DIR}" "${TARGET_ARCHITECTURE_TEST_FILE}" OUTPUT_VARIABLE _LOG ) string(REGEX MATCH "##arch=([^#]+)##" _IGNORED "${_LOG}") set(${OUTPUT_VARIABLE} "${CMAKE_MATCH_1}" PARENT_SCOPE) set("${OUTPUT_VARIABLE}_${CMAKE_MATCH_1}" 1 PARENT_SCOPE) if (CMAKE_MATCH_1 STREQUAL "unknown") message(WARNING "could not detect the target architecture.") endif() endfunction() pybase64-1.4.3/base64/cmake/Modules/TargetSIMDInstructionSet.cmake000066400000000000000000000026621500645130400245570ustar00rootroot00000000000000# Written in 2016-2017 by Henrik Steffen Gaßmann henrik@gassmann.onl # # To the extent possible under law, the author(s) have dedicated all # copyright and related and neighboring rights to this software to the # public domain worldwide. This software is distributed without any warranty. # # You should have received a copy of the CC0 Public Domain Dedication # along with this software. If not, see # # http://creativecommons.org/publicdomain/zero/1.0/ # ######################################################################## ######################################################################## # compiler flags definition macro(define_SIMD_compile_flags) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") # x86 set(COMPILE_FLAGS_SSSE3 "-mssse3") set(COMPILE_FLAGS_SSE41 "-msse4.1") set(COMPILE_FLAGS_SSE42 "-msse4.2") set(COMPILE_FLAGS_AVX "-mavx") set(COMPILE_FLAGS_AVX2 "-mavx2") set(COMPILE_FLAGS_AVX512 "-mavx512vl -mavx512vbmi") #arm set(COMPILE_FLAGS_NEON32 "-mfpu=neon") elseif(MSVC) set(COMPILE_FLAGS_SSSE3 " ") set(COMPILE_FLAGS_SSE41 " ") set(COMPILE_FLAGS_SSE42 " ") set(COMPILE_FLAGS_AVX "/arch:AVX") set(COMPILE_FLAGS_AVX2 "/arch:AVX2") set(COMPILE_FLAGS_AVX512 "/arch:AVX512") endif() endmacro(define_SIMD_compile_flags) pybase64-1.4.3/base64/cmake/base64-config.cmake.in000066400000000000000000000001551500645130400212550ustar00rootroot00000000000000@PACKAGE_INIT@ include("${CMAKE_CURRENT_LIST_DIR}/base64-targets.cmake") check_required_components(base64) pybase64-1.4.3/base64/cmake/config.h.in000066400000000000000000000012031500645130400173350ustar00rootroot00000000000000#ifndef BASE64_CONFIG_H #define BASE64_CONFIG_H #cmakedefine01 BASE64_WITH_SSSE3 #define HAVE_SSSE3 BASE64_WITH_SSSE3 #cmakedefine01 BASE64_WITH_SSE41 #define HAVE_SSE41 BASE64_WITH_SSE41 #cmakedefine01 BASE64_WITH_SSE42 #define HAVE_SSE42 BASE64_WITH_SSE42 #cmakedefine01 BASE64_WITH_AVX #define HAVE_AVX BASE64_WITH_AVX #cmakedefine01 BASE64_WITH_AVX2 #define HAVE_AVX2 BASE64_WITH_AVX2 #cmakedefine01 BASE64_WITH_AVX512 #define HAVE_AVX512 BASE64_WITH_AVX512 #cmakedefine01 BASE64_WITH_NEON32 #define HAVE_NEON32 BASE64_WITH_NEON32 #cmakedefine01 BASE64_WITH_NEON64 #define HAVE_NEON64 BASE64_WITH_NEON64 #endif // BASE64_CONFIG_H pybase64-1.4.3/base64/cmake/test-arch.c000066400000000000000000000016421500645130400173570ustar00rootroot00000000000000// Written in 2017 by Henrik Steffen Gaßmann henrik@gassmann.onl // // To the extent possible under law, the author(s) have dedicated all // copyright and related and neighboring rights to this software to the // public domain worldwide. This software is distributed without any warranty. // // You should have received a copy of the CC0 Public Domain Dedication // along with this software. If not, see // // http://creativecommons.org/publicdomain/zero/1.0/ // //////////////////////////////////////////////////////////////////////////////// // ARM 64-Bit #if defined(__aarch64__) \ || defined(_M_ARM64) #error ##arch=arm64## // ARM 32-Bit #elif defined(__arm__) \ || defined(_M_ARM) #error ##arch=arm## // x86 64-Bit #elif defined(__x86_64__) \ || defined(_M_X64) #error ##arch=x64## // x86 32-Bit #elif defined(__i386__) \ || defined(_M_IX86) #error ##arch=x86## #else #error ##arch=unknown## #endif pybase64-1.4.3/base64/include/000077500000000000000000000000001500645130400156615ustar00rootroot00000000000000pybase64-1.4.3/base64/include/libbase64.h000066400000000000000000000112651500645130400176120ustar00rootroot00000000000000#ifndef LIBBASE64_H #define LIBBASE64_H #include /* size_t */ #if defined(_WIN32) || defined(__CYGWIN__) #define BASE64_SYMBOL_IMPORT __declspec(dllimport) #define BASE64_SYMBOL_EXPORT __declspec(dllexport) #define BASE64_SYMBOL_PRIVATE #elif __GNUC__ >= 4 #define BASE64_SYMBOL_IMPORT __attribute__ ((visibility ("default"))) #define BASE64_SYMBOL_EXPORT __attribute__ ((visibility ("default"))) #define BASE64_SYMBOL_PRIVATE __attribute__ ((visibility ("hidden"))) #else #define BASE64_SYMBOL_IMPORT #define BASE64_SYMBOL_EXPORT #define BASE64_SYMBOL_PRIVATE #endif #if defined(BASE64_STATIC_DEFINE) #define BASE64_EXPORT #define BASE64_NO_EXPORT #else #if defined(BASE64_EXPORTS) // defined if we are building the shared library #define BASE64_EXPORT BASE64_SYMBOL_EXPORT #else #define BASE64_EXPORT BASE64_SYMBOL_IMPORT #endif #define BASE64_NO_EXPORT BASE64_SYMBOL_PRIVATE #endif #ifdef __cplusplus extern "C" { #endif /* These are the flags that can be passed in the `flags` argument. The values * below force the use of a given codec, even if that codec is a no-op in the * current build. Used in testing. Set to 0 for the default behavior, which is * runtime feature detection on x86, a compile-time fixed codec on ARM, and * the plain codec on other platforms: */ #define BASE64_FORCE_AVX2 (1 << 0) #define BASE64_FORCE_NEON32 (1 << 1) #define BASE64_FORCE_NEON64 (1 << 2) #define BASE64_FORCE_PLAIN (1 << 3) #define BASE64_FORCE_SSSE3 (1 << 4) #define BASE64_FORCE_SSE41 (1 << 5) #define BASE64_FORCE_SSE42 (1 << 6) #define BASE64_FORCE_AVX (1 << 7) #define BASE64_FORCE_AVX512 (1 << 8) struct base64_state { int eof; int bytes; int flags; unsigned char carry; }; /* Wrapper function to encode a plain string of given length. Output is written * to *out without trailing zero. Output length in bytes is written to *outlen. * The buffer in `out` has been allocated by the caller and is at least 4/3 the * size of the input. See above for `flags`; set to 0 for default operation: */ void BASE64_EXPORT base64_encode ( const char *src , size_t srclen , char *out , size_t *outlen , int flags ) ; /* Call this before calling base64_stream_encode() to init the state. See above * for `flags`; set to 0 for default operation: */ void BASE64_EXPORT base64_stream_encode_init ( struct base64_state *state , int flags ) ; /* Encodes the block of data of given length at `src`, into the buffer at * `out`. Caller is responsible for allocating a large enough out-buffer; it * must be at least 4/3 the size of the in-buffer, but take some margin. Places * the number of new bytes written into `outlen` (which is set to zero when the * function starts). Does not zero-terminate or finalize the output. */ void BASE64_EXPORT base64_stream_encode ( struct base64_state *state , const char *src , size_t srclen , char *out , size_t *outlen ) ; /* Finalizes the output begun by previous calls to `base64_stream_encode()`. * Adds the required end-of-stream markers if appropriate. `outlen` is modified * and will contain the number of new bytes written at `out` (which will quite * often be zero). */ void BASE64_EXPORT base64_stream_encode_final ( struct base64_state *state , char *out , size_t *outlen ) ; /* Wrapper function to decode a plain string of given length. Output is written * to *out without trailing zero. Output length in bytes is written to *outlen. * The buffer in `out` has been allocated by the caller and is at least 3/4 the * size of the input. See above for `flags`, set to 0 for default operation: */ int BASE64_EXPORT base64_decode ( const char *src , size_t srclen , char *out , size_t *outlen , int flags ) ; /* Call this before calling base64_stream_decode() to init the state. See above * for `flags`; set to 0 for default operation: */ void BASE64_EXPORT base64_stream_decode_init ( struct base64_state *state , int flags ) ; /* Decodes the block of data of given length at `src`, into the buffer at * `out`. Caller is responsible for allocating a large enough out-buffer; it * must be at least 3/4 the size of the in-buffer, but take some margin. Places * the number of new bytes written into `outlen` (which is set to zero when the * function starts). Does not zero-terminate the output. Returns 1 if all is * well, and 0 if a decoding error was found, such as an invalid character. * Returns -1 if the chosen codec is not included in the current build. Used by * the test harness to check whether a codec is available for testing. */ int BASE64_EXPORT base64_stream_decode ( struct base64_state *state , const char *src , size_t srclen , char *out , size_t *outlen ) ; #ifdef __cplusplus } #endif #endif /* LIBBASE64_H */ pybase64-1.4.3/base64/lib/000077500000000000000000000000001500645130400150045ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/000077500000000000000000000000001500645130400157215ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/avx/000077500000000000000000000000001500645130400165175ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/avx/codec.c000066400000000000000000000027401500645130400177430ustar00rootroot00000000000000#include #include #include #include "../../../include/libbase64.h" #include "../../tables/tables.h" #include "../../codecs.h" #include "config.h" #include "../../env.h" #if HAVE_AVX #include // Only enable inline assembly on supported compilers and on 64-bit CPUs. #ifndef BASE64_AVX_USE_ASM # if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64 # define BASE64_AVX_USE_ASM 1 # else # define BASE64_AVX_USE_ASM 0 # endif #endif #include "../ssse3/dec_reshuffle.c" #include "../ssse3/dec_loop.c" #if BASE64_AVX_USE_ASM # include "enc_loop_asm.c" #else # include "../ssse3/enc_translate.c" # include "../ssse3/enc_reshuffle.c" # include "../ssse3/enc_loop.c" #endif #endif // HAVE_AVX void base64_stream_encode_avx BASE64_ENC_PARAMS { #if HAVE_AVX #include "../generic/enc_head.c" // For supported compilers, use a hand-optimized inline assembly // encoder. Otherwise fall back on the SSSE3 encoder, but compiled with // AVX flags to generate better optimized AVX code. #if BASE64_AVX_USE_ASM enc_loop_avx(&s, &slen, &o, &olen); #else enc_loop_ssse3(&s, &slen, &o, &olen); #endif #include "../generic/enc_tail.c" #else base64_enc_stub(state, src, srclen, out, outlen); #endif } int base64_stream_decode_avx BASE64_DEC_PARAMS { #if HAVE_AVX #include "../generic/dec_head.c" dec_loop_ssse3(&s, &slen, &o, &olen); #include "../generic/dec_tail.c" #else return base64_dec_stub(state, src, srclen, out, outlen); #endif } pybase64-1.4.3/base64/lib/arch/avx/enc_loop_asm.c000066400000000000000000000221421500645130400213220ustar00rootroot00000000000000// Apologies in advance for combining the preprocessor with inline assembly, // two notoriously gnarly parts of C, but it was necessary to avoid a lot of // code repetition. The preprocessor is used to template large sections of // inline assembly that differ only in the registers used. If the code was // written out by hand, it would become very large and hard to audit. // Generate a block of inline assembly that loads register R0 from memory. The // offset at which the register is loaded is set by the given round. #define LOAD(R0, ROUND) \ "vlddqu ("#ROUND" * 12)(%[src]), %["R0"] \n\t" // Generate a block of inline assembly that deinterleaves and shuffles register // R0 using preloaded constants. Outputs in R0 and R1. #define SHUF(R0, R1, R2) \ "vpshufb %[lut0], %["R0"], %["R1"] \n\t" \ "vpand %["R1"], %[msk0], %["R2"] \n\t" \ "vpand %["R1"], %[msk2], %["R1"] \n\t" \ "vpmulhuw %["R2"], %[msk1], %["R2"] \n\t" \ "vpmullw %["R1"], %[msk3], %["R1"] \n\t" \ "vpor %["R1"], %["R2"], %["R1"] \n\t" // Generate a block of inline assembly that takes R0 and R1 and translates // their contents to the base64 alphabet, using preloaded constants. #define TRAN(R0, R1, R2) \ "vpsubusb %[n51], %["R1"], %["R0"] \n\t" \ "vpcmpgtb %[n25], %["R1"], %["R2"] \n\t" \ "vpsubb %["R2"], %["R0"], %["R0"] \n\t" \ "vpshufb %["R0"], %[lut1], %["R2"] \n\t" \ "vpaddb %["R1"], %["R2"], %["R0"] \n\t" // Generate a block of inline assembly that stores the given register R0 at an // offset set by the given round. #define STOR(R0, ROUND) \ "vmovdqu %["R0"], ("#ROUND" * 16)(%[dst]) \n\t" // Generate a block of inline assembly that generates a single self-contained // encoder round: fetch the data, process it, and store the result. Then update // the source and destination pointers. #define ROUND() \ LOAD("a", 0) \ SHUF("a", "b", "c") \ TRAN("a", "b", "c") \ STOR("a", 0) \ "add $12, %[src] \n\t" \ "add $16, %[dst] \n\t" // Define a macro that initiates a three-way interleaved encoding round by // preloading registers a, b and c from memory. // The register graph shows which registers are in use during each step, and // is a visual aid for choosing registers for that step. Symbol index: // // + indicates that a register is loaded by that step. // | indicates that a register is in use and must not be touched. // - indicates that a register is decommissioned by that step. // x indicates that a register is used as a temporary by that step. // V indicates that a register is an input or output to the macro. // #define ROUND_3_INIT() /* a b c d e f */ \ LOAD("a", 0) /* + */ \ SHUF("a", "d", "e") /* | + x */ \ LOAD("b", 1) /* | + | */ \ TRAN("a", "d", "e") /* | | - x */ \ LOAD("c", 2) /* V V V */ // Define a macro that translates, shuffles and stores the input registers A, B // and C, and preloads registers D, E and F for the next round. // This macro can be arbitrarily daisy-chained by feeding output registers D, E // and F back into the next round as input registers A, B and C. The macro // carefully interleaves memory operations with data operations for optimal // pipelined performance. #define ROUND_3(ROUND, A,B,C,D,E,F) /* A B C D E F */ \ LOAD(D, (ROUND + 3)) /* V V V + */ \ SHUF(B, E, F) /* | | | | + x */ \ STOR(A, (ROUND + 0)) /* - | | | | */ \ TRAN(B, E, F) /* | | | - x */ \ LOAD(E, (ROUND + 4)) /* | | | + */ \ SHUF(C, A, F) /* + | | | | x */ \ STOR(B, (ROUND + 1)) /* | - | | | */ \ TRAN(C, A, F) /* - | | | x */ \ LOAD(F, (ROUND + 5)) /* | | | + */ \ SHUF(D, A, B) /* + x | | | | */ \ STOR(C, (ROUND + 2)) /* | - | | | */ \ TRAN(D, A, B) /* - x V V V */ // Define a macro that terminates a ROUND_3 macro by taking pre-loaded // registers D, E and F, and translating, shuffling and storing them. #define ROUND_3_END(ROUND, A,B,C,D,E,F) /* A B C D E F */ \ SHUF(E, A, B) /* + x V V V */ \ STOR(D, (ROUND + 3)) /* | - | | */ \ TRAN(E, A, B) /* - x | | */ \ SHUF(F, C, D) /* + x | | */ \ STOR(E, (ROUND + 4)) /* | - | */ \ TRAN(F, C, D) /* - x | */ \ STOR(F, (ROUND + 5)) /* - */ // Define a type A round. Inputs are a, b, and c, outputs are d, e, and f. #define ROUND_3_A(ROUND) \ ROUND_3(ROUND, "a", "b", "c", "d", "e", "f") // Define a type B round. Inputs and outputs are swapped with regard to type A. #define ROUND_3_B(ROUND) \ ROUND_3(ROUND, "d", "e", "f", "a", "b", "c") // Terminating macro for a type A round. #define ROUND_3_A_LAST(ROUND) \ ROUND_3_A(ROUND) \ ROUND_3_END(ROUND, "a", "b", "c", "d", "e", "f") // Terminating macro for a type B round. #define ROUND_3_B_LAST(ROUND) \ ROUND_3_B(ROUND) \ ROUND_3_END(ROUND, "d", "e", "f", "a", "b", "c") // Suppress clang's warning that the literal string in the asm statement is // overlong (longer than the ISO-mandated minimum size of 4095 bytes for C99 // compilers). It may be true, but the goal here is not C99 portability. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverlength-strings" static inline void enc_loop_avx (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { // For a clearer explanation of the algorithm used by this function, // please refer to the plain (not inline assembly) implementation. This // function follows the same basic logic. if (*slen < 16) { return; } // Process blocks of 12 bytes at a time. Input is read in blocks of 16 // bytes, so "reserve" four bytes from the input buffer to ensure that // we never read beyond the end of the input buffer. size_t rounds = (*slen - 4) / 12; *slen -= rounds * 12; // 12 bytes consumed per round *olen += rounds * 16; // 16 bytes produced per round // Number of times to go through the 36x loop. size_t loops = rounds / 36; // Number of rounds remaining after the 36x loop. rounds %= 36; // Lookup tables. const __m128i lut0 = _mm_set_epi8( 10, 11, 9, 10, 7, 8, 6, 7, 4, 5, 3, 4, 1, 2, 0, 1); const __m128i lut1 = _mm_setr_epi8( 65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0); // Temporary registers. __m128i a, b, c, d, e, f; __asm__ volatile ( // If there are 36 rounds or more, enter a 36x unrolled loop of // interleaved encoding rounds. The rounds interleave memory // operations (load/store) with data operations (table lookups, // etc) to maximize pipeline throughput. " test %[loops], %[loops] \n\t" " jz 18f \n\t" " jmp 36f \n\t" " \n\t" ".balign 64 \n\t" "36: " ROUND_3_INIT() " " ROUND_3_A( 0) " " ROUND_3_B( 3) " " ROUND_3_A( 6) " " ROUND_3_B( 9) " " ROUND_3_A(12) " " ROUND_3_B(15) " " ROUND_3_A(18) " " ROUND_3_B(21) " " ROUND_3_A(24) " " ROUND_3_B(27) " " ROUND_3_A_LAST(30) " add $(12 * 36), %[src] \n\t" " add $(16 * 36), %[dst] \n\t" " dec %[loops] \n\t" " jnz 36b \n\t" // Enter an 18x unrolled loop for rounds of 18 or more. "18: cmp $18, %[rounds] \n\t" " jl 9f \n\t" " " ROUND_3_INIT() " " ROUND_3_A(0) " " ROUND_3_B(3) " " ROUND_3_A(6) " " ROUND_3_B(9) " " ROUND_3_A_LAST(12) " sub $18, %[rounds] \n\t" " add $(12 * 18), %[src] \n\t" " add $(16 * 18), %[dst] \n\t" // Enter a 9x unrolled loop for rounds of 9 or more. "9: cmp $9, %[rounds] \n\t" " jl 6f \n\t" " " ROUND_3_INIT() " " ROUND_3_A(0) " " ROUND_3_B_LAST(3) " sub $9, %[rounds] \n\t" " add $(12 * 9), %[src] \n\t" " add $(16 * 9), %[dst] \n\t" // Enter a 6x unrolled loop for rounds of 6 or more. "6: cmp $6, %[rounds] \n\t" " jl 55f \n\t" " " ROUND_3_INIT() " " ROUND_3_A_LAST(0) " sub $6, %[rounds] \n\t" " add $(12 * 6), %[src] \n\t" " add $(16 * 6), %[dst] \n\t" // Dispatch the remaining rounds 0..5. "55: cmp $3, %[rounds] \n\t" " jg 45f \n\t" " je 3f \n\t" " cmp $1, %[rounds] \n\t" " jg 2f \n\t" " je 1f \n\t" " jmp 0f \n\t" "45: cmp $4, %[rounds] \n\t" " je 4f \n\t" // Block of non-interlaced encoding rounds, which can each // individually be jumped to. Rounds fall through to the next. "5: " ROUND() "4: " ROUND() "3: " ROUND() "2: " ROUND() "1: " ROUND() "0: \n\t" // Outputs (modified). : [rounds] "+r" (rounds), [loops] "+r" (loops), [src] "+r" (*s), [dst] "+r" (*o), [a] "=&x" (a), [b] "=&x" (b), [c] "=&x" (c), [d] "=&x" (d), [e] "=&x" (e), [f] "=&x" (f) // Inputs (not modified). : [lut0] "x" (lut0), [lut1] "x" (lut1), [msk0] "x" (_mm_set1_epi32(0x0FC0FC00)), [msk1] "x" (_mm_set1_epi32(0x04000040)), [msk2] "x" (_mm_set1_epi32(0x003F03F0)), [msk3] "x" (_mm_set1_epi32(0x01000010)), [n51] "x" (_mm_set1_epi8(51)), [n25] "x" (_mm_set1_epi8(25)) // Clobbers. : "cc", "memory" ); } #pragma GCC diagnostic pop pybase64-1.4.3/base64/lib/arch/avx2/000077500000000000000000000000001500645130400166015ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/avx2/codec.c000066400000000000000000000022571500645130400200300ustar00rootroot00000000000000#include #include #include #include "../../../include/libbase64.h" #include "../../tables/tables.h" #include "../../codecs.h" #include "config.h" #include "../../env.h" #if HAVE_AVX2 #include // Only enable inline assembly on supported compilers and on 64-bit CPUs. #ifndef BASE64_AVX2_USE_ASM # if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64 # define BASE64_AVX2_USE_ASM 1 # else # define BASE64_AVX2_USE_ASM 0 # endif #endif #include "dec_reshuffle.c" #include "dec_loop.c" #if BASE64_AVX2_USE_ASM # include "enc_loop_asm.c" #else # include "enc_translate.c" # include "enc_reshuffle.c" # include "enc_loop.c" #endif #endif // HAVE_AVX2 void base64_stream_encode_avx2 BASE64_ENC_PARAMS { #if HAVE_AVX2 #include "../generic/enc_head.c" enc_loop_avx2(&s, &slen, &o, &olen); #include "../generic/enc_tail.c" #else base64_enc_stub(state, src, srclen, out, outlen); #endif } int base64_stream_decode_avx2 BASE64_DEC_PARAMS { #if HAVE_AVX2 #include "../generic/dec_head.c" dec_loop_avx2(&s, &slen, &o, &olen); #include "../generic/dec_tail.c" #else return base64_dec_stub(state, src, srclen, out, outlen); #endif } pybase64-1.4.3/base64/lib/arch/avx2/dec_loop.c000066400000000000000000000062351500645130400205370ustar00rootroot00000000000000static BASE64_FORCE_INLINE int dec_loop_avx2_inner (const uint8_t **s, uint8_t **o, size_t *rounds) { const __m256i lut_lo = _mm256_setr_epi8( 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x1A, 0x1B, 0x1B, 0x1B, 0x1A, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x1A, 0x1B, 0x1B, 0x1B, 0x1A); const __m256i lut_hi = _mm256_setr_epi8( 0x10, 0x10, 0x01, 0x02, 0x04, 0x08, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01, 0x02, 0x04, 0x08, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10); const __m256i lut_roll = _mm256_setr_epi8( 0, 16, 19, 4, -65, -65, -71, -71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 19, 4, -65, -65, -71, -71, 0, 0, 0, 0, 0, 0, 0, 0); const __m256i mask_2F = _mm256_set1_epi8(0x2F); // Load input: __m256i str = _mm256_loadu_si256((__m256i *) *s); // See the SSSE3 decoder for an explanation of the algorithm. const __m256i hi_nibbles = _mm256_and_si256(_mm256_srli_epi32(str, 4), mask_2F); const __m256i lo_nibbles = _mm256_and_si256(str, mask_2F); const __m256i hi = _mm256_shuffle_epi8(lut_hi, hi_nibbles); const __m256i lo = _mm256_shuffle_epi8(lut_lo, lo_nibbles); if (!_mm256_testz_si256(lo, hi)) { return 0; } const __m256i eq_2F = _mm256_cmpeq_epi8(str, mask_2F); const __m256i roll = _mm256_shuffle_epi8(lut_roll, _mm256_add_epi8(eq_2F, hi_nibbles)); // Now simply add the delta values to the input: str = _mm256_add_epi8(str, roll); // Reshuffle the input to packed 12-byte output format: str = dec_reshuffle(str); // Store the output: _mm256_storeu_si256((__m256i *) *o, str); *s += 32; *o += 24; *rounds -= 1; return 1; } static inline void dec_loop_avx2 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 45) { return; } // Process blocks of 32 bytes per round. Because 8 extra zero bytes are // written after the output, ensure that there will be at least 13 // bytes of input data left to cover the gap. (11 data bytes and up to // two end-of-string markers.) size_t rounds = (*slen - 13) / 32; *slen -= rounds * 32; // 32 bytes consumed per round *olen += rounds * 24; // 24 bytes produced per round do { if (rounds >= 8) { if (dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds)) { continue; } break; } if (rounds >= 4) { if (dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds)) { continue; } break; } if (rounds >= 2) { if (dec_loop_avx2_inner(s, o, &rounds) && dec_loop_avx2_inner(s, o, &rounds)) { continue; } break; } dec_loop_avx2_inner(s, o, &rounds); break; } while (rounds > 0); // Adjust for any rounds that were skipped: *slen += rounds * 32; *olen -= rounds * 24; } pybase64-1.4.3/base64/lib/arch/avx2/dec_reshuffle.c000066400000000000000000000024301500645130400215420ustar00rootroot00000000000000static BASE64_FORCE_INLINE __m256i dec_reshuffle (const __m256i in) { // in, lower lane, bits, upper case are most significant bits, lower // case are least significant bits: // 00llllll 00kkkkLL 00jjKKKK 00JJJJJJ // 00iiiiii 00hhhhII 00ggHHHH 00GGGGGG // 00ffffff 00eeeeFF 00ddEEEE 00DDDDDD // 00cccccc 00bbbbCC 00aaBBBB 00AAAAAA const __m256i merge_ab_and_bc = _mm256_maddubs_epi16(in, _mm256_set1_epi32(0x01400140)); // 0000kkkk LLllllll 0000JJJJ JJjjKKKK // 0000hhhh IIiiiiii 0000GGGG GGggHHHH // 0000eeee FFffffff 0000DDDD DDddEEEE // 0000bbbb CCcccccc 0000AAAA AAaaBBBB __m256i out = _mm256_madd_epi16(merge_ab_and_bc, _mm256_set1_epi32(0x00011000)); // 00000000 JJJJJJjj KKKKkkkk LLllllll // 00000000 GGGGGGgg HHHHhhhh IIiiiiii // 00000000 DDDDDDdd EEEEeeee FFffffff // 00000000 AAAAAAaa BBBBbbbb CCcccccc // Pack bytes together in each lane: out = _mm256_shuffle_epi8(out, _mm256_setr_epi8( 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1, 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1)); // 00000000 00000000 00000000 00000000 // LLllllll KKKKkkkk JJJJJJjj IIiiiiii // HHHHhhhh GGGGGGgg FFffffff EEEEeeee // DDDDDDdd CCcccccc BBBBbbbb AAAAAAaa // Pack lanes: return _mm256_permutevar8x32_epi32(out, _mm256_setr_epi32(0, 1, 2, 4, 5, 6, -1, -1)); } pybase64-1.4.3/base64/lib/arch/avx2/enc_loop.c000066400000000000000000000043651500645130400205530ustar00rootroot00000000000000static BASE64_FORCE_INLINE void enc_loop_avx2_inner_first (const uint8_t **s, uint8_t **o) { // First load is done at s - 0 to not get a segfault: __m256i src = _mm256_loadu_si256((__m256i *) *s); // Shift by 4 bytes, as required by enc_reshuffle: src = _mm256_permutevar8x32_epi32(src, _mm256_setr_epi32(0, 0, 1, 2, 3, 4, 5, 6)); // Reshuffle, translate, store: src = enc_reshuffle(src); src = enc_translate(src); _mm256_storeu_si256((__m256i *) *o, src); // Subsequent loads will be done at s - 4, set pointer for next round: *s += 20; *o += 32; } static BASE64_FORCE_INLINE void enc_loop_avx2_inner (const uint8_t **s, uint8_t **o) { // Load input: __m256i src = _mm256_loadu_si256((__m256i *) *s); // Reshuffle, translate, store: src = enc_reshuffle(src); src = enc_translate(src); _mm256_storeu_si256((__m256i *) *o, src); *s += 24; *o += 32; } static inline void enc_loop_avx2 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 32) { return; } // Process blocks of 24 bytes at a time. Because blocks are loaded 32 // bytes at a time an offset of -4, ensure that there will be at least // 4 remaining bytes after the last round, so that the final read will // not pass beyond the bounds of the input buffer: size_t rounds = (*slen - 4) / 24; *slen -= rounds * 24; // 24 bytes consumed per round *olen += rounds * 32; // 32 bytes produced per round // The first loop iteration requires special handling to ensure that // the read, which is done at an offset, does not underflow the buffer: enc_loop_avx2_inner_first(s, o); rounds--; while (rounds > 0) { if (rounds >= 8) { enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); rounds -= 8; continue; } if (rounds >= 4) { enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); rounds -= 4; continue; } if (rounds >= 2) { enc_loop_avx2_inner(s, o); enc_loop_avx2_inner(s, o); rounds -= 2; continue; } enc_loop_avx2_inner(s, o); break; } // Add the offset back: *s += 4; } pybase64-1.4.3/base64/lib/arch/avx2/enc_loop_asm.c000066400000000000000000000243251500645130400214110ustar00rootroot00000000000000// Apologies in advance for combining the preprocessor with inline assembly, // two notoriously gnarly parts of C, but it was necessary to avoid a lot of // code repetition. The preprocessor is used to template large sections of // inline assembly that differ only in the registers used. If the code was // written out by hand, it would become very large and hard to audit. // Generate a block of inline assembly that loads register R0 from memory. The // offset at which the register is loaded is set by the given round and a // constant offset. #define LOAD(R0, ROUND, OFFSET) \ "vlddqu ("#ROUND" * 24 + "#OFFSET")(%[src]), %["R0"] \n\t" // Generate a block of inline assembly that deinterleaves and shuffles register // R0 using preloaded constants. Outputs in R0 and R1. #define SHUF(R0, R1, R2) \ "vpshufb %[lut0], %["R0"], %["R1"] \n\t" \ "vpand %["R1"], %[msk0], %["R2"] \n\t" \ "vpand %["R1"], %[msk2], %["R1"] \n\t" \ "vpmulhuw %["R2"], %[msk1], %["R2"] \n\t" \ "vpmullw %["R1"], %[msk3], %["R1"] \n\t" \ "vpor %["R1"], %["R2"], %["R1"] \n\t" // Generate a block of inline assembly that takes R0 and R1 and translates // their contents to the base64 alphabet, using preloaded constants. #define TRAN(R0, R1, R2) \ "vpsubusb %[n51], %["R1"], %["R0"] \n\t" \ "vpcmpgtb %[n25], %["R1"], %["R2"] \n\t" \ "vpsubb %["R2"], %["R0"], %["R0"] \n\t" \ "vpshufb %["R0"], %[lut1], %["R2"] \n\t" \ "vpaddb %["R1"], %["R2"], %["R0"] \n\t" // Generate a block of inline assembly that stores the given register R0 at an // offset set by the given round. #define STOR(R0, ROUND) \ "vmovdqu %["R0"], ("#ROUND" * 32)(%[dst]) \n\t" // Generate a block of inline assembly that generates a single self-contained // encoder round: fetch the data, process it, and store the result. Then update // the source and destination pointers. #define ROUND() \ LOAD("a", 0, -4) \ SHUF("a", "b", "c") \ TRAN("a", "b", "c") \ STOR("a", 0) \ "add $24, %[src] \n\t" \ "add $32, %[dst] \n\t" // Define a macro that initiates a three-way interleaved encoding round by // preloading registers a, b and c from memory. // The register graph shows which registers are in use during each step, and // is a visual aid for choosing registers for that step. Symbol index: // // + indicates that a register is loaded by that step. // | indicates that a register is in use and must not be touched. // - indicates that a register is decommissioned by that step. // x indicates that a register is used as a temporary by that step. // V indicates that a register is an input or output to the macro. // #define ROUND_3_INIT() /* a b c d e f */ \ LOAD("a", 0, -4) /* + */ \ SHUF("a", "d", "e") /* | + x */ \ LOAD("b", 1, -4) /* | + | */ \ TRAN("a", "d", "e") /* | | - x */ \ LOAD("c", 2, -4) /* V V V */ // Define a macro that translates, shuffles and stores the input registers A, B // and C, and preloads registers D, E and F for the next round. // This macro can be arbitrarily daisy-chained by feeding output registers D, E // and F back into the next round as input registers A, B and C. The macro // carefully interleaves memory operations with data operations for optimal // pipelined performance. #define ROUND_3(ROUND, A,B,C,D,E,F) /* A B C D E F */ \ LOAD(D, (ROUND + 3), -4) /* V V V + */ \ SHUF(B, E, F) /* | | | | + x */ \ STOR(A, (ROUND + 0)) /* - | | | | */ \ TRAN(B, E, F) /* | | | - x */ \ LOAD(E, (ROUND + 4), -4) /* | | | + */ \ SHUF(C, A, F) /* + | | | | x */ \ STOR(B, (ROUND + 1)) /* | - | | | */ \ TRAN(C, A, F) /* - | | | x */ \ LOAD(F, (ROUND + 5), -4) /* | | | + */ \ SHUF(D, A, B) /* + x | | | | */ \ STOR(C, (ROUND + 2)) /* | - | | | */ \ TRAN(D, A, B) /* - x V V V */ // Define a macro that terminates a ROUND_3 macro by taking pre-loaded // registers D, E and F, and translating, shuffling and storing them. #define ROUND_3_END(ROUND, A,B,C,D,E,F) /* A B C D E F */ \ SHUF(E, A, B) /* + x V V V */ \ STOR(D, (ROUND + 3)) /* | - | | */ \ TRAN(E, A, B) /* - x | | */ \ SHUF(F, C, D) /* + x | | */ \ STOR(E, (ROUND + 4)) /* | - | */ \ TRAN(F, C, D) /* - x | */ \ STOR(F, (ROUND + 5)) /* - */ // Define a type A round. Inputs are a, b, and c, outputs are d, e, and f. #define ROUND_3_A(ROUND) \ ROUND_3(ROUND, "a", "b", "c", "d", "e", "f") // Define a type B round. Inputs and outputs are swapped with regard to type A. #define ROUND_3_B(ROUND) \ ROUND_3(ROUND, "d", "e", "f", "a", "b", "c") // Terminating macro for a type A round. #define ROUND_3_A_LAST(ROUND) \ ROUND_3_A(ROUND) \ ROUND_3_END(ROUND, "a", "b", "c", "d", "e", "f") // Terminating macro for a type B round. #define ROUND_3_B_LAST(ROUND) \ ROUND_3_B(ROUND) \ ROUND_3_END(ROUND, "d", "e", "f", "a", "b", "c") // Suppress clang's warning that the literal string in the asm statement is // overlong (longer than the ISO-mandated minimum size of 4095 bytes for C99 // compilers). It may be true, but the goal here is not C99 portability. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverlength-strings" static inline void enc_loop_avx2 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { // For a clearer explanation of the algorithm used by this function, // please refer to the plain (not inline assembly) implementation. This // function follows the same basic logic. if (*slen < 32) { return; } // Process blocks of 24 bytes at a time. Because blocks are loaded 32 // bytes at a time an offset of -4, ensure that there will be at least // 4 remaining bytes after the last round, so that the final read will // not pass beyond the bounds of the input buffer. size_t rounds = (*slen - 4) / 24; *slen -= rounds * 24; // 24 bytes consumed per round *olen += rounds * 32; // 32 bytes produced per round // Pre-decrement the number of rounds to get the number of rounds // *after* the first round, which is handled as a special case. rounds--; // Number of times to go through the 36x loop. size_t loops = rounds / 36; // Number of rounds remaining after the 36x loop. rounds %= 36; // Lookup tables. const __m256i lut0 = _mm256_set_epi8( 10, 11, 9, 10, 7, 8, 6, 7, 4, 5, 3, 4, 1, 2, 0, 1, 14, 15, 13, 14, 11, 12, 10, 11, 8, 9, 7, 8, 5, 6, 4, 5); const __m256i lut1 = _mm256_setr_epi8( 65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0, 65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0); // Temporary registers. __m256i a, b, c, d, e; // Temporary register f doubles as the shift mask for the first round. __m256i f = _mm256_setr_epi32(0, 0, 1, 2, 3, 4, 5, 6); __asm__ volatile ( // The first loop iteration requires special handling to ensure // that the read, which is normally done at an offset of -4, // does not underflow the buffer. Load the buffer at an offset // of 0 and permute the input to achieve the same effect. LOAD("a", 0, 0) "vpermd %[a], %[f], %[a] \n\t" // Perform the standard shuffling and translation steps. SHUF("a", "b", "c") TRAN("a", "b", "c") // Store the result and increment the source and dest pointers. "vmovdqu %[a], (%[dst]) \n\t" "add $24, %[src] \n\t" "add $32, %[dst] \n\t" // If there are 36 rounds or more, enter a 36x unrolled loop of // interleaved encoding rounds. The rounds interleave memory // operations (load/store) with data operations (table lookups, // etc) to maximize pipeline throughput. " test %[loops], %[loops] \n\t" " jz 18f \n\t" " jmp 36f \n\t" " \n\t" ".balign 64 \n\t" "36: " ROUND_3_INIT() " " ROUND_3_A( 0) " " ROUND_3_B( 3) " " ROUND_3_A( 6) " " ROUND_3_B( 9) " " ROUND_3_A(12) " " ROUND_3_B(15) " " ROUND_3_A(18) " " ROUND_3_B(21) " " ROUND_3_A(24) " " ROUND_3_B(27) " " ROUND_3_A_LAST(30) " add $(24 * 36), %[src] \n\t" " add $(32 * 36), %[dst] \n\t" " dec %[loops] \n\t" " jnz 36b \n\t" // Enter an 18x unrolled loop for rounds of 18 or more. "18: cmp $18, %[rounds] \n\t" " jl 9f \n\t" " " ROUND_3_INIT() " " ROUND_3_A(0) " " ROUND_3_B(3) " " ROUND_3_A(6) " " ROUND_3_B(9) " " ROUND_3_A_LAST(12) " sub $18, %[rounds] \n\t" " add $(24 * 18), %[src] \n\t" " add $(32 * 18), %[dst] \n\t" // Enter a 9x unrolled loop for rounds of 9 or more. "9: cmp $9, %[rounds] \n\t" " jl 6f \n\t" " " ROUND_3_INIT() " " ROUND_3_A(0) " " ROUND_3_B_LAST(3) " sub $9, %[rounds] \n\t" " add $(24 * 9), %[src] \n\t" " add $(32 * 9), %[dst] \n\t" // Enter a 6x unrolled loop for rounds of 6 or more. "6: cmp $6, %[rounds] \n\t" " jl 55f \n\t" " " ROUND_3_INIT() " " ROUND_3_A_LAST(0) " sub $6, %[rounds] \n\t" " add $(24 * 6), %[src] \n\t" " add $(32 * 6), %[dst] \n\t" // Dispatch the remaining rounds 0..5. "55: cmp $3, %[rounds] \n\t" " jg 45f \n\t" " je 3f \n\t" " cmp $1, %[rounds] \n\t" " jg 2f \n\t" " je 1f \n\t" " jmp 0f \n\t" "45: cmp $4, %[rounds] \n\t" " je 4f \n\t" // Block of non-interlaced encoding rounds, which can each // individually be jumped to. Rounds fall through to the next. "5: " ROUND() "4: " ROUND() "3: " ROUND() "2: " ROUND() "1: " ROUND() "0: \n\t" // Outputs (modified). : [rounds] "+r" (rounds), [loops] "+r" (loops), [src] "+r" (*s), [dst] "+r" (*o), [a] "=&x" (a), [b] "=&x" (b), [c] "=&x" (c), [d] "=&x" (d), [e] "=&x" (e), [f] "+x" (f) // Inputs (not modified). : [lut0] "x" (lut0), [lut1] "x" (lut1), [msk0] "x" (_mm256_set1_epi32(0x0FC0FC00)), [msk1] "x" (_mm256_set1_epi32(0x04000040)), [msk2] "x" (_mm256_set1_epi32(0x003F03F0)), [msk3] "x" (_mm256_set1_epi32(0x01000010)), [n51] "x" (_mm256_set1_epi8(51)), [n25] "x" (_mm256_set1_epi8(25)) // Clobbers. : "cc", "memory" ); } #pragma GCC diagnostic pop pybase64-1.4.3/base64/lib/arch/avx2/enc_reshuffle.c000066400000000000000000000052321500645130400215570ustar00rootroot00000000000000static BASE64_FORCE_INLINE __m256i enc_reshuffle (const __m256i input) { // Translation of the SSSE3 reshuffling algorithm to AVX2. This one // works with shifted (4 bytes) input in order to be able to work // efficiently in the two 128-bit lanes. // Input, bytes MSB to LSB: // 0 0 0 0 x w v u t s r q p o n m // l k j i h g f e d c b a 0 0 0 0 const __m256i in = _mm256_shuffle_epi8(input, _mm256_set_epi8( 10, 11, 9, 10, 7, 8, 6, 7, 4, 5, 3, 4, 1, 2, 0, 1, 14, 15, 13, 14, 11, 12, 10, 11, 8, 9, 7, 8, 5, 6, 4, 5)); // in, bytes MSB to LSB: // w x v w // t u s t // q r p q // n o m n // k l j k // h i g h // e f d e // b c a b const __m256i t0 = _mm256_and_si256(in, _mm256_set1_epi32(0x0FC0FC00)); // bits, upper case are most significant bits, lower case are least // significant bits. // 0000wwww XX000000 VVVVVV00 00000000 // 0000tttt UU000000 SSSSSS00 00000000 // 0000qqqq RR000000 PPPPPP00 00000000 // 0000nnnn OO000000 MMMMMM00 00000000 // 0000kkkk LL000000 JJJJJJ00 00000000 // 0000hhhh II000000 GGGGGG00 00000000 // 0000eeee FF000000 DDDDDD00 00000000 // 0000bbbb CC000000 AAAAAA00 00000000 const __m256i t1 = _mm256_mulhi_epu16(t0, _mm256_set1_epi32(0x04000040)); // 00000000 00wwwwXX 00000000 00VVVVVV // 00000000 00ttttUU 00000000 00SSSSSS // 00000000 00qqqqRR 00000000 00PPPPPP // 00000000 00nnnnOO 00000000 00MMMMMM // 00000000 00kkkkLL 00000000 00JJJJJJ // 00000000 00hhhhII 00000000 00GGGGGG // 00000000 00eeeeFF 00000000 00DDDDDD // 00000000 00bbbbCC 00000000 00AAAAAA const __m256i t2 = _mm256_and_si256(in, _mm256_set1_epi32(0x003F03F0)); // 00000000 00xxxxxx 000000vv WWWW0000 // 00000000 00uuuuuu 000000ss TTTT0000 // 00000000 00rrrrrr 000000pp QQQQ0000 // 00000000 00oooooo 000000mm NNNN0000 // 00000000 00llllll 000000jj KKKK0000 // 00000000 00iiiiii 000000gg HHHH0000 // 00000000 00ffffff 000000dd EEEE0000 // 00000000 00cccccc 000000aa BBBB0000 const __m256i t3 = _mm256_mullo_epi16(t2, _mm256_set1_epi32(0x01000010)); // 00xxxxxx 00000000 00vvWWWW 00000000 // 00uuuuuu 00000000 00ssTTTT 00000000 // 00rrrrrr 00000000 00ppQQQQ 00000000 // 00oooooo 00000000 00mmNNNN 00000000 // 00llllll 00000000 00jjKKKK 00000000 // 00iiiiii 00000000 00ggHHHH 00000000 // 00ffffff 00000000 00ddEEEE 00000000 // 00cccccc 00000000 00aaBBBB 00000000 return _mm256_or_si256(t1, t3); // 00xxxxxx 00wwwwXX 00vvWWWW 00VVVVVV // 00uuuuuu 00ttttUU 00ssTTTT 00SSSSSS // 00rrrrrr 00qqqqRR 00ppQQQQ 00PPPPPP // 00oooooo 00nnnnOO 00mmNNNN 00MMMMMM // 00llllll 00kkkkLL 00jjKKKK 00JJJJJJ // 00iiiiii 00hhhhII 00ggHHHH 00GGGGGG // 00ffffff 00eeeeFF 00ddEEEE 00DDDDDD // 00cccccc 00bbbbCC 00aaBBBB 00AAAAAA } pybase64-1.4.3/base64/lib/arch/avx2/enc_translate.c000066400000000000000000000023431500645130400215710ustar00rootroot00000000000000static BASE64_FORCE_INLINE __m256i enc_translate (const __m256i in) { // A lookup table containing the absolute offsets for all ranges: const __m256i lut = _mm256_setr_epi8( 65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0, 65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0); // Translate values 0..63 to the Base64 alphabet. There are five sets: // # From To Abs Index Characters // 0 [0..25] [65..90] +65 0 ABCDEFGHIJKLMNOPQRSTUVWXYZ // 1 [26..51] [97..122] +71 1 abcdefghijklmnopqrstuvwxyz // 2 [52..61] [48..57] -4 [2..11] 0123456789 // 3 [62] [43] -19 12 + // 4 [63] [47] -16 13 / // Create LUT indices from the input. The index for range #0 is right, // others are 1 less than expected: __m256i indices = _mm256_subs_epu8(in, _mm256_set1_epi8(51)); // mask is 0xFF (-1) for range #[1..4] and 0x00 for range #0: const __m256i mask = _mm256_cmpgt_epi8(in, _mm256_set1_epi8(25)); // Subtract -1, so add 1 to indices for range #[1..4]. All indices are // now correct: indices = _mm256_sub_epi8(indices, mask); // Add offsets to input values: return _mm256_add_epi8(in, _mm256_shuffle_epi8(lut, indices)); } pybase64-1.4.3/base64/lib/arch/avx512/000077500000000000000000000000001500645130400167475ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/avx512/codec.c000066400000000000000000000016541500645130400201760ustar00rootroot00000000000000#include #include #include #include "../../../include/libbase64.h" #include "../../tables/tables.h" #include "../../codecs.h" #include "config.h" #include "../../env.h" #if HAVE_AVX512 #include #include "../avx2/dec_reshuffle.c" #include "../avx2/dec_loop.c" #include "enc_reshuffle_translate.c" #include "enc_loop.c" #endif // HAVE_AVX512 void base64_stream_encode_avx512 BASE64_ENC_PARAMS { #if HAVE_AVX512 #include "../generic/enc_head.c" enc_loop_avx512(&s, &slen, &o, &olen); #include "../generic/enc_tail.c" #else base64_enc_stub(state, src, srclen, out, outlen); #endif } // Reuse AVX2 decoding. Not supporting AVX512 at present int base64_stream_decode_avx512 BASE64_DEC_PARAMS { #if HAVE_AVX512 #include "../generic/dec_head.c" dec_loop_avx2(&s, &slen, &o, &olen); #include "../generic/dec_tail.c" #else return base64_dec_stub(state, src, srclen, out, outlen); #endif } pybase64-1.4.3/base64/lib/arch/avx512/enc_loop.c000066400000000000000000000027421500645130400207160ustar00rootroot00000000000000static BASE64_FORCE_INLINE void enc_loop_avx512_inner (const uint8_t **s, uint8_t **o) { // Load input. __m512i src = _mm512_loadu_si512((__m512i *) *s); // Reshuffle, translate, store. src = enc_reshuffle_translate(src); _mm512_storeu_si512((__m512i *) *o, src); *s += 48; *o += 64; } static inline void enc_loop_avx512 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 64) { return; } // Process blocks of 48 bytes at a time. Because blocks are loaded 64 // bytes at a time, ensure that there will be at least 24 remaining // bytes after the last round, so that the final read will not pass // beyond the bounds of the input buffer. size_t rounds = (*slen - 24) / 48; *slen -= rounds * 48; // 48 bytes consumed per round *olen += rounds * 64; // 64 bytes produced per round while (rounds > 0) { if (rounds >= 8) { enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); rounds -= 8; continue; } if (rounds >= 4) { enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); rounds -= 4; continue; } if (rounds >= 2) { enc_loop_avx512_inner(s, o); enc_loop_avx512_inner(s, o); rounds -= 2; continue; } enc_loop_avx512_inner(s, o); break; } } pybase64-1.4.3/base64/lib/arch/avx512/enc_reshuffle_translate.c000066400000000000000000000043461500645130400240070ustar00rootroot00000000000000// AVX512 algorithm is based on permutevar and multishift. The code is based on // https://github.com/WojciechMula/base64simd which is under BSD-2 license. static BASE64_FORCE_INLINE __m512i enc_reshuffle_translate (const __m512i input) { // 32-bit input // [ 0 0 0 0 0 0 0 0|c1 c0 d5 d4 d3 d2 d1 d0| // b3 b2 b1 b0 c5 c4 c3 c2|a5 a4 a3 a2 a1 a0 b5 b4] // output order [1, 2, 0, 1] // [b3 b2 b1 b0 c5 c4 c3 c2|c1 c0 d5 d4 d3 d2 d1 d0| // a5 a4 a3 a2 a1 a0 b5 b4|b3 b2 b1 b0 c3 c2 c1 c0] const __m512i shuffle_input = _mm512_setr_epi32(0x01020001, 0x04050304, 0x07080607, 0x0a0b090a, 0x0d0e0c0d, 0x10110f10, 0x13141213, 0x16171516, 0x191a1819, 0x1c1d1b1c, 0x1f201e1f, 0x22232122, 0x25262425, 0x28292728, 0x2b2c2a2b, 0x2e2f2d2e); // Reorder bytes // [b3 b2 b1 b0 c5 c4 c3 c2|c1 c0 d5 d4 d3 d2 d1 d0| // a5 a4 a3 a2 a1 a0 b5 b4|b3 b2 b1 b0 c3 c2 c1 c0] const __m512i in = _mm512_permutexvar_epi8(shuffle_input, input); // After multishift a single 32-bit lane has following layout // [c1 c0 d5 d4 d3 d2 d1 d0|b1 b0 c5 c4 c3 c2 c1 c0| // a1 a0 b5 b4 b3 b2 b1 b0|d1 d0 a5 a4 a3 a2 a1 a0] // (a = [10:17], b = [4:11], c = [22:27], d = [16:21]) // 48, 54, 36, 42, 16, 22, 4, 10 const __m512i shifts = _mm512_set1_epi64(0x3036242a1016040alu); __m512i shuffled_in = _mm512_multishift_epi64_epi8(shifts, in); // Translate immediatedly after reshuffled. const __m512i lookup = _mm512_loadu_si512(base64_table_enc_6bit); // Translation 6-bit values to ASCII. return _mm512_permutexvar_epi8(shuffled_in, lookup); } pybase64-1.4.3/base64/lib/arch/generic/000077500000000000000000000000001500645130400173355ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/generic/32/000077500000000000000000000000001500645130400175615ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/generic/32/dec_loop.c000066400000000000000000000042521500645130400215140ustar00rootroot00000000000000static BASE64_FORCE_INLINE int dec_loop_generic_32_inner (const uint8_t **s, uint8_t **o, size_t *rounds) { const uint32_t str = base64_table_dec_32bit_d0[(*s)[0]] | base64_table_dec_32bit_d1[(*s)[1]] | base64_table_dec_32bit_d2[(*s)[2]] | base64_table_dec_32bit_d3[(*s)[3]]; #if BASE64_LITTLE_ENDIAN // LUTs for little-endian set MSB in case of invalid character: if (str & UINT32_C(0x80000000)) { return 0; } #else // LUTs for big-endian set LSB in case of invalid character: if (str & UINT32_C(1)) { return 0; } #endif // Store the output: memcpy(*o, &str, sizeof (str)); *s += 4; *o += 3; *rounds -= 1; return 1; } static inline void dec_loop_generic_32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 8) { return; } // Process blocks of 4 bytes per round. Because one extra zero byte is // written after the output, ensure that there will be at least 4 bytes // of input data left to cover the gap. (Two data bytes and up to two // end-of-string markers.) size_t rounds = (*slen - 4) / 4; *slen -= rounds * 4; // 4 bytes consumed per round *olen += rounds * 3; // 3 bytes produced per round do { if (rounds >= 8) { if (dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds)) { continue; } break; } if (rounds >= 4) { if (dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds)) { continue; } break; } if (rounds >= 2) { if (dec_loop_generic_32_inner(s, o, &rounds) && dec_loop_generic_32_inner(s, o, &rounds)) { continue; } break; } dec_loop_generic_32_inner(s, o, &rounds); break; } while (rounds > 0); // Adjust for any rounds that were skipped: *slen += rounds * 4; *olen -= rounds * 3; } pybase64-1.4.3/base64/lib/arch/generic/32/enc_loop.c000066400000000000000000000036141500645130400215270ustar00rootroot00000000000000static BASE64_FORCE_INLINE void enc_loop_generic_32_inner (const uint8_t **s, uint8_t **o) { uint32_t src; // Load input: memcpy(&src, *s, sizeof (src)); // Reorder to 32-bit big-endian, if not already in that format. The // workset must be in big-endian, otherwise the shifted bits do not // carry over properly among adjacent bytes: src = BASE64_HTOBE32(src); // Two indices for the 12-bit lookup table: const size_t index0 = (src >> 20) & 0xFFFU; const size_t index1 = (src >> 8) & 0xFFFU; // Table lookup and store: memcpy(*o + 0, base64_table_enc_12bit + index0, 2); memcpy(*o + 2, base64_table_enc_12bit + index1, 2); *s += 3; *o += 4; } static inline void enc_loop_generic_32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 4) { return; } // Process blocks of 3 bytes at a time. Because blocks are loaded 4 // bytes at a time, ensure that there will be at least one remaining // byte after the last round, so that the final read will not pass // beyond the bounds of the input buffer: size_t rounds = (*slen - 1) / 3; *slen -= rounds * 3; // 3 bytes consumed per round *olen += rounds * 4; // 4 bytes produced per round do { if (rounds >= 8) { enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); rounds -= 8; continue; } if (rounds >= 4) { enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); rounds -= 4; continue; } if (rounds >= 2) { enc_loop_generic_32_inner(s, o); enc_loop_generic_32_inner(s, o); rounds -= 2; continue; } enc_loop_generic_32_inner(s, o); break; } while (rounds > 0); } pybase64-1.4.3/base64/lib/arch/generic/64/000077500000000000000000000000001500645130400175665ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/generic/64/enc_loop.c000066400000000000000000000041201500645130400215250ustar00rootroot00000000000000static BASE64_FORCE_INLINE void enc_loop_generic_64_inner (const uint8_t **s, uint8_t **o) { uint64_t src; // Load input: memcpy(&src, *s, sizeof (src)); // Reorder to 64-bit big-endian, if not already in that format. The // workset must be in big-endian, otherwise the shifted bits do not // carry over properly among adjacent bytes: src = BASE64_HTOBE64(src); // Four indices for the 12-bit lookup table: const size_t index0 = (src >> 52) & 0xFFFU; const size_t index1 = (src >> 40) & 0xFFFU; const size_t index2 = (src >> 28) & 0xFFFU; const size_t index3 = (src >> 16) & 0xFFFU; // Table lookup and store: memcpy(*o + 0, base64_table_enc_12bit + index0, 2); memcpy(*o + 2, base64_table_enc_12bit + index1, 2); memcpy(*o + 4, base64_table_enc_12bit + index2, 2); memcpy(*o + 6, base64_table_enc_12bit + index3, 2); *s += 6; *o += 8; } static inline void enc_loop_generic_64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 8) { return; } // Process blocks of 6 bytes at a time. Because blocks are loaded 8 // bytes at a time, ensure that there will be at least 2 remaining // bytes after the last round, so that the final read will not pass // beyond the bounds of the input buffer: size_t rounds = (*slen - 2) / 6; *slen -= rounds * 6; // 6 bytes consumed per round *olen += rounds * 8; // 8 bytes produced per round do { if (rounds >= 8) { enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); rounds -= 8; continue; } if (rounds >= 4) { enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); rounds -= 4; continue; } if (rounds >= 2) { enc_loop_generic_64_inner(s, o); enc_loop_generic_64_inner(s, o); rounds -= 2; continue; } enc_loop_generic_64_inner(s, o); break; } while (rounds > 0); } pybase64-1.4.3/base64/lib/arch/generic/codec.c000066400000000000000000000014471500645130400205640ustar00rootroot00000000000000#include #include #include #include "../../../include/libbase64.h" #include "../../tables/tables.h" #include "../../codecs.h" #include "config.h" #include "../../env.h" #if BASE64_WORDSIZE == 32 # include "32/enc_loop.c" #elif BASE64_WORDSIZE == 64 # include "64/enc_loop.c" #endif #if BASE64_WORDSIZE >= 32 # include "32/dec_loop.c" #endif void base64_stream_encode_plain BASE64_ENC_PARAMS { #include "enc_head.c" #if BASE64_WORDSIZE == 32 enc_loop_generic_32(&s, &slen, &o, &olen); #elif BASE64_WORDSIZE == 64 enc_loop_generic_64(&s, &slen, &o, &olen); #endif #include "enc_tail.c" } int base64_stream_decode_plain BASE64_DEC_PARAMS { #include "dec_head.c" #if BASE64_WORDSIZE >= 32 dec_loop_generic_32(&s, &slen, &o, &olen); #endif #include "dec_tail.c" } pybase64-1.4.3/base64/lib/arch/generic/dec_head.c000066400000000000000000000014271500645130400212210ustar00rootroot00000000000000int ret = 0; const uint8_t *s = (const uint8_t *) src; uint8_t *o = (uint8_t *) out; uint8_t q; // Use local temporaries to avoid cache thrashing: size_t olen = 0; size_t slen = srclen; struct base64_state st; st.eof = state->eof; st.bytes = state->bytes; st.carry = state->carry; // If we previously saw an EOF or an invalid character, bail out: if (st.eof) { *outlen = 0; ret = 0; // If there was a trailing '=' to check, check it: if (slen && (st.eof == BASE64_AEOF)) { state->bytes = 0; state->eof = BASE64_EOF; ret = ((base64_table_dec_8bit[*s++] == 254) && (slen == 1)) ? 1 : 0; } return ret; } // Turn four 6-bit numbers into three bytes: // out[0] = 11111122 // out[1] = 22223333 // out[2] = 33444444 // Duff's device again: switch (st.bytes) { for (;;) { case 0: pybase64-1.4.3/base64/lib/arch/generic/dec_tail.c000066400000000000000000000033561500645130400212540ustar00rootroot00000000000000 if (slen-- == 0) { ret = 1; break; } if ((q = base64_table_dec_8bit[*s++]) >= 254) { st.eof = BASE64_EOF; // Treat character '=' as invalid for byte 0: break; } st.carry = q << 2; st.bytes++; // Deliberate fallthrough: BASE64_FALLTHROUGH case 1: if (slen-- == 0) { ret = 1; break; } if ((q = base64_table_dec_8bit[*s++]) >= 254) { st.eof = BASE64_EOF; // Treat character '=' as invalid for byte 1: break; } *o++ = st.carry | (q >> 4); st.carry = q << 4; st.bytes++; olen++; // Deliberate fallthrough: BASE64_FALLTHROUGH case 2: if (slen-- == 0) { ret = 1; break; } if ((q = base64_table_dec_8bit[*s++]) >= 254) { st.bytes++; // When q == 254, the input char is '='. // Check if next byte is also '=': if (q == 254) { if (slen-- != 0) { st.bytes = 0; // EOF: st.eof = BASE64_EOF; q = base64_table_dec_8bit[*s++]; ret = ((q == 254) && (slen == 0)) ? 1 : 0; break; } else { // Almost EOF st.eof = BASE64_AEOF; ret = 1; break; } } // If we get here, there was an error: break; } *o++ = st.carry | (q >> 2); st.carry = q << 6; st.bytes++; olen++; // Deliberate fallthrough: BASE64_FALLTHROUGH case 3: if (slen-- == 0) { ret = 1; break; } if ((q = base64_table_dec_8bit[*s++]) >= 254) { st.bytes = 0; st.eof = BASE64_EOF; // When q == 254, the input char is '='. Return 1 and EOF. // When q == 255, the input char is invalid. Return 0 and EOF. ret = ((q == 254) && (slen == 0)) ? 1 : 0; break; } *o++ = st.carry | q; st.carry = 0; st.bytes = 0; olen++; } } state->eof = st.eof; state->bytes = st.bytes; state->carry = st.carry; *outlen = olen; return ret; pybase64-1.4.3/base64/lib/arch/generic/enc_head.c000066400000000000000000000011111500645130400212210ustar00rootroot00000000000000// Assume that *out is large enough to contain the output. // Theoretically it should be 4/3 the length of src. const uint8_t *s = (const uint8_t *) src; uint8_t *o = (uint8_t *) out; // Use local temporaries to avoid cache thrashing: size_t olen = 0; size_t slen = srclen; struct base64_state st; st.bytes = state->bytes; st.carry = state->carry; // Turn three bytes into four 6-bit numbers: // in[0] = 00111111 // in[1] = 00112222 // in[2] = 00222233 // in[3] = 00333333 // Duff's device, a for() loop inside a switch() statement. Legal! switch (st.bytes) { for (;;) { case 0: pybase64-1.4.3/base64/lib/arch/generic/enc_tail.c000066400000000000000000000011751500645130400212630ustar00rootroot00000000000000 if (slen-- == 0) { break; } *o++ = base64_table_enc_6bit[*s >> 2]; st.carry = (*s++ << 4) & 0x30; st.bytes++; olen += 1; // Deliberate fallthrough: BASE64_FALLTHROUGH case 1: if (slen-- == 0) { break; } *o++ = base64_table_enc_6bit[st.carry | (*s >> 4)]; st.carry = (*s++ << 2) & 0x3C; st.bytes++; olen += 1; // Deliberate fallthrough: BASE64_FALLTHROUGH case 2: if (slen-- == 0) { break; } *o++ = base64_table_enc_6bit[st.carry | (*s >> 6)]; *o++ = base64_table_enc_6bit[*s++ & 0x3F]; st.bytes = 0; olen += 2; } } state->bytes = st.bytes; state->carry = st.carry; *outlen = olen; pybase64-1.4.3/base64/lib/arch/neon32/000077500000000000000000000000001500645130400170255ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/neon32/codec.c000066400000000000000000000037211500645130400202510ustar00rootroot00000000000000#include #include #include #include "../../../include/libbase64.h" #include "../../tables/tables.h" #include "../../codecs.h" #include "config.h" #include "../../env.h" #ifdef __arm__ # if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && HAVE_NEON32 # define BASE64_USE_NEON32 # endif #endif #ifdef BASE64_USE_NEON32 #include // Only enable inline assembly on supported compilers. #if defined(__GNUC__) || defined(__clang__) #define BASE64_NEON32_USE_ASM #endif static BASE64_FORCE_INLINE uint8x16_t vqtbl1q_u8 (const uint8x16_t lut, const uint8x16_t indices) { // NEON32 only supports 64-bit wide lookups in 128-bit tables. Emulate // the NEON64 `vqtbl1q_u8` intrinsic to do 128-bit wide lookups. uint8x8x2_t lut2; uint8x8x2_t result; lut2.val[0] = vget_low_u8(lut); lut2.val[1] = vget_high_u8(lut); result.val[0] = vtbl2_u8(lut2, vget_low_u8(indices)); result.val[1] = vtbl2_u8(lut2, vget_high_u8(indices)); return vcombine_u8(result.val[0], result.val[1]); } #include "../generic/32/dec_loop.c" #include "../generic/32/enc_loop.c" #include "dec_loop.c" #include "enc_reshuffle.c" #include "enc_translate.c" #include "enc_loop.c" #endif // BASE64_USE_NEON32 // Stride size is so large on these NEON 32-bit functions // (48 bytes encode, 32 bytes decode) that we inline the // uint32 codec to stay performant on smaller inputs. void base64_stream_encode_neon32 BASE64_ENC_PARAMS { #ifdef BASE64_USE_NEON32 #include "../generic/enc_head.c" enc_loop_neon32(&s, &slen, &o, &olen); enc_loop_generic_32(&s, &slen, &o, &olen); #include "../generic/enc_tail.c" #else base64_enc_stub(state, src, srclen, out, outlen); #endif } int base64_stream_decode_neon32 BASE64_DEC_PARAMS { #ifdef BASE64_USE_NEON32 #include "../generic/dec_head.c" dec_loop_neon32(&s, &slen, &o, &olen); dec_loop_generic_32(&s, &slen, &o, &olen); #include "../generic/dec_tail.c" #else return base64_dec_stub(state, src, srclen, out, outlen); #endif } pybase64-1.4.3/base64/lib/arch/neon32/dec_loop.c000066400000000000000000000055321500645130400207620ustar00rootroot00000000000000static BASE64_FORCE_INLINE int is_nonzero (const uint8x16_t v) { uint64_t u64; const uint64x2_t v64 = vreinterpretq_u64_u8(v); const uint32x2_t v32 = vqmovn_u64(v64); vst1_u64(&u64, vreinterpret_u64_u32(v32)); return u64 != 0; } static BASE64_FORCE_INLINE uint8x16_t delta_lookup (const uint8x16_t v) { const uint8x8_t lut = { 0, 16, 19, 4, (uint8_t) -65, (uint8_t) -65, (uint8_t) -71, (uint8_t) -71, }; return vcombine_u8( vtbl1_u8(lut, vget_low_u8(v)), vtbl1_u8(lut, vget_high_u8(v))); } static BASE64_FORCE_INLINE uint8x16_t dec_loop_neon32_lane (uint8x16_t *lane) { // See the SSSE3 decoder for an explanation of the algorithm. const uint8x16_t lut_lo = { 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x1A, 0x1B, 0x1B, 0x1B, 0x1A }; const uint8x16_t lut_hi = { 0x10, 0x10, 0x01, 0x02, 0x04, 0x08, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }; const uint8x16_t mask_0F = vdupq_n_u8(0x0F); const uint8x16_t mask_2F = vdupq_n_u8(0x2F); const uint8x16_t hi_nibbles = vshrq_n_u8(*lane, 4); const uint8x16_t lo_nibbles = vandq_u8(*lane, mask_0F); const uint8x16_t eq_2F = vceqq_u8(*lane, mask_2F); const uint8x16_t hi = vqtbl1q_u8(lut_hi, hi_nibbles); const uint8x16_t lo = vqtbl1q_u8(lut_lo, lo_nibbles); // Now simply add the delta values to the input: *lane = vaddq_u8(*lane, delta_lookup(vaddq_u8(eq_2F, hi_nibbles))); // Return the validity mask: return vandq_u8(lo, hi); } static inline void dec_loop_neon32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 64) { return; } // Process blocks of 64 bytes per round. Unlike the SSE codecs, no // extra trailing zero bytes are written, so it is not necessary to // reserve extra input bytes: size_t rounds = *slen / 64; *slen -= rounds * 64; // 64 bytes consumed per round *olen += rounds * 48; // 48 bytes produced per round do { uint8x16x3_t dec; // Load 64 bytes and deinterleave: uint8x16x4_t str = vld4q_u8(*s); // Decode each lane, collect a mask of invalid inputs: const uint8x16_t classified = dec_loop_neon32_lane(&str.val[0]) | dec_loop_neon32_lane(&str.val[1]) | dec_loop_neon32_lane(&str.val[2]) | dec_loop_neon32_lane(&str.val[3]); // Check for invalid input: if any of the delta values are // zero, fall back on bytewise code to do error checking and // reporting: if (is_nonzero(classified)) { break; } // Compress four bytes into three: dec.val[0] = vorrq_u8(vshlq_n_u8(str.val[0], 2), vshrq_n_u8(str.val[1], 4)); dec.val[1] = vorrq_u8(vshlq_n_u8(str.val[1], 4), vshrq_n_u8(str.val[2], 2)); dec.val[2] = vorrq_u8(vshlq_n_u8(str.val[2], 6), str.val[3]); // Interleave and store decoded result: vst3q_u8(*o, dec); *s += 64; *o += 48; } while (--rounds > 0); // Adjust for any rounds that were skipped: *slen += rounds * 64; *olen -= rounds * 48; } pybase64-1.4.3/base64/lib/arch/neon32/enc_loop.c000066400000000000000000000110571500645130400207730ustar00rootroot00000000000000#ifdef BASE64_NEON32_USE_ASM static BASE64_FORCE_INLINE void enc_loop_neon32_inner_asm (const uint8_t **s, uint8_t **o) { // This function duplicates the functionality of enc_loop_neon32_inner, // but entirely with inline assembly. This gives a significant speedup // over using NEON intrinsics, which do not always generate very good // code. The logic of the assembly is directly lifted from the // intrinsics version, so it can be used as a guide to this code. // Temporary registers, used as scratch space. uint8x16_t tmp0, tmp1, tmp2, tmp3; uint8x16_t mask0, mask1, mask2, mask3; // A lookup table containing the absolute offsets for all ranges. const uint8x16_t lut = { 65U, 71U, 252U, 252U, 252U, 252U, 252U, 252U, 252U, 252U, 252U, 252U, 237U, 240U, 0U, 0U }; // Numeric constants. const uint8x16_t n51 = vdupq_n_u8(51); const uint8x16_t n25 = vdupq_n_u8(25); const uint8x16_t n63 = vdupq_n_u8(63); __asm__ ( // Load 48 bytes and deinterleave. The bytes are loaded to // hard-coded registers q12, q13 and q14, to ensure that they // are contiguous. Increment the source pointer. "vld3.8 {d24, d26, d28}, [%[src]]! \n\t" "vld3.8 {d25, d27, d29}, [%[src]]! \n\t" // Reshuffle the bytes using temporaries. "vshr.u8 %q[t0], q12, #2 \n\t" "vshr.u8 %q[t1], q13, #4 \n\t" "vshr.u8 %q[t2], q14, #6 \n\t" "vsli.8 %q[t1], q12, #4 \n\t" "vsli.8 %q[t2], q13, #2 \n\t" "vand.u8 %q[t1], %q[t1], %q[n63] \n\t" "vand.u8 %q[t2], %q[t2], %q[n63] \n\t" "vand.u8 %q[t3], q14, %q[n63] \n\t" // t0..t3 are the reshuffled inputs. Create LUT indices. "vqsub.u8 q12, %q[t0], %q[n51] \n\t" "vqsub.u8 q13, %q[t1], %q[n51] \n\t" "vqsub.u8 q14, %q[t2], %q[n51] \n\t" "vqsub.u8 q15, %q[t3], %q[n51] \n\t" // Create the mask for range #0. "vcgt.u8 %q[m0], %q[t0], %q[n25] \n\t" "vcgt.u8 %q[m1], %q[t1], %q[n25] \n\t" "vcgt.u8 %q[m2], %q[t2], %q[n25] \n\t" "vcgt.u8 %q[m3], %q[t3], %q[n25] \n\t" // Subtract -1 to correct the LUT indices. "vsub.u8 q12, %q[m0] \n\t" "vsub.u8 q13, %q[m1] \n\t" "vsub.u8 q14, %q[m2] \n\t" "vsub.u8 q15, %q[m3] \n\t" // Lookup the delta values. "vtbl.u8 d24, {%q[lut]}, d24 \n\t" "vtbl.u8 d25, {%q[lut]}, d25 \n\t" "vtbl.u8 d26, {%q[lut]}, d26 \n\t" "vtbl.u8 d27, {%q[lut]}, d27 \n\t" "vtbl.u8 d28, {%q[lut]}, d28 \n\t" "vtbl.u8 d29, {%q[lut]}, d29 \n\t" "vtbl.u8 d30, {%q[lut]}, d30 \n\t" "vtbl.u8 d31, {%q[lut]}, d31 \n\t" // Add the delta values. "vadd.u8 q12, %q[t0] \n\t" "vadd.u8 q13, %q[t1] \n\t" "vadd.u8 q14, %q[t2] \n\t" "vadd.u8 q15, %q[t3] \n\t" // Store 64 bytes and interleave. Increment the dest pointer. "vst4.8 {d24, d26, d28, d30}, [%[dst]]! \n\t" "vst4.8 {d25, d27, d29, d31}, [%[dst]]! \n\t" // Outputs (modified). : [src] "+r" (*s), [dst] "+r" (*o), [t0] "=&w" (tmp0), [t1] "=&w" (tmp1), [t2] "=&w" (tmp2), [t3] "=&w" (tmp3), [m0] "=&w" (mask0), [m1] "=&w" (mask1), [m2] "=&w" (mask2), [m3] "=&w" (mask3) // Inputs (not modified). : [lut] "w" (lut), [n25] "w" (n25), [n51] "w" (n51), [n63] "w" (n63) // Clobbers. : "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", "cc", "memory" ); } #endif static BASE64_FORCE_INLINE void enc_loop_neon32_inner (const uint8_t **s, uint8_t **o) { #ifdef BASE64_NEON32_USE_ASM enc_loop_neon32_inner_asm(s, o); #else // Load 48 bytes and deinterleave: uint8x16x3_t src = vld3q_u8(*s); // Reshuffle: uint8x16x4_t out = enc_reshuffle(src); // Translate reshuffled bytes to the Base64 alphabet: out = enc_translate(out); // Interleave and store output: vst4q_u8(*o, out); *s += 48; *o += 64; #endif } static inline void enc_loop_neon32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { size_t rounds = *slen / 48; *slen -= rounds * 48; // 48 bytes consumed per round *olen += rounds * 64; // 64 bytes produced per round while (rounds > 0) { if (rounds >= 8) { enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); rounds -= 8; continue; } if (rounds >= 4) { enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); rounds -= 4; continue; } if (rounds >= 2) { enc_loop_neon32_inner(s, o); enc_loop_neon32_inner(s, o); rounds -= 2; continue; } enc_loop_neon32_inner(s, o); break; } } pybase64-1.4.3/base64/lib/arch/neon32/enc_reshuffle.c000066400000000000000000000017261500645130400220070ustar00rootroot00000000000000static BASE64_FORCE_INLINE uint8x16x4_t enc_reshuffle (uint8x16x3_t in) { uint8x16x4_t out; // Input: // in[0] = a7 a6 a5 a4 a3 a2 a1 a0 // in[1] = b7 b6 b5 b4 b3 b2 b1 b0 // in[2] = c7 c6 c5 c4 c3 c2 c1 c0 // Output: // out[0] = 00 00 a7 a6 a5 a4 a3 a2 // out[1] = 00 00 a1 a0 b7 b6 b5 b4 // out[2] = 00 00 b3 b2 b1 b0 c7 c6 // out[3] = 00 00 c5 c4 c3 c2 c1 c0 // Move the input bits to where they need to be in the outputs. Except // for the first output, the high two bits are not cleared. out.val[0] = vshrq_n_u8(in.val[0], 2); out.val[1] = vshrq_n_u8(in.val[1], 4); out.val[2] = vshrq_n_u8(in.val[2], 6); out.val[1] = vsliq_n_u8(out.val[1], in.val[0], 4); out.val[2] = vsliq_n_u8(out.val[2], in.val[1], 2); // Clear the high two bits in the second, third and fourth output. out.val[1] = vandq_u8(out.val[1], vdupq_n_u8(0x3F)); out.val[2] = vandq_u8(out.val[2], vdupq_n_u8(0x3F)); out.val[3] = vandq_u8(in.val[2], vdupq_n_u8(0x3F)); return out; } pybase64-1.4.3/base64/lib/arch/neon32/enc_translate.c000066400000000000000000000041041500645130400220120ustar00rootroot00000000000000static BASE64_FORCE_INLINE uint8x16x4_t enc_translate (const uint8x16x4_t in) { // A lookup table containing the absolute offsets for all ranges: const uint8x16_t lut = { 65U, 71U, 252U, 252U, 252U, 252U, 252U, 252U, 252U, 252U, 252U, 252U, 237U, 240U, 0U, 0U }; const uint8x16_t offset = vdupq_n_u8(51); uint8x16x4_t indices, mask, delta, out; // Translate values 0..63 to the Base64 alphabet. There are five sets: // # From To Abs Index Characters // 0 [0..25] [65..90] +65 0 ABCDEFGHIJKLMNOPQRSTUVWXYZ // 1 [26..51] [97..122] +71 1 abcdefghijklmnopqrstuvwxyz // 2 [52..61] [48..57] -4 [2..11] 0123456789 // 3 [62] [43] -19 12 + // 4 [63] [47] -16 13 / // Create LUT indices from input: // the index for range #0 is right, others are 1 less than expected: indices.val[0] = vqsubq_u8(in.val[0], offset); indices.val[1] = vqsubq_u8(in.val[1], offset); indices.val[2] = vqsubq_u8(in.val[2], offset); indices.val[3] = vqsubq_u8(in.val[3], offset); // mask is 0xFF (-1) for range #[1..4] and 0x00 for range #0: mask.val[0] = vcgtq_u8(in.val[0], vdupq_n_u8(25)); mask.val[1] = vcgtq_u8(in.val[1], vdupq_n_u8(25)); mask.val[2] = vcgtq_u8(in.val[2], vdupq_n_u8(25)); mask.val[3] = vcgtq_u8(in.val[3], vdupq_n_u8(25)); // Subtract -1, so add 1 to indices for range #[1..4], All indices are // now correct: indices.val[0] = vsubq_u8(indices.val[0], mask.val[0]); indices.val[1] = vsubq_u8(indices.val[1], mask.val[1]); indices.val[2] = vsubq_u8(indices.val[2], mask.val[2]); indices.val[3] = vsubq_u8(indices.val[3], mask.val[3]); // Lookup delta values: delta.val[0] = vqtbl1q_u8(lut, indices.val[0]); delta.val[1] = vqtbl1q_u8(lut, indices.val[1]); delta.val[2] = vqtbl1q_u8(lut, indices.val[2]); delta.val[3] = vqtbl1q_u8(lut, indices.val[3]); // Add delta values: out.val[0] = vaddq_u8(in.val[0], delta.val[0]); out.val[1] = vaddq_u8(in.val[1], delta.val[1]); out.val[2] = vaddq_u8(in.val[2], delta.val[2]); out.val[3] = vaddq_u8(in.val[3], delta.val[3]); return out; } pybase64-1.4.3/base64/lib/arch/neon64/000077500000000000000000000000001500645130400170325ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/neon64/codec.c000066400000000000000000000042071500645130400202560ustar00rootroot00000000000000#include #include #include #include "../../../include/libbase64.h" #include "../../tables/tables.h" #include "../../codecs.h" #include "config.h" #include "../../env.h" #if HAVE_NEON64 #include // Only enable inline assembly on supported compilers. #if defined(__GNUC__) || defined(__clang__) #define BASE64_NEON64_USE_ASM #endif static BASE64_FORCE_INLINE uint8x16x4_t load_64byte_table (const uint8_t *p) { #ifdef BASE64_NEON64_USE_ASM // Force the table to be loaded into contiguous registers. GCC will not // normally allocate contiguous registers for a `uint8x16x4_t'. These // registers are chosen to not conflict with the ones in the enc loop. register uint8x16_t t0 __asm__ ("v8"); register uint8x16_t t1 __asm__ ("v9"); register uint8x16_t t2 __asm__ ("v10"); register uint8x16_t t3 __asm__ ("v11"); __asm__ ( "ld1 {%[t0].16b, %[t1].16b, %[t2].16b, %[t3].16b}, [%[src]], #64 \n\t" : [src] "+r" (p), [t0] "=w" (t0), [t1] "=w" (t1), [t2] "=w" (t2), [t3] "=w" (t3) ); return (uint8x16x4_t) { .val[0] = t0, .val[1] = t1, .val[2] = t2, .val[3] = t3, }; #else return vld1q_u8_x4(p); #endif } #include "../generic/32/dec_loop.c" #include "../generic/64/enc_loop.c" #include "dec_loop.c" #ifdef BASE64_NEON64_USE_ASM # include "enc_loop_asm.c" #else # include "enc_reshuffle.c" # include "enc_loop.c" #endif #endif // HAVE_NEON64 // Stride size is so large on these NEON 64-bit functions // (48 bytes encode, 64 bytes decode) that we inline the // uint64 codec to stay performant on smaller inputs. void base64_stream_encode_neon64 BASE64_ENC_PARAMS { #if HAVE_NEON64 #include "../generic/enc_head.c" enc_loop_neon64(&s, &slen, &o, &olen); enc_loop_generic_64(&s, &slen, &o, &olen); #include "../generic/enc_tail.c" #else base64_enc_stub(state, src, srclen, out, outlen); #endif } int base64_stream_decode_neon64 BASE64_DEC_PARAMS { #if HAVE_NEON64 #include "../generic/dec_head.c" dec_loop_neon64(&s, &slen, &o, &olen); dec_loop_generic_32(&s, &slen, &o, &olen); #include "../generic/dec_tail.c" #else return base64_dec_stub(state, src, srclen, out, outlen); #endif } pybase64-1.4.3/base64/lib/arch/neon64/dec_loop.c000066400000000000000000000122171500645130400207650ustar00rootroot00000000000000// The input consists of five valid character sets in the Base64 alphabet, // which we need to map back to the 6-bit values they represent. // There are three ranges, two singles, and then there's the rest. // // # From To LUT Characters // 1 [0..42] [255] #1 invalid input // 2 [43] [62] #1 + // 3 [44..46] [255] #1 invalid input // 4 [47] [63] #1 / // 5 [48..57] [52..61] #1 0..9 // 6 [58..63] [255] #1 invalid input // 7 [64] [255] #2 invalid input // 8 [65..90] [0..25] #2 A..Z // 9 [91..96] [255] #2 invalid input // 10 [97..122] [26..51] #2 a..z // 11 [123..126] [255] #2 invalid input // (12) Everything else => invalid input // The first LUT will use the VTBL instruction (out of range indices are set to // 0 in destination). static const uint8_t dec_lut1[] = { 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 62U, 255U, 255U, 255U, 63U, 52U, 53U, 54U, 55U, 56U, 57U, 58U, 59U, 60U, 61U, 255U, 255U, 255U, 255U, 255U, 255U, }; // The second LUT will use the VTBX instruction (out of range indices will be // unchanged in destination). Input [64..126] will be mapped to index [1..63] // in this LUT. Index 0 means that value comes from LUT #1. static const uint8_t dec_lut2[] = { 0U, 255U, 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 16U, 17U, 18U, 19U, 20U, 21U, 22U, 23U, 24U, 25U, 255U, 255U, 255U, 255U, 255U, 255U, 26U, 27U, 28U, 29U, 30U, 31U, 32U, 33U, 34U, 35U, 36U, 37U, 38U, 39U, 40U, 41U, 42U, 43U, 44U, 45U, 46U, 47U, 48U, 49U, 50U, 51U, 255U, 255U, 255U, 255U, }; // All input values in range for the first look-up will be 0U in the second // look-up result. All input values out of range for the first look-up will be // 0U in the first look-up result. Thus, the two results can be ORed without // conflicts. // // Invalid characters that are in the valid range for either look-up will be // set to 255U in the combined result. Other invalid characters will just be // passed through with the second look-up result (using the VTBX instruction). // Since the second LUT is 64 bytes, those passed-through values are guaranteed // to have a value greater than 63U. Therefore, valid characters will be mapped // to the valid [0..63] range and all invalid characters will be mapped to // values greater than 63. static inline void dec_loop_neon64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 64) { return; } // Process blocks of 64 bytes per round. Unlike the SSE codecs, no // extra trailing zero bytes are written, so it is not necessary to // reserve extra input bytes: size_t rounds = *slen / 64; *slen -= rounds * 64; // 64 bytes consumed per round *olen += rounds * 48; // 48 bytes produced per round const uint8x16x4_t tbl_dec1 = load_64byte_table(dec_lut1); const uint8x16x4_t tbl_dec2 = load_64byte_table(dec_lut2); do { const uint8x16_t offset = vdupq_n_u8(63U); uint8x16x4_t dec1, dec2; uint8x16x3_t dec; // Load 64 bytes and deinterleave: uint8x16x4_t str = vld4q_u8((uint8_t *) *s); // Get indices for second LUT: dec2.val[0] = vqsubq_u8(str.val[0], offset); dec2.val[1] = vqsubq_u8(str.val[1], offset); dec2.val[2] = vqsubq_u8(str.val[2], offset); dec2.val[3] = vqsubq_u8(str.val[3], offset); // Get values from first LUT: dec1.val[0] = vqtbl4q_u8(tbl_dec1, str.val[0]); dec1.val[1] = vqtbl4q_u8(tbl_dec1, str.val[1]); dec1.val[2] = vqtbl4q_u8(tbl_dec1, str.val[2]); dec1.val[3] = vqtbl4q_u8(tbl_dec1, str.val[3]); // Get values from second LUT: dec2.val[0] = vqtbx4q_u8(dec2.val[0], tbl_dec2, dec2.val[0]); dec2.val[1] = vqtbx4q_u8(dec2.val[1], tbl_dec2, dec2.val[1]); dec2.val[2] = vqtbx4q_u8(dec2.val[2], tbl_dec2, dec2.val[2]); dec2.val[3] = vqtbx4q_u8(dec2.val[3], tbl_dec2, dec2.val[3]); // Get final values: str.val[0] = vorrq_u8(dec1.val[0], dec2.val[0]); str.val[1] = vorrq_u8(dec1.val[1], dec2.val[1]); str.val[2] = vorrq_u8(dec1.val[2], dec2.val[2]); str.val[3] = vorrq_u8(dec1.val[3], dec2.val[3]); // Check for invalid input, any value larger than 63: const uint8x16_t classified = vorrq_u8( vorrq_u8(vcgtq_u8(str.val[0], vdupq_n_u8(63)), vcgtq_u8(str.val[1], vdupq_n_u8(63))), vorrq_u8(vcgtq_u8(str.val[2], vdupq_n_u8(63)), vcgtq_u8(str.val[3], vdupq_n_u8(63))) ); // Check that all bits are zero: if (vmaxvq_u8(classified) != 0U) { break; } // Compress four bytes into three: dec.val[0] = vorrq_u8(vshlq_n_u8(str.val[0], 2), vshrq_n_u8(str.val[1], 4)); dec.val[1] = vorrq_u8(vshlq_n_u8(str.val[1], 4), vshrq_n_u8(str.val[2], 2)); dec.val[2] = vorrq_u8(vshlq_n_u8(str.val[2], 6), str.val[3]); // Interleave and store decoded result: vst3q_u8((uint8_t *) *o, dec); *s += 64; *o += 48; } while (--rounds > 0); // Adjust for any rounds that were skipped: *slen += rounds * 64; *olen -= rounds * 48; } pybase64-1.4.3/base64/lib/arch/neon64/enc_loop.c000066400000000000000000000035011500645130400207730ustar00rootroot00000000000000static BASE64_FORCE_INLINE void enc_loop_neon64_inner (const uint8_t **s, uint8_t **o, const uint8x16x4_t tbl_enc) { // Load 48 bytes and deinterleave: uint8x16x3_t src = vld3q_u8(*s); // Divide bits of three input bytes over four output bytes: uint8x16x4_t out = enc_reshuffle(src); // The bits have now been shifted to the right locations; // translate their values 0..63 to the Base64 alphabet. // Use a 64-byte table lookup: out.val[0] = vqtbl4q_u8(tbl_enc, out.val[0]); out.val[1] = vqtbl4q_u8(tbl_enc, out.val[1]); out.val[2] = vqtbl4q_u8(tbl_enc, out.val[2]); out.val[3] = vqtbl4q_u8(tbl_enc, out.val[3]); // Interleave and store output: vst4q_u8(*o, out); *s += 48; *o += 64; } static inline void enc_loop_neon64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { size_t rounds = *slen / 48; *slen -= rounds * 48; // 48 bytes consumed per round *olen += rounds * 64; // 64 bytes produced per round // Load the encoding table: const uint8x16x4_t tbl_enc = load_64byte_table(base64_table_enc_6bit); while (rounds > 0) { if (rounds >= 8) { enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); rounds -= 8; continue; } if (rounds >= 4) { enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); rounds -= 4; continue; } if (rounds >= 2) { enc_loop_neon64_inner(s, o, tbl_enc); enc_loop_neon64_inner(s, o, tbl_enc); rounds -= 2; continue; } enc_loop_neon64_inner(s, o, tbl_enc); break; } } pybase64-1.4.3/base64/lib/arch/neon64/enc_loop_asm.c000066400000000000000000000127611500645130400216430ustar00rootroot00000000000000// Apologies in advance for combining the preprocessor with inline assembly, // two notoriously gnarly parts of C, but it was necessary to avoid a lot of // code repetition. The preprocessor is used to template large sections of // inline assembly that differ only in the registers used. If the code was // written out by hand, it would become very large and hard to audit. // Generate a block of inline assembly that loads three user-defined registers // A, B, C from memory and deinterleaves them, post-incrementing the src // pointer. The register set should be sequential. #define LOAD(A, B, C) \ "ld3 {"A".16b, "B".16b, "C".16b}, [%[src]], #48 \n\t" // Generate a block of inline assembly that takes three deinterleaved registers // and shuffles the bytes. The output is in temporary registers t0..t3. #define SHUF(A, B, C) \ "ushr %[t0].16b, "A".16b, #2 \n\t" \ "ushr %[t1].16b, "B".16b, #4 \n\t" \ "ushr %[t2].16b, "C".16b, #6 \n\t" \ "sli %[t1].16b, "A".16b, #4 \n\t" \ "sli %[t2].16b, "B".16b, #2 \n\t" \ "and %[t1].16b, %[t1].16b, %[n63].16b \n\t" \ "and %[t2].16b, %[t2].16b, %[n63].16b \n\t" \ "and %[t3].16b, "C".16b, %[n63].16b \n\t" // Generate a block of inline assembly that takes temporary registers t0..t3 // and translates them to the base64 alphabet, using a table loaded into // v8..v11. The output is in user-defined registers A..D. #define TRAN(A, B, C, D) \ "tbl "A".16b, {v8.16b-v11.16b}, %[t0].16b \n\t" \ "tbl "B".16b, {v8.16b-v11.16b}, %[t1].16b \n\t" \ "tbl "C".16b, {v8.16b-v11.16b}, %[t2].16b \n\t" \ "tbl "D".16b, {v8.16b-v11.16b}, %[t3].16b \n\t" // Generate a block of inline assembly that interleaves four registers and // stores them, post-incrementing the destination pointer. #define STOR(A, B, C, D) \ "st4 {"A".16b, "B".16b, "C".16b, "D".16b}, [%[dst]], #64 \n\t" // Generate a block of inline assembly that generates a single self-contained // encoder round: fetch the data, process it, and store the result. #define ROUND() \ LOAD("v12", "v13", "v14") \ SHUF("v12", "v13", "v14") \ TRAN("v12", "v13", "v14", "v15") \ STOR("v12", "v13", "v14", "v15") // Generate a block of assembly that generates a type A interleaved encoder // round. It uses registers that were loaded by the previous type B round, and // in turn loads registers for the next type B round. #define ROUND_A() \ SHUF("v2", "v3", "v4") \ LOAD("v12", "v13", "v14") \ TRAN("v2", "v3", "v4", "v5") \ STOR("v2", "v3", "v4", "v5") // Type B interleaved encoder round. Same as type A, but register sets swapped. #define ROUND_B() \ SHUF("v12", "v13", "v14") \ LOAD("v2", "v3", "v4") \ TRAN("v12", "v13", "v14", "v15") \ STOR("v12", "v13", "v14", "v15") // The first type A round needs to load its own registers. #define ROUND_A_FIRST() \ LOAD("v2", "v3", "v4") \ ROUND_A() // The last type B round omits the load for the next step. #define ROUND_B_LAST() \ SHUF("v12", "v13", "v14") \ TRAN("v12", "v13", "v14", "v15") \ STOR("v12", "v13", "v14", "v15") // Suppress clang's warning that the literal string in the asm statement is // overlong (longer than the ISO-mandated minimum size of 4095 bytes for C99 // compilers). It may be true, but the goal here is not C99 portability. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverlength-strings" static inline void enc_loop_neon64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { size_t rounds = *slen / 48; if (rounds == 0) { return; } *slen -= rounds * 48; // 48 bytes consumed per round. *olen += rounds * 64; // 64 bytes produced per round. // Number of times to go through the 8x loop. size_t loops = rounds / 8; // Number of rounds remaining after the 8x loop. rounds %= 8; // Temporary registers, used as scratch space. uint8x16_t tmp0, tmp1, tmp2, tmp3; __asm__ volatile ( // Load the encoding table into v8..v11. " ld1 {v8.16b-v11.16b}, [%[tbl]] \n\t" // If there are eight rounds or more, enter an 8x unrolled loop // of interleaved encoding rounds. The rounds interleave memory // operations (load/store) with data operations to maximize // pipeline throughput. " cbz %[loops], 4f \n\t" // The SIMD instructions do not touch the flags. "88: subs %[loops], %[loops], #1 \n\t" " " ROUND_A_FIRST() " " ROUND_B() " " ROUND_A() " " ROUND_B() " " ROUND_A() " " ROUND_B() " " ROUND_A() " " ROUND_B_LAST() " b.ne 88b \n\t" // Enter a 4x unrolled loop for rounds of 4 or more. "4: cmp %[rounds], #4 \n\t" " b.lt 30f \n\t" " " ROUND_A_FIRST() " " ROUND_B() " " ROUND_A() " " ROUND_B_LAST() " sub %[rounds], %[rounds], #4 \n\t" // Dispatch the remaining rounds 0..3. "30: cbz %[rounds], 0f \n\t" " cmp %[rounds], #2 \n\t" " b.eq 2f \n\t" " b.lt 1f \n\t" // Block of non-interlaced encoding rounds, which can each // individually be jumped to. Rounds fall through to the next. "3: " ROUND() "2: " ROUND() "1: " ROUND() "0: \n\t" // Outputs (modified). : [loops] "+r" (loops), [src] "+r" (*s), [dst] "+r" (*o), [t0] "=&w" (tmp0), [t1] "=&w" (tmp1), [t2] "=&w" (tmp2), [t3] "=&w" (tmp3) // Inputs (not modified). : [rounds] "r" (rounds), [tbl] "r" (base64_table_enc_6bit), [n63] "w" (vdupq_n_u8(63)) // Clobbers. : "v2", "v3", "v4", "v5", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", "cc", "memory" ); } #pragma GCC diagnostic pop pybase64-1.4.3/base64/lib/arch/neon64/enc_reshuffle.c000066400000000000000000000017341500645130400220130ustar00rootroot00000000000000static BASE64_FORCE_INLINE uint8x16x4_t enc_reshuffle (const uint8x16x3_t in) { uint8x16x4_t out; // Input: // in[0] = a7 a6 a5 a4 a3 a2 a1 a0 // in[1] = b7 b6 b5 b4 b3 b2 b1 b0 // in[2] = c7 c6 c5 c4 c3 c2 c1 c0 // Output: // out[0] = 00 00 a7 a6 a5 a4 a3 a2 // out[1] = 00 00 a1 a0 b7 b6 b5 b4 // out[2] = 00 00 b3 b2 b1 b0 c7 c6 // out[3] = 00 00 c5 c4 c3 c2 c1 c0 // Move the input bits to where they need to be in the outputs. Except // for the first output, the high two bits are not cleared. out.val[0] = vshrq_n_u8(in.val[0], 2); out.val[1] = vshrq_n_u8(in.val[1], 4); out.val[2] = vshrq_n_u8(in.val[2], 6); out.val[1] = vsliq_n_u8(out.val[1], in.val[0], 4); out.val[2] = vsliq_n_u8(out.val[2], in.val[1], 2); // Clear the high two bits in the second, third and fourth output. out.val[1] = vandq_u8(out.val[1], vdupq_n_u8(0x3F)); out.val[2] = vandq_u8(out.val[2], vdupq_n_u8(0x3F)); out.val[3] = vandq_u8(in.val[2], vdupq_n_u8(0x3F)); return out; } pybase64-1.4.3/base64/lib/arch/sse41/000077500000000000000000000000001500645130400166605ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/sse41/codec.c000066400000000000000000000023611500645130400201030ustar00rootroot00000000000000#include #include #include #include "../../../include/libbase64.h" #include "../../tables/tables.h" #include "../../codecs.h" #include "config.h" #include "../../env.h" #if HAVE_SSE41 #include // Only enable inline assembly on supported compilers and on 64-bit CPUs. #ifndef BASE64_SSE41_USE_ASM # if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64 # define BASE64_SSE41_USE_ASM 1 # else # define BASE64_SSE41_USE_ASM 0 # endif #endif #include "../ssse3/dec_reshuffle.c" #include "../ssse3/dec_loop.c" #if BASE64_SSE41_USE_ASM # include "../ssse3/enc_loop_asm.c" #else # include "../ssse3/enc_translate.c" # include "../ssse3/enc_reshuffle.c" # include "../ssse3/enc_loop.c" #endif #endif // HAVE_SSE41 void base64_stream_encode_sse41 BASE64_ENC_PARAMS { #if HAVE_SSE41 #include "../generic/enc_head.c" enc_loop_ssse3(&s, &slen, &o, &olen); #include "../generic/enc_tail.c" #else base64_enc_stub(state, src, srclen, out, outlen); #endif } int base64_stream_decode_sse41 BASE64_DEC_PARAMS { #if HAVE_SSE41 #include "../generic/dec_head.c" dec_loop_ssse3(&s, &slen, &o, &olen); #include "../generic/dec_tail.c" #else return base64_dec_stub(state, src, srclen, out, outlen); #endif } pybase64-1.4.3/base64/lib/arch/sse42/000077500000000000000000000000001500645130400166615ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/sse42/codec.c000066400000000000000000000023611500645130400201040ustar00rootroot00000000000000#include #include #include #include "../../../include/libbase64.h" #include "../../tables/tables.h" #include "../../codecs.h" #include "config.h" #include "../../env.h" #if HAVE_SSE42 #include // Only enable inline assembly on supported compilers and on 64-bit CPUs. #ifndef BASE64_SSE42_USE_ASM # if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64 # define BASE64_SSE42_USE_ASM 1 # else # define BASE64_SSE42_USE_ASM 0 # endif #endif #include "../ssse3/dec_reshuffle.c" #include "../ssse3/dec_loop.c" #if BASE64_SSE42_USE_ASM # include "../ssse3/enc_loop_asm.c" #else # include "../ssse3/enc_translate.c" # include "../ssse3/enc_reshuffle.c" # include "../ssse3/enc_loop.c" #endif #endif // HAVE_SSE42 void base64_stream_encode_sse42 BASE64_ENC_PARAMS { #if HAVE_SSE42 #include "../generic/enc_head.c" enc_loop_ssse3(&s, &slen, &o, &olen); #include "../generic/enc_tail.c" #else base64_enc_stub(state, src, srclen, out, outlen); #endif } int base64_stream_decode_sse42 BASE64_DEC_PARAMS { #if HAVE_SSE42 #include "../generic/dec_head.c" dec_loop_ssse3(&s, &slen, &o, &olen); #include "../generic/dec_tail.c" #else return base64_dec_stub(state, src, srclen, out, outlen); #endif } pybase64-1.4.3/base64/lib/arch/ssse3/000077500000000000000000000000001500645130400167615ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/arch/ssse3/codec.c000066400000000000000000000025071500645130400202060ustar00rootroot00000000000000#include #include #include #include "../../../include/libbase64.h" #include "../../tables/tables.h" #include "../../codecs.h" #include "config.h" #include "../../env.h" #if HAVE_SSSE3 #include // Only enable inline assembly on supported compilers and on 64-bit CPUs. // 32-bit CPUs with SSSE3 support, such as low-end Atoms, only have eight XMM // registers, which is not enough to run the inline assembly. #ifndef BASE64_SSSE3_USE_ASM # if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64 # define BASE64_SSSE3_USE_ASM 1 # else # define BASE64_SSSE3_USE_ASM 0 # endif #endif #include "dec_reshuffle.c" #include "dec_loop.c" #if BASE64_SSSE3_USE_ASM # include "enc_loop_asm.c" #else # include "enc_reshuffle.c" # include "enc_translate.c" # include "enc_loop.c" #endif #endif // HAVE_SSSE3 void base64_stream_encode_ssse3 BASE64_ENC_PARAMS { #if HAVE_SSSE3 #include "../generic/enc_head.c" enc_loop_ssse3(&s, &slen, &o, &olen); #include "../generic/enc_tail.c" #else base64_enc_stub(state, src, srclen, out, outlen); #endif } int base64_stream_decode_ssse3 BASE64_DEC_PARAMS { #if HAVE_SSSE3 #include "../generic/dec_head.c" dec_loop_ssse3(&s, &slen, &o, &olen); #include "../generic/dec_tail.c" #else return base64_dec_stub(state, src, srclen, out, outlen); #endif } pybase64-1.4.3/base64/lib/arch/ssse3/dec_loop.c000066400000000000000000000153531500645130400207200ustar00rootroot00000000000000// The input consists of six character sets in the Base64 alphabet, which we // need to map back to the 6-bit values they represent. There are three ranges, // two singles, and then there's the rest. // // # From To Add Characters // 1 [43] [62] +19 + // 2 [47] [63] +16 / // 3 [48..57] [52..61] +4 0..9 // 4 [65..90] [0..25] -65 A..Z // 5 [97..122] [26..51] -71 a..z // (6) Everything else => invalid input // // We will use lookup tables for character validation and offset computation. // Remember that 0x2X and 0x0X are the same index for _mm_shuffle_epi8, this // allows to mask with 0x2F instead of 0x0F and thus save one constant // declaration (register and/or memory access). // // For offsets: // Perfect hash for lut = ((src >> 4) & 0x2F) + ((src == 0x2F) ? 0xFF : 0x00) // 0000 = garbage // 0001 = / // 0010 = + // 0011 = 0-9 // 0100 = A-Z // 0101 = A-Z // 0110 = a-z // 0111 = a-z // 1000 >= garbage // // For validation, here's the table. // A character is valid if and only if the AND of the 2 lookups equals 0: // // hi \ lo 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 // LUT 0x15 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x13 0x1A 0x1B 0x1B 0x1B 0x1A // // 0000 0x10 char NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI // andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 // // 0001 0x10 char DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US // andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 // // 0010 0x01 char ! " # $ % & ' ( ) * + , - . / // andlut 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x00 0x01 0x01 0x01 0x00 // // 0011 0x02 char 0 1 2 3 4 5 6 7 8 9 : ; < = > ? // andlut 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x02 0x02 0x02 0x02 0x02 // // 0100 0x04 char @ A B C D E F G H I J K L M N O // andlut 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 // // 0101 0x08 char P Q R S T U V W X Y Z [ \ ] ^ _ // andlut 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x08 0x08 0x08 0x08 0x08 // // 0110 0x04 char ` a b c d e f g h i j k l m n o // andlut 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 // 0111 0x08 char p q r s t u v w x y z { | } ~ // andlut 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x08 0x08 0x08 0x08 0x08 // // 1000 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 // 1001 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 // 1010 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 // 1011 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 // 1100 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 // 1101 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 // 1110 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 // 1111 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static BASE64_FORCE_INLINE int dec_loop_ssse3_inner (const uint8_t **s, uint8_t **o, size_t *rounds) { const __m128i lut_lo = _mm_setr_epi8( 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x1A, 0x1B, 0x1B, 0x1B, 0x1A); const __m128i lut_hi = _mm_setr_epi8( 0x10, 0x10, 0x01, 0x02, 0x04, 0x08, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10); const __m128i lut_roll = _mm_setr_epi8( 0, 16, 19, 4, -65, -65, -71, -71, 0, 0, 0, 0, 0, 0, 0, 0); const __m128i mask_2F = _mm_set1_epi8(0x2F); // Load input: __m128i str = _mm_loadu_si128((__m128i *) *s); // Table lookups: const __m128i hi_nibbles = _mm_and_si128(_mm_srli_epi32(str, 4), mask_2F); const __m128i lo_nibbles = _mm_and_si128(str, mask_2F); const __m128i hi = _mm_shuffle_epi8(lut_hi, hi_nibbles); const __m128i lo = _mm_shuffle_epi8(lut_lo, lo_nibbles); // Check for invalid input: if any "and" values from lo and hi are not // zero, fall back on bytewise code to do error checking and reporting: if (_mm_movemask_epi8(_mm_cmpgt_epi8(_mm_and_si128(lo, hi), _mm_setzero_si128())) != 0) { return 0; } const __m128i eq_2F = _mm_cmpeq_epi8(str, mask_2F); const __m128i roll = _mm_shuffle_epi8(lut_roll, _mm_add_epi8(eq_2F, hi_nibbles)); // Now simply add the delta values to the input: str = _mm_add_epi8(str, roll); // Reshuffle the input to packed 12-byte output format: str = dec_reshuffle(str); // Store the output: _mm_storeu_si128((__m128i *) *o, str); *s += 16; *o += 12; *rounds -= 1; return 1; } static inline void dec_loop_ssse3 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 24) { return; } // Process blocks of 16 bytes per round. Because 4 extra zero bytes are // written after the output, ensure that there will be at least 8 bytes // of input data left to cover the gap. (6 data bytes and up to two // end-of-string markers.) size_t rounds = (*slen - 8) / 16; *slen -= rounds * 16; // 16 bytes consumed per round *olen += rounds * 12; // 12 bytes produced per round do { if (rounds >= 8) { if (dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds)) { continue; } break; } if (rounds >= 4) { if (dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds)) { continue; } break; } if (rounds >= 2) { if (dec_loop_ssse3_inner(s, o, &rounds) && dec_loop_ssse3_inner(s, o, &rounds)) { continue; } break; } dec_loop_ssse3_inner(s, o, &rounds); break; } while (rounds > 0); // Adjust for any rounds that were skipped: *slen += rounds * 16; *olen -= rounds * 12; } pybase64-1.4.3/base64/lib/arch/ssse3/dec_reshuffle.c000066400000000000000000000021361500645130400217250ustar00rootroot00000000000000static BASE64_FORCE_INLINE __m128i dec_reshuffle (const __m128i in) { // in, bits, upper case are most significant bits, lower case are least significant bits // 00llllll 00kkkkLL 00jjKKKK 00JJJJJJ // 00iiiiii 00hhhhII 00ggHHHH 00GGGGGG // 00ffffff 00eeeeFF 00ddEEEE 00DDDDDD // 00cccccc 00bbbbCC 00aaBBBB 00AAAAAA const __m128i merge_ab_and_bc = _mm_maddubs_epi16(in, _mm_set1_epi32(0x01400140)); // 0000kkkk LLllllll 0000JJJJ JJjjKKKK // 0000hhhh IIiiiiii 0000GGGG GGggHHHH // 0000eeee FFffffff 0000DDDD DDddEEEE // 0000bbbb CCcccccc 0000AAAA AAaaBBBB const __m128i out = _mm_madd_epi16(merge_ab_and_bc, _mm_set1_epi32(0x00011000)); // 00000000 JJJJJJjj KKKKkkkk LLllllll // 00000000 GGGGGGgg HHHHhhhh IIiiiiii // 00000000 DDDDDDdd EEEEeeee FFffffff // 00000000 AAAAAAaa BBBBbbbb CCcccccc // Pack bytes together: return _mm_shuffle_epi8(out, _mm_setr_epi8( 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1)); // 00000000 00000000 00000000 00000000 // LLllllll KKKKkkkk JJJJJJjj IIiiiiii // HHHHhhhh GGGGGGgg FFffffff EEEEeeee // DDDDDDdd CCcccccc BBBBbbbb AAAAAAaa } pybase64-1.4.3/base64/lib/arch/ssse3/enc_loop.c000066400000000000000000000030151500645130400207220ustar00rootroot00000000000000static BASE64_FORCE_INLINE void enc_loop_ssse3_inner (const uint8_t **s, uint8_t **o) { // Load input: __m128i str = _mm_loadu_si128((__m128i *) *s); // Reshuffle: str = enc_reshuffle(str); // Translate reshuffled bytes to the Base64 alphabet: str = enc_translate(str); // Store: _mm_storeu_si128((__m128i *) *o, str); *s += 12; *o += 16; } static inline void enc_loop_ssse3 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { if (*slen < 16) { return; } // Process blocks of 12 bytes at a time. Because blocks are loaded 16 // bytes at a time, ensure that there will be at least 4 remaining // bytes after the last round, so that the final read will not pass // beyond the bounds of the input buffer: size_t rounds = (*slen - 4) / 12; *slen -= rounds * 12; // 12 bytes consumed per round *olen += rounds * 16; // 16 bytes produced per round do { if (rounds >= 8) { enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); rounds -= 8; continue; } if (rounds >= 4) { enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); rounds -= 4; continue; } if (rounds >= 2) { enc_loop_ssse3_inner(s, o); enc_loop_ssse3_inner(s, o); rounds -= 2; continue; } enc_loop_ssse3_inner(s, o); break; } while (rounds > 0); } pybase64-1.4.3/base64/lib/arch/ssse3/enc_loop_asm.c000066400000000000000000000221361500645130400215670ustar00rootroot00000000000000// Apologies in advance for combining the preprocessor with inline assembly, // two notoriously gnarly parts of C, but it was necessary to avoid a lot of // code repetition. The preprocessor is used to template large sections of // inline assembly that differ only in the registers used. If the code was // written out by hand, it would become very large and hard to audit. // Generate a block of inline assembly that loads register R0 from memory. The // offset at which the register is loaded is set by the given round. #define LOAD(R0, ROUND) \ "lddqu ("#ROUND" * 12)(%[src]), %["R0"] \n\t" // Generate a block of inline assembly that deinterleaves and shuffles register // R0 using preloaded constants. Outputs in R0 and R1. #define SHUF(R0, R1) \ "pshufb %[lut0], %["R0"] \n\t" \ "movdqa %["R0"], %["R1"] \n\t" \ "pand %[msk0], %["R0"] \n\t" \ "pand %[msk2], %["R1"] \n\t" \ "pmulhuw %[msk1], %["R0"] \n\t" \ "pmullw %[msk3], %["R1"] \n\t" \ "por %["R1"], %["R0"] \n\t" // Generate a block of inline assembly that takes R0 and R1 and translates // their contents to the base64 alphabet, using preloaded constants. #define TRAN(R0, R1, R2) \ "movdqa %["R0"], %["R1"] \n\t" \ "movdqa %["R0"], %["R2"] \n\t" \ "psubusb %[n51], %["R1"] \n\t" \ "pcmpgtb %[n25], %["R2"] \n\t" \ "psubb %["R2"], %["R1"] \n\t" \ "movdqa %[lut1], %["R2"] \n\t" \ "pshufb %["R1"], %["R2"] \n\t" \ "paddb %["R2"], %["R0"] \n\t" // Generate a block of inline assembly that stores the given register R0 at an // offset set by the given round. #define STOR(R0, ROUND) \ "movdqu %["R0"], ("#ROUND" * 16)(%[dst]) \n\t" // Generate a block of inline assembly that generates a single self-contained // encoder round: fetch the data, process it, and store the result. Then update // the source and destination pointers. #define ROUND() \ LOAD("a", 0) \ SHUF("a", "b") \ TRAN("a", "b", "c") \ STOR("a", 0) \ "add $12, %[src] \n\t" \ "add $16, %[dst] \n\t" // Define a macro that initiates a three-way interleaved encoding round by // preloading registers a, b and c from memory. // The register graph shows which registers are in use during each step, and // is a visual aid for choosing registers for that step. Symbol index: // // + indicates that a register is loaded by that step. // | indicates that a register is in use and must not be touched. // - indicates that a register is decommissioned by that step. // x indicates that a register is used as a temporary by that step. // V indicates that a register is an input or output to the macro. // #define ROUND_3_INIT() /* a b c d e f */ \ LOAD("a", 0) /* + */ \ SHUF("a", "d") /* | + */ \ LOAD("b", 1) /* | + | */ \ TRAN("a", "d", "e") /* | | - x */ \ LOAD("c", 2) /* V V V */ // Define a macro that translates, shuffles and stores the input registers A, B // and C, and preloads registers D, E and F for the next round. // This macro can be arbitrarily daisy-chained by feeding output registers D, E // and F back into the next round as input registers A, B and C. The macro // carefully interleaves memory operations with data operations for optimal // pipelined performance. #define ROUND_3(ROUND, A,B,C,D,E,F) /* A B C D E F */ \ LOAD(D, (ROUND + 3)) /* V V V + */ \ SHUF(B, E) /* | | | | + */ \ STOR(A, (ROUND + 0)) /* - | | | | */ \ TRAN(B, E, F) /* | | | - x */ \ LOAD(E, (ROUND + 4)) /* | | | + */ \ SHUF(C, A) /* + | | | | */ \ STOR(B, (ROUND + 1)) /* | - | | | */ \ TRAN(C, A, F) /* - | | | x */ \ LOAD(F, (ROUND + 5)) /* | | | + */ \ SHUF(D, A) /* + | | | | */ \ STOR(C, (ROUND + 2)) /* | - | | | */ \ TRAN(D, A, B) /* - x V V V */ // Define a macro that terminates a ROUND_3 macro by taking pre-loaded // registers D, E and F, and translating, shuffling and storing them. #define ROUND_3_END(ROUND, A,B,C,D,E,F) /* A B C D E F */ \ SHUF(E, A) /* + V V V */ \ STOR(D, (ROUND + 3)) /* | - | | */ \ TRAN(E, A, B) /* - x | | */ \ SHUF(F, C) /* + | | */ \ STOR(E, (ROUND + 4)) /* | - | */ \ TRAN(F, C, D) /* - x | */ \ STOR(F, (ROUND + 5)) /* - */ // Define a type A round. Inputs are a, b, and c, outputs are d, e, and f. #define ROUND_3_A(ROUND) \ ROUND_3(ROUND, "a", "b", "c", "d", "e", "f") // Define a type B round. Inputs and outputs are swapped with regard to type A. #define ROUND_3_B(ROUND) \ ROUND_3(ROUND, "d", "e", "f", "a", "b", "c") // Terminating macro for a type A round. #define ROUND_3_A_LAST(ROUND) \ ROUND_3_A(ROUND) \ ROUND_3_END(ROUND, "a", "b", "c", "d", "e", "f") // Terminating macro for a type B round. #define ROUND_3_B_LAST(ROUND) \ ROUND_3_B(ROUND) \ ROUND_3_END(ROUND, "d", "e", "f", "a", "b", "c") // Suppress clang's warning that the literal string in the asm statement is // overlong (longer than the ISO-mandated minimum size of 4095 bytes for C99 // compilers). It may be true, but the goal here is not C99 portability. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverlength-strings" static inline void enc_loop_ssse3 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { // For a clearer explanation of the algorithm used by this function, // please refer to the plain (not inline assembly) implementation. This // function follows the same basic logic. if (*slen < 16) { return; } // Process blocks of 12 bytes at a time. Input is read in blocks of 16 // bytes, so "reserve" four bytes from the input buffer to ensure that // we never read beyond the end of the input buffer. size_t rounds = (*slen - 4) / 12; *slen -= rounds * 12; // 12 bytes consumed per round *olen += rounds * 16; // 16 bytes produced per round // Number of times to go through the 36x loop. size_t loops = rounds / 36; // Number of rounds remaining after the 36x loop. rounds %= 36; // Lookup tables. const __m128i lut0 = _mm_set_epi8( 10, 11, 9, 10, 7, 8, 6, 7, 4, 5, 3, 4, 1, 2, 0, 1); const __m128i lut1 = _mm_setr_epi8( 65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0); // Temporary registers. __m128i a, b, c, d, e, f; __asm__ volatile ( // If there are 36 rounds or more, enter a 36x unrolled loop of // interleaved encoding rounds. The rounds interleave memory // operations (load/store) with data operations (table lookups, // etc) to maximize pipeline throughput. " test %[loops], %[loops] \n\t" " jz 18f \n\t" " jmp 36f \n\t" " \n\t" ".balign 64 \n\t" "36: " ROUND_3_INIT() " " ROUND_3_A( 0) " " ROUND_3_B( 3) " " ROUND_3_A( 6) " " ROUND_3_B( 9) " " ROUND_3_A(12) " " ROUND_3_B(15) " " ROUND_3_A(18) " " ROUND_3_B(21) " " ROUND_3_A(24) " " ROUND_3_B(27) " " ROUND_3_A_LAST(30) " add $(12 * 36), %[src] \n\t" " add $(16 * 36), %[dst] \n\t" " dec %[loops] \n\t" " jnz 36b \n\t" // Enter an 18x unrolled loop for rounds of 18 or more. "18: cmp $18, %[rounds] \n\t" " jl 9f \n\t" " " ROUND_3_INIT() " " ROUND_3_A(0) " " ROUND_3_B(3) " " ROUND_3_A(6) " " ROUND_3_B(9) " " ROUND_3_A_LAST(12) " sub $18, %[rounds] \n\t" " add $(12 * 18), %[src] \n\t" " add $(16 * 18), %[dst] \n\t" // Enter a 9x unrolled loop for rounds of 9 or more. "9: cmp $9, %[rounds] \n\t" " jl 6f \n\t" " " ROUND_3_INIT() " " ROUND_3_A(0) " " ROUND_3_B_LAST(3) " sub $9, %[rounds] \n\t" " add $(12 * 9), %[src] \n\t" " add $(16 * 9), %[dst] \n\t" // Enter a 6x unrolled loop for rounds of 6 or more. "6: cmp $6, %[rounds] \n\t" " jl 55f \n\t" " " ROUND_3_INIT() " " ROUND_3_A_LAST(0) " sub $6, %[rounds] \n\t" " add $(12 * 6), %[src] \n\t" " add $(16 * 6), %[dst] \n\t" // Dispatch the remaining rounds 0..5. "55: cmp $3, %[rounds] \n\t" " jg 45f \n\t" " je 3f \n\t" " cmp $1, %[rounds] \n\t" " jg 2f \n\t" " je 1f \n\t" " jmp 0f \n\t" "45: cmp $4, %[rounds] \n\t" " je 4f \n\t" // Block of non-interlaced encoding rounds, which can each // individually be jumped to. Rounds fall through to the next. "5: " ROUND() "4: " ROUND() "3: " ROUND() "2: " ROUND() "1: " ROUND() "0: \n\t" // Outputs (modified). : [rounds] "+r" (rounds), [loops] "+r" (loops), [src] "+r" (*s), [dst] "+r" (*o), [a] "=&x" (a), [b] "=&x" (b), [c] "=&x" (c), [d] "=&x" (d), [e] "=&x" (e), [f] "=&x" (f) // Inputs (not modified). : [lut0] "x" (lut0), [lut1] "x" (lut1), [msk0] "x" (_mm_set1_epi32(0x0FC0FC00)), [msk1] "x" (_mm_set1_epi32(0x04000040)), [msk2] "x" (_mm_set1_epi32(0x003F03F0)), [msk3] "x" (_mm_set1_epi32(0x01000010)), [n51] "x" (_mm_set1_epi8(51)), [n25] "x" (_mm_set1_epi8(25)) // Clobbers. : "cc", "memory" ); } #pragma GCC diagnostic pop pybase64-1.4.3/base64/lib/arch/ssse3/enc_reshuffle.c000066400000000000000000000027521500645130400217430ustar00rootroot00000000000000static BASE64_FORCE_INLINE __m128i enc_reshuffle (__m128i in) { // Input, bytes MSB to LSB: // 0 0 0 0 l k j i h g f e d c b a in = _mm_shuffle_epi8(in, _mm_set_epi8( 10, 11, 9, 10, 7, 8, 6, 7, 4, 5, 3, 4, 1, 2, 0, 1)); // in, bytes MSB to LSB: // k l j k // h i g h // e f d e // b c a b const __m128i t0 = _mm_and_si128(in, _mm_set1_epi32(0x0FC0FC00)); // bits, upper case are most significant bits, lower case are least significant bits // 0000kkkk LL000000 JJJJJJ00 00000000 // 0000hhhh II000000 GGGGGG00 00000000 // 0000eeee FF000000 DDDDDD00 00000000 // 0000bbbb CC000000 AAAAAA00 00000000 const __m128i t1 = _mm_mulhi_epu16(t0, _mm_set1_epi32(0x04000040)); // 00000000 00kkkkLL 00000000 00JJJJJJ // 00000000 00hhhhII 00000000 00GGGGGG // 00000000 00eeeeFF 00000000 00DDDDDD // 00000000 00bbbbCC 00000000 00AAAAAA const __m128i t2 = _mm_and_si128(in, _mm_set1_epi32(0x003F03F0)); // 00000000 00llllll 000000jj KKKK0000 // 00000000 00iiiiii 000000gg HHHH0000 // 00000000 00ffffff 000000dd EEEE0000 // 00000000 00cccccc 000000aa BBBB0000 const __m128i t3 = _mm_mullo_epi16(t2, _mm_set1_epi32(0x01000010)); // 00llllll 00000000 00jjKKKK 00000000 // 00iiiiii 00000000 00ggHHHH 00000000 // 00ffffff 00000000 00ddEEEE 00000000 // 00cccccc 00000000 00aaBBBB 00000000 return _mm_or_si128(t1, t3); // 00llllll 00kkkkLL 00jjKKKK 00JJJJJJ // 00iiiiii 00hhhhII 00ggHHHH 00GGGGGG // 00ffffff 00eeeeFF 00ddEEEE 00DDDDDD // 00cccccc 00bbbbCC 00aaBBBB 00AAAAAA } pybase64-1.4.3/base64/lib/arch/ssse3/enc_translate.c000066400000000000000000000022231500645130400217460ustar00rootroot00000000000000static BASE64_FORCE_INLINE __m128i enc_translate (const __m128i in) { // A lookup table containing the absolute offsets for all ranges: const __m128i lut = _mm_setr_epi8( 65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0 ); // Translate values 0..63 to the Base64 alphabet. There are five sets: // # From To Abs Index Characters // 0 [0..25] [65..90] +65 0 ABCDEFGHIJKLMNOPQRSTUVWXYZ // 1 [26..51] [97..122] +71 1 abcdefghijklmnopqrstuvwxyz // 2 [52..61] [48..57] -4 [2..11] 0123456789 // 3 [62] [43] -19 12 + // 4 [63] [47] -16 13 / // Create LUT indices from the input. The index for range #0 is right, // others are 1 less than expected: __m128i indices = _mm_subs_epu8(in, _mm_set1_epi8(51)); // mask is 0xFF (-1) for range #[1..4] and 0x00 for range #0: __m128i mask = _mm_cmpgt_epi8(in, _mm_set1_epi8(25)); // Subtract -1, so add 1 to indices for range #[1..4]. All indices are // now correct: indices = _mm_sub_epi8(indices, mask); // Add offsets to input values: return _mm_add_epi8(in, _mm_shuffle_epi8(lut, indices)); } pybase64-1.4.3/base64/lib/codec_choose.c000066400000000000000000000166611500645130400175770ustar00rootroot00000000000000#include #include #include #include #include #include "../include/libbase64.h" #include "codecs.h" #include "config.h" #include "env.h" #if (__x86_64__ || __i386__ || _M_X86 || _M_X64) #define BASE64_X86 #if (HAVE_SSSE3 || HAVE_SSE41 || HAVE_SSE42 || HAVE_AVX || HAVE_AVX2 || HAVE_AVX512) #define BASE64_X86_SIMD #endif #endif #ifdef BASE64_X86 #ifdef _MSC_VER #include #define __cpuid_count(__level, __count, __eax, __ebx, __ecx, __edx) \ { \ int info[4]; \ __cpuidex(info, __level, __count); \ __eax = info[0]; \ __ebx = info[1]; \ __ecx = info[2]; \ __edx = info[3]; \ } #define __cpuid(__level, __eax, __ebx, __ecx, __edx) \ __cpuid_count(__level, 0, __eax, __ebx, __ecx, __edx) #else #include #if HAVE_AVX512 || HAVE_AVX2 || HAVE_AVX #if ((__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 2) || (__clang_major__ >= 3)) static inline uint64_t _xgetbv (uint32_t index) { uint32_t eax, edx; __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index)); return ((uint64_t)edx << 32) | eax; } #else #error "Platform not supported" #endif #endif #endif #ifndef bit_AVX512vl #define bit_AVX512vl (1 << 31) #endif #ifndef bit_AVX512vbmi #define bit_AVX512vbmi (1 << 1) #endif #ifndef bit_AVX2 #define bit_AVX2 (1 << 5) #endif #ifndef bit_SSSE3 #define bit_SSSE3 (1 << 9) #endif #ifndef bit_SSE41 #define bit_SSE41 (1 << 19) #endif #ifndef bit_SSE42 #define bit_SSE42 (1 << 20) #endif #ifndef bit_AVX #define bit_AVX (1 << 28) #endif #define bit_XSAVE_XRSTORE (1 << 27) #ifndef _XCR_XFEATURE_ENABLED_MASK #define _XCR_XFEATURE_ENABLED_MASK 0 #endif #define bit_XMM (1 << 1) #define bit_YMM (1 << 2) #define bit_OPMASK (1 << 5) #define bit_ZMM (1 << 6) #define bit_HIGH_ZMM (1 << 7) #define _XCR_XMM_AND_YMM_STATE_ENABLED_BY_OS (bit_XMM | bit_YMM) #define _AVX_512_ENABLED_BY_OS (bit_XMM | bit_YMM | bit_OPMASK | bit_ZMM | bit_HIGH_ZMM) #endif // Function declarations: #define BASE64_CODEC_FUNCS(arch) \ extern void base64_stream_encode_ ## arch BASE64_ENC_PARAMS; \ extern int base64_stream_decode_ ## arch BASE64_DEC_PARAMS; BASE64_CODEC_FUNCS(avx512) BASE64_CODEC_FUNCS(avx2) BASE64_CODEC_FUNCS(neon32) BASE64_CODEC_FUNCS(neon64) BASE64_CODEC_FUNCS(plain) BASE64_CODEC_FUNCS(ssse3) BASE64_CODEC_FUNCS(sse41) BASE64_CODEC_FUNCS(sse42) BASE64_CODEC_FUNCS(avx) static bool codec_choose_forced (struct codec *codec, int flags) { // If the user wants to use a certain codec, // always allow it, even if the codec is a no-op. // For testing purposes. if (!(flags & 0xFFFF)) { return false; } if (flags & BASE64_FORCE_AVX2) { codec->enc = base64_stream_encode_avx2; codec->dec = base64_stream_decode_avx2; return true; } if (flags & BASE64_FORCE_NEON32) { codec->enc = base64_stream_encode_neon32; codec->dec = base64_stream_decode_neon32; return true; } if (flags & BASE64_FORCE_NEON64) { codec->enc = base64_stream_encode_neon64; codec->dec = base64_stream_decode_neon64; return true; } if (flags & BASE64_FORCE_PLAIN) { codec->enc = base64_stream_encode_plain; codec->dec = base64_stream_decode_plain; return true; } if (flags & BASE64_FORCE_SSSE3) { codec->enc = base64_stream_encode_ssse3; codec->dec = base64_stream_decode_ssse3; return true; } if (flags & BASE64_FORCE_SSE41) { codec->enc = base64_stream_encode_sse41; codec->dec = base64_stream_decode_sse41; return true; } if (flags & BASE64_FORCE_SSE42) { codec->enc = base64_stream_encode_sse42; codec->dec = base64_stream_decode_sse42; return true; } if (flags & BASE64_FORCE_AVX) { codec->enc = base64_stream_encode_avx; codec->dec = base64_stream_decode_avx; return true; } if (flags & BASE64_FORCE_AVX512) { codec->enc = base64_stream_encode_avx512; codec->dec = base64_stream_decode_avx512; return true; } return false; } static bool codec_choose_arm (struct codec *codec) { #if HAVE_NEON64 || ((defined(__ARM_NEON__) || defined(__ARM_NEON)) && HAVE_NEON32) // Unfortunately there is no portable way to check for NEON // support at runtime from userland in the same way that x86 // has cpuid, so just stick to the compile-time configuration: #if HAVE_NEON64 codec->enc = base64_stream_encode_neon64; codec->dec = base64_stream_decode_neon64; #else codec->enc = base64_stream_encode_neon32; codec->dec = base64_stream_decode_neon32; #endif return true; #else (void)codec; return false; #endif } static bool codec_choose_x86 (struct codec *codec) { #ifdef BASE64_X86_SIMD unsigned int eax, ebx = 0, ecx = 0, edx; unsigned int max_level; #ifdef _MSC_VER int info[4]; __cpuidex(info, 0, 0); max_level = info[0]; #else max_level = __get_cpuid_max(0, NULL); #endif #if HAVE_AVX512 || HAVE_AVX2 || HAVE_AVX // Check for AVX/AVX2/AVX512 support: // Checking for AVX requires 3 things: // 1) CPUID indicates that the OS uses XSAVE and XRSTORE instructions // (allowing saving YMM registers on context switch) // 2) CPUID indicates support for AVX // 3) XGETBV indicates the AVX registers will be saved and restored on // context switch // // Note that XGETBV is only available on 686 or later CPUs, so the // instruction needs to be conditionally run. if (max_level >= 1) { __cpuid_count(1, 0, eax, ebx, ecx, edx); if (ecx & bit_XSAVE_XRSTORE) { uint64_t xcr_mask; xcr_mask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); if ((xcr_mask & _XCR_XMM_AND_YMM_STATE_ENABLED_BY_OS) == _XCR_XMM_AND_YMM_STATE_ENABLED_BY_OS) { // check multiple bits at once #if HAVE_AVX512 if (max_level >= 7 && ((xcr_mask & _AVX_512_ENABLED_BY_OS) == _AVX_512_ENABLED_BY_OS)) { __cpuid_count(7, 0, eax, ebx, ecx, edx); if ((ebx & bit_AVX512vl) && (ecx & bit_AVX512vbmi)) { codec->enc = base64_stream_encode_avx512; codec->dec = base64_stream_decode_avx512; return true; } } #endif #if HAVE_AVX2 if (max_level >= 7) { __cpuid_count(7, 0, eax, ebx, ecx, edx); if (ebx & bit_AVX2) { codec->enc = base64_stream_encode_avx2; codec->dec = base64_stream_decode_avx2; return true; } } #endif #if HAVE_AVX __cpuid_count(1, 0, eax, ebx, ecx, edx); if (ecx & bit_AVX) { codec->enc = base64_stream_encode_avx; codec->dec = base64_stream_decode_avx; return true; } #endif } } } #endif #if HAVE_SSE42 // Check for SSE42 support: if (max_level >= 1) { __cpuid(1, eax, ebx, ecx, edx); if (ecx & bit_SSE42) { codec->enc = base64_stream_encode_sse42; codec->dec = base64_stream_decode_sse42; return true; } } #endif #if HAVE_SSE41 // Check for SSE41 support: if (max_level >= 1) { __cpuid(1, eax, ebx, ecx, edx); if (ecx & bit_SSE41) { codec->enc = base64_stream_encode_sse41; codec->dec = base64_stream_decode_sse41; return true; } } #endif #if HAVE_SSSE3 // Check for SSSE3 support: if (max_level >= 1) { __cpuid(1, eax, ebx, ecx, edx); if (ecx & bit_SSSE3) { codec->enc = base64_stream_encode_ssse3; codec->dec = base64_stream_decode_ssse3; return true; } } #endif #else (void)codec; #endif return false; } void codec_choose (struct codec *codec, int flags) { // User forced a codec: if (codec_choose_forced(codec, flags)) { return; } // Runtime feature detection: if (codec_choose_arm(codec)) { return; } if (codec_choose_x86(codec)) { return; } codec->enc = base64_stream_encode_plain; codec->dec = base64_stream_decode_plain; } pybase64-1.4.3/base64/lib/codecs.h000066400000000000000000000022571500645130400164230ustar00rootroot00000000000000#include "../include/libbase64.h" // Function parameters for encoding functions: #define BASE64_ENC_PARAMS \ ( struct base64_state *state \ , const char *src \ , size_t srclen \ , char *out \ , size_t *outlen \ ) // Function parameters for decoding functions: #define BASE64_DEC_PARAMS \ ( struct base64_state *state \ , const char *src \ , size_t srclen \ , char *out \ , size_t *outlen \ ) // This function is used as a stub when a certain encoder is not compiled in. // It discards the inputs and returns zero output bytes. static inline void base64_enc_stub BASE64_ENC_PARAMS { (void) state; (void) src; (void) srclen; (void) out; *outlen = 0; } // This function is used as a stub when a certain decoder is not compiled in. // It discards the inputs and returns an invalid decoding result. static inline int base64_dec_stub BASE64_DEC_PARAMS { (void) state; (void) src; (void) srclen; (void) out; (void) outlen; return -1; } typedef void (* base64_enc_fn) BASE64_ENC_PARAMS; typedef int (* base64_dec_fn) BASE64_DEC_PARAMS; struct codec { base64_enc_fn enc; base64_dec_fn dec; }; extern void codec_choose (struct codec *, int flags); pybase64-1.4.3/base64/lib/env.h000066400000000000000000000046251500645130400157540ustar00rootroot00000000000000#ifndef BASE64_ENV_H #define BASE64_ENV_H #include // This header file contains macro definitions that describe certain aspects of // the compile-time environment. Compatibility and portability macros go here. // Define machine endianness. This is for GCC: #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) # define BASE64_LITTLE_ENDIAN 1 #else # define BASE64_LITTLE_ENDIAN 0 #endif // This is for Clang: #ifdef __LITTLE_ENDIAN__ # define BASE64_LITTLE_ENDIAN 1 #endif #ifdef __BIG_ENDIAN__ # define BASE64_LITTLE_ENDIAN 0 #endif // MSVC++ needs intrin.h for _byteswap_uint64 (issue #68): #if BASE64_LITTLE_ENDIAN && defined(_MSC_VER) # include #endif // Endian conversion functions: #if BASE64_LITTLE_ENDIAN # ifdef _MSC_VER // Microsoft Visual C++: # define BASE64_HTOBE32(x) _byteswap_ulong(x) # define BASE64_HTOBE64(x) _byteswap_uint64(x) # else // GCC and Clang: # define BASE64_HTOBE32(x) __builtin_bswap32(x) # define BASE64_HTOBE64(x) __builtin_bswap64(x) # endif #else // No conversion needed: # define BASE64_HTOBE32(x) (x) # define BASE64_HTOBE64(x) (x) #endif // Detect word size: #if defined (__x86_64__) // This also works for the x32 ABI, which has a 64-bit word size. # define BASE64_WORDSIZE 64 #elif SIZE_MAX == UINT32_MAX # define BASE64_WORDSIZE 32 #elif SIZE_MAX == UINT64_MAX # define BASE64_WORDSIZE 64 #else # error BASE64_WORDSIZE_NOT_DEFINED #endif // End-of-file definitions. // Almost end-of-file when waiting for the last '=' character: #define BASE64_AEOF 1 // End-of-file when stream end has been reached or invalid input provided: #define BASE64_EOF 2 // GCC 7 defaults to issuing a warning for fallthrough in switch statements, // unless the fallthrough cases are marked with an attribute. As we use // fallthrough deliberately, define an alias for the attribute: #if __GNUC__ >= 7 # define BASE64_FALLTHROUGH __attribute__((fallthrough)); #else # define BASE64_FALLTHROUGH #endif // Declare macros to ensure that functions that are intended to be inlined, are // actually inlined, even when no optimization is applied. A lot of inner loop // code is factored into separate functions for reasons of readability, but // that code should always be inlined (and optimized) in the main loop. #ifdef _MSC_VER # define BASE64_FORCE_INLINE __forceinline #else # define BASE64_FORCE_INLINE inline __attribute__((always_inline)) #endif #endif // BASE64_ENV_H pybase64-1.4.3/base64/lib/exports.txt000066400000000000000000000002251500645130400172500ustar00rootroot00000000000000base64_encode base64_stream_encode base64_stream_encode_init base64_stream_encode_final base64_decode base64_stream_decode base64_stream_decode_init pybase64-1.4.3/base64/lib/lib.c000066400000000000000000000063211500645130400157200ustar00rootroot00000000000000#include #include #ifdef _OPENMP #include #endif #include "../include/libbase64.h" #include "tables/tables.h" #include "codecs.h" #include "env.h" // These static function pointers are initialized once when the library is // first used, and remain in use for the remaining lifetime of the program. // The idea being that CPU features don't change at runtime. static struct codec codec = { NULL, NULL }; void base64_stream_encode_init (struct base64_state *state, int flags) { // If any of the codec flags are set, redo choice: if (codec.enc == NULL || flags & 0xFF) { codec_choose(&codec, flags); } state->eof = 0; state->bytes = 0; state->carry = 0; state->flags = flags; } void base64_stream_encode ( struct base64_state *state , const char *src , size_t srclen , char *out , size_t *outlen ) { codec.enc(state, src, srclen, out, outlen); } void base64_stream_encode_final ( struct base64_state *state , char *out , size_t *outlen ) { uint8_t *o = (uint8_t *)out; if (state->bytes == 1) { *o++ = base64_table_enc_6bit[state->carry]; *o++ = '='; *o++ = '='; *outlen = 3; return; } if (state->bytes == 2) { *o++ = base64_table_enc_6bit[state->carry]; *o++ = '='; *outlen = 2; return; } *outlen = 0; } void base64_stream_decode_init (struct base64_state *state, int flags) { // If any of the codec flags are set, redo choice: if (codec.dec == NULL || flags & 0xFFFF) { codec_choose(&codec, flags); } state->eof = 0; state->bytes = 0; state->carry = 0; state->flags = flags; } int base64_stream_decode ( struct base64_state *state , const char *src , size_t srclen , char *out , size_t *outlen ) { return codec.dec(state, src, srclen, out, outlen); } #ifdef _OPENMP // Due to the overhead of initializing OpenMP and creating a team of // threads, we require the data length to be larger than a threshold: #define OMP_THRESHOLD 20000 // Conditionally include OpenMP-accelerated codec implementations: #include "lib_openmp.c" #endif void base64_encode ( const char *src , size_t srclen , char *out , size_t *outlen , int flags ) { size_t s; size_t t; struct base64_state state; #ifdef _OPENMP if (srclen >= OMP_THRESHOLD) { base64_encode_openmp(src, srclen, out, outlen, flags); return; } #endif // Init the stream reader: base64_stream_encode_init(&state, flags); // Feed the whole string to the stream reader: base64_stream_encode(&state, src, srclen, out, &s); // Finalize the stream by writing trailer if any: base64_stream_encode_final(&state, out + s, &t); // Final output length is stream length plus tail: *outlen = s + t; } int base64_decode ( const char *src , size_t srclen , char *out , size_t *outlen , int flags ) { int ret; struct base64_state state; #ifdef _OPENMP if (srclen >= OMP_THRESHOLD) { return base64_decode_openmp(src, srclen, out, outlen, flags); } #endif // Init the stream reader: base64_stream_decode_init(&state, flags); // Feed the whole string to the stream reader: ret = base64_stream_decode(&state, src, srclen, out, outlen); // If when decoding a whole block, we're still waiting for input then fail: if (ret && (state.bytes == 0)) { return ret; } return 0; } pybase64-1.4.3/base64/lib/lib_openmp.c000066400000000000000000000105511500645130400172760ustar00rootroot00000000000000// This code makes some assumptions on the implementation of // base64_stream_encode_init(), base64_stream_encode() and base64_stream_decode(). // Basically these assumptions boil down to that when breaking the src into // parts, out parts can be written without side effects. // This is met when: // 1) base64_stream_encode() and base64_stream_decode() don't use globals; // 2) the shared variables src and out are not read or written outside of the // bounds of their parts, i.e. when base64_stream_encode() reads a multiple // of 3 bytes, it must write no more then a multiple of 4 bytes, not even // temporarily; // 3) the state flag can be discarded after base64_stream_encode() and // base64_stream_decode() on the parts. static inline void base64_encode_openmp ( const char *src , size_t srclen , char *out , size_t *outlen , int flags ) { size_t s; size_t t; size_t sum = 0, len, last_len; struct base64_state state, initial_state; int num_threads, i; // Request a number of threads but not necessarily get them: #pragma omp parallel { // Get the number of threads used from one thread only, // as num_threads is a shared var: #pragma omp single { num_threads = omp_get_num_threads(); // Split the input string into num_threads parts, each // part a multiple of 3 bytes. The remaining bytes will // be done later: len = srclen / (num_threads * 3); len *= 3; last_len = srclen - num_threads * len; // Init the stream reader: base64_stream_encode_init(&state, flags); initial_state = state; } // Single has an implicit barrier for all threads to wait here // for the above to complete: #pragma omp for firstprivate(state) private(s) reduction(+:sum) schedule(static,1) for (i = 0; i < num_threads; i++) { // Feed each part of the string to the stream reader: base64_stream_encode(&state, src + i * len, len, out + i * len * 4 / 3, &s); sum += s; } } // As encoding should never fail and we encode an exact multiple // of 3 bytes, we can discard state: state = initial_state; // Encode the remaining bytes: base64_stream_encode(&state, src + num_threads * len, last_len, out + num_threads * len * 4 / 3, &s); // Finalize the stream by writing trailer if any: base64_stream_encode_final(&state, out + num_threads * len * 4 / 3 + s, &t); // Final output length is stream length plus tail: sum += s + t; *outlen = sum; } static inline int base64_decode_openmp ( const char *src , size_t srclen , char *out , size_t *outlen , int flags ) { int num_threads, result = 0, i; size_t sum = 0, len, last_len, s; struct base64_state state, initial_state; // Request a number of threads but not necessarily get them: #pragma omp parallel { // Get the number of threads used from one thread only, // as num_threads is a shared var: #pragma omp single { num_threads = omp_get_num_threads(); // Split the input string into num_threads parts, each // part a multiple of 4 bytes. The remaining bytes will // be done later: len = srclen / (num_threads * 4); len *= 4; last_len = srclen - num_threads * len; // Init the stream reader: base64_stream_decode_init(&state, flags); initial_state = state; } // Single has an implicit barrier to wait here for the above to // complete: #pragma omp for firstprivate(state) private(s) reduction(+:sum, result) schedule(static,1) for (i = 0; i < num_threads; i++) { int this_result; // Feed each part of the string to the stream reader: this_result = base64_stream_decode(&state, src + i * len, len, out + i * len * 3 / 4, &s); sum += s; result += this_result; } } // If `result' equals `-num_threads', then all threads returned -1, // indicating that the requested codec is not available: if (result == -num_threads) { return -1; } // If `result' does not equal `num_threads', then at least one of the // threads hit a decode error: if (result != num_threads) { return 0; } // So far so good, now decode whatever remains in the buffer. Reuse the // initial state, since we are at a 4-byte boundary: state = initial_state; result = base64_stream_decode(&state, src + num_threads * len, last_len, out + num_threads * len * 3 / 4, &s); sum += s; *outlen = sum; // If when decoding a whole block, we're still waiting for input then fail: if (result && (state.bytes == 0)) { return result; } return 0; } pybase64-1.4.3/base64/lib/tables/000077500000000000000000000000001500645130400162565ustar00rootroot00000000000000pybase64-1.4.3/base64/lib/tables/.gitignore000066400000000000000000000000201500645130400202360ustar00rootroot00000000000000table_generator pybase64-1.4.3/base64/lib/tables/Makefile000066400000000000000000000004341500645130400177170ustar00rootroot00000000000000.PHONY: all clean TARGETS := table_dec_32bit.h table_enc_12bit.h table_generator all: $(TARGETS) clean: $(RM) $(TARGETS) table_dec_32bit.h: table_generator ./$^ > $@ table_enc_12bit.h: table_enc_12bit.py ./$^ > $@ table_generator: table_generator.c $(CC) $(CFLAGS) -o $@ $^ pybase64-1.4.3/base64/lib/tables/table_dec_32bit.h000066400000000000000000000612521500645130400213420ustar00rootroot00000000000000#include #define CHAR62 '+' #define CHAR63 '/' #define CHARPAD '=' #if BASE64_LITTLE_ENDIAN /* SPECIAL DECODE TABLES FOR LITTLE ENDIAN (INTEL) CPUS */ const uint32_t base64_table_dec_32bit_d0[256] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000f8, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000fc, 0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4, 0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018, 0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030, 0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048, 0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060, 0x00000064, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078, 0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090, 0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8, 0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0, 0x000000c4, 0x000000c8, 0x000000cc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; const uint32_t base64_table_dec_32bit_d1[256] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000e003, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000f003, 0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003, 0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000, 0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000, 0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001, 0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001, 0x00009001, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001, 0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002, 0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002, 0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003, 0x00001003, 0x00002003, 0x00003003, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; const uint32_t base64_table_dec_32bit_d2[256] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00800f00, 0xffffffff, 0xffffffff, 0xffffffff, 0x00c00f00, 0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00, 0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100, 0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300, 0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400, 0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600, 0x00400600, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700, 0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900, 0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00, 0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00, 0x00400c00, 0x00800c00, 0x00c00c00, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; const uint32_t base64_table_dec_32bit_d3[256] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x003e0000, 0xffffffff, 0xffffffff, 0xffffffff, 0x003f0000, 0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000, 0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000, 0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000, 0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000, 0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000, 0x00190000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000, 0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000, 0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000, 0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000, 0x00310000, 0x00320000, 0x00330000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; #else /* SPECIAL DECODE TABLES FOR BIG ENDIAN (IBM/MOTOROLA/SUN) CPUS */ const uint32_t base64_table_dec_32bit_d0[256] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf8000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfc000000, 0xd0000000, 0xd4000000, 0xd8000000, 0xdc000000, 0xe0000000, 0xe4000000, 0xe8000000, 0xec000000, 0xf0000000, 0xf4000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x04000000, 0x08000000, 0x0c000000, 0x10000000, 0x14000000, 0x18000000, 0x1c000000, 0x20000000, 0x24000000, 0x28000000, 0x2c000000, 0x30000000, 0x34000000, 0x38000000, 0x3c000000, 0x40000000, 0x44000000, 0x48000000, 0x4c000000, 0x50000000, 0x54000000, 0x58000000, 0x5c000000, 0x60000000, 0x64000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x68000000, 0x6c000000, 0x70000000, 0x74000000, 0x78000000, 0x7c000000, 0x80000000, 0x84000000, 0x88000000, 0x8c000000, 0x90000000, 0x94000000, 0x98000000, 0x9c000000, 0xa0000000, 0xa4000000, 0xa8000000, 0xac000000, 0xb0000000, 0xb4000000, 0xb8000000, 0xbc000000, 0xc0000000, 0xc4000000, 0xc8000000, 0xcc000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; const uint32_t base64_table_dec_32bit_d1[256] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03e00000, 0xffffffff, 0xffffffff, 0xffffffff, 0x03f00000, 0x03400000, 0x03500000, 0x03600000, 0x03700000, 0x03800000, 0x03900000, 0x03a00000, 0x03b00000, 0x03c00000, 0x03d00000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00100000, 0x00200000, 0x00300000, 0x00400000, 0x00500000, 0x00600000, 0x00700000, 0x00800000, 0x00900000, 0x00a00000, 0x00b00000, 0x00c00000, 0x00d00000, 0x00e00000, 0x00f00000, 0x01000000, 0x01100000, 0x01200000, 0x01300000, 0x01400000, 0x01500000, 0x01600000, 0x01700000, 0x01800000, 0x01900000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01a00000, 0x01b00000, 0x01c00000, 0x01d00000, 0x01e00000, 0x01f00000, 0x02000000, 0x02100000, 0x02200000, 0x02300000, 0x02400000, 0x02500000, 0x02600000, 0x02700000, 0x02800000, 0x02900000, 0x02a00000, 0x02b00000, 0x02c00000, 0x02d00000, 0x02e00000, 0x02f00000, 0x03000000, 0x03100000, 0x03200000, 0x03300000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; const uint32_t base64_table_dec_32bit_d2[256] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000f8000, 0xffffffff, 0xffffffff, 0xffffffff, 0x000fc000, 0x000d0000, 0x000d4000, 0x000d8000, 0x000dc000, 0x000e0000, 0x000e4000, 0x000e8000, 0x000ec000, 0x000f0000, 0x000f4000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00004000, 0x00008000, 0x0000c000, 0x00010000, 0x00014000, 0x00018000, 0x0001c000, 0x00020000, 0x00024000, 0x00028000, 0x0002c000, 0x00030000, 0x00034000, 0x00038000, 0x0003c000, 0x00040000, 0x00044000, 0x00048000, 0x0004c000, 0x00050000, 0x00054000, 0x00058000, 0x0005c000, 0x00060000, 0x00064000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00068000, 0x0006c000, 0x00070000, 0x00074000, 0x00078000, 0x0007c000, 0x00080000, 0x00084000, 0x00088000, 0x0008c000, 0x00090000, 0x00094000, 0x00098000, 0x0009c000, 0x000a0000, 0x000a4000, 0x000a8000, 0x000ac000, 0x000b0000, 0x000b4000, 0x000b8000, 0x000bc000, 0x000c0000, 0x000c4000, 0x000c8000, 0x000cc000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; const uint32_t base64_table_dec_32bit_d3[256] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00003e00, 0xffffffff, 0xffffffff, 0xffffffff, 0x00003f00, 0x00003400, 0x00003500, 0x00003600, 0x00003700, 0x00003800, 0x00003900, 0x00003a00, 0x00003b00, 0x00003c00, 0x00003d00, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000100, 0x00000200, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00000700, 0x00000800, 0x00000900, 0x00000a00, 0x00000b00, 0x00000c00, 0x00000d00, 0x00000e00, 0x00000f00, 0x00001000, 0x00001100, 0x00001200, 0x00001300, 0x00001400, 0x00001500, 0x00001600, 0x00001700, 0x00001800, 0x00001900, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00001a00, 0x00001b00, 0x00001c00, 0x00001d00, 0x00001e00, 0x00001f00, 0x00002000, 0x00002100, 0x00002200, 0x00002300, 0x00002400, 0x00002500, 0x00002600, 0x00002700, 0x00002800, 0x00002900, 0x00002a00, 0x00002b00, 0x00002c00, 0x00002d00, 0x00002e00, 0x00002f00, 0x00003000, 0x00003100, 0x00003200, 0x00003300, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; #endif pybase64-1.4.3/base64/lib/tables/table_enc_12bit.h000066400000000000000000002221521500645130400213500ustar00rootroot00000000000000#include const uint16_t base64_table_enc_12bit[] = { #if BASE64_LITTLE_ENDIAN 0x4141U, 0x4241U, 0x4341U, 0x4441U, 0x4541U, 0x4641U, 0x4741U, 0x4841U, 0x4941U, 0x4A41U, 0x4B41U, 0x4C41U, 0x4D41U, 0x4E41U, 0x4F41U, 0x5041U, 0x5141U, 0x5241U, 0x5341U, 0x5441U, 0x5541U, 0x5641U, 0x5741U, 0x5841U, 0x5941U, 0x5A41U, 0x6141U, 0x6241U, 0x6341U, 0x6441U, 0x6541U, 0x6641U, 0x6741U, 0x6841U, 0x6941U, 0x6A41U, 0x6B41U, 0x6C41U, 0x6D41U, 0x6E41U, 0x6F41U, 0x7041U, 0x7141U, 0x7241U, 0x7341U, 0x7441U, 0x7541U, 0x7641U, 0x7741U, 0x7841U, 0x7941U, 0x7A41U, 0x3041U, 0x3141U, 0x3241U, 0x3341U, 0x3441U, 0x3541U, 0x3641U, 0x3741U, 0x3841U, 0x3941U, 0x2B41U, 0x2F41U, 0x4142U, 0x4242U, 0x4342U, 0x4442U, 0x4542U, 0x4642U, 0x4742U, 0x4842U, 0x4942U, 0x4A42U, 0x4B42U, 0x4C42U, 0x4D42U, 0x4E42U, 0x4F42U, 0x5042U, 0x5142U, 0x5242U, 0x5342U, 0x5442U, 0x5542U, 0x5642U, 0x5742U, 0x5842U, 0x5942U, 0x5A42U, 0x6142U, 0x6242U, 0x6342U, 0x6442U, 0x6542U, 0x6642U, 0x6742U, 0x6842U, 0x6942U, 0x6A42U, 0x6B42U, 0x6C42U, 0x6D42U, 0x6E42U, 0x6F42U, 0x7042U, 0x7142U, 0x7242U, 0x7342U, 0x7442U, 0x7542U, 0x7642U, 0x7742U, 0x7842U, 0x7942U, 0x7A42U, 0x3042U, 0x3142U, 0x3242U, 0x3342U, 0x3442U, 0x3542U, 0x3642U, 0x3742U, 0x3842U, 0x3942U, 0x2B42U, 0x2F42U, 0x4143U, 0x4243U, 0x4343U, 0x4443U, 0x4543U, 0x4643U, 0x4743U, 0x4843U, 0x4943U, 0x4A43U, 0x4B43U, 0x4C43U, 0x4D43U, 0x4E43U, 0x4F43U, 0x5043U, 0x5143U, 0x5243U, 0x5343U, 0x5443U, 0x5543U, 0x5643U, 0x5743U, 0x5843U, 0x5943U, 0x5A43U, 0x6143U, 0x6243U, 0x6343U, 0x6443U, 0x6543U, 0x6643U, 0x6743U, 0x6843U, 0x6943U, 0x6A43U, 0x6B43U, 0x6C43U, 0x6D43U, 0x6E43U, 0x6F43U, 0x7043U, 0x7143U, 0x7243U, 0x7343U, 0x7443U, 0x7543U, 0x7643U, 0x7743U, 0x7843U, 0x7943U, 0x7A43U, 0x3043U, 0x3143U, 0x3243U, 0x3343U, 0x3443U, 0x3543U, 0x3643U, 0x3743U, 0x3843U, 0x3943U, 0x2B43U, 0x2F43U, 0x4144U, 0x4244U, 0x4344U, 0x4444U, 0x4544U, 0x4644U, 0x4744U, 0x4844U, 0x4944U, 0x4A44U, 0x4B44U, 0x4C44U, 0x4D44U, 0x4E44U, 0x4F44U, 0x5044U, 0x5144U, 0x5244U, 0x5344U, 0x5444U, 0x5544U, 0x5644U, 0x5744U, 0x5844U, 0x5944U, 0x5A44U, 0x6144U, 0x6244U, 0x6344U, 0x6444U, 0x6544U, 0x6644U, 0x6744U, 0x6844U, 0x6944U, 0x6A44U, 0x6B44U, 0x6C44U, 0x6D44U, 0x6E44U, 0x6F44U, 0x7044U, 0x7144U, 0x7244U, 0x7344U, 0x7444U, 0x7544U, 0x7644U, 0x7744U, 0x7844U, 0x7944U, 0x7A44U, 0x3044U, 0x3144U, 0x3244U, 0x3344U, 0x3444U, 0x3544U, 0x3644U, 0x3744U, 0x3844U, 0x3944U, 0x2B44U, 0x2F44U, 0x4145U, 0x4245U, 0x4345U, 0x4445U, 0x4545U, 0x4645U, 0x4745U, 0x4845U, 0x4945U, 0x4A45U, 0x4B45U, 0x4C45U, 0x4D45U, 0x4E45U, 0x4F45U, 0x5045U, 0x5145U, 0x5245U, 0x5345U, 0x5445U, 0x5545U, 0x5645U, 0x5745U, 0x5845U, 0x5945U, 0x5A45U, 0x6145U, 0x6245U, 0x6345U, 0x6445U, 0x6545U, 0x6645U, 0x6745U, 0x6845U, 0x6945U, 0x6A45U, 0x6B45U, 0x6C45U, 0x6D45U, 0x6E45U, 0x6F45U, 0x7045U, 0x7145U, 0x7245U, 0x7345U, 0x7445U, 0x7545U, 0x7645U, 0x7745U, 0x7845U, 0x7945U, 0x7A45U, 0x3045U, 0x3145U, 0x3245U, 0x3345U, 0x3445U, 0x3545U, 0x3645U, 0x3745U, 0x3845U, 0x3945U, 0x2B45U, 0x2F45U, 0x4146U, 0x4246U, 0x4346U, 0x4446U, 0x4546U, 0x4646U, 0x4746U, 0x4846U, 0x4946U, 0x4A46U, 0x4B46U, 0x4C46U, 0x4D46U, 0x4E46U, 0x4F46U, 0x5046U, 0x5146U, 0x5246U, 0x5346U, 0x5446U, 0x5546U, 0x5646U, 0x5746U, 0x5846U, 0x5946U, 0x5A46U, 0x6146U, 0x6246U, 0x6346U, 0x6446U, 0x6546U, 0x6646U, 0x6746U, 0x6846U, 0x6946U, 0x6A46U, 0x6B46U, 0x6C46U, 0x6D46U, 0x6E46U, 0x6F46U, 0x7046U, 0x7146U, 0x7246U, 0x7346U, 0x7446U, 0x7546U, 0x7646U, 0x7746U, 0x7846U, 0x7946U, 0x7A46U, 0x3046U, 0x3146U, 0x3246U, 0x3346U, 0x3446U, 0x3546U, 0x3646U, 0x3746U, 0x3846U, 0x3946U, 0x2B46U, 0x2F46U, 0x4147U, 0x4247U, 0x4347U, 0x4447U, 0x4547U, 0x4647U, 0x4747U, 0x4847U, 0x4947U, 0x4A47U, 0x4B47U, 0x4C47U, 0x4D47U, 0x4E47U, 0x4F47U, 0x5047U, 0x5147U, 0x5247U, 0x5347U, 0x5447U, 0x5547U, 0x5647U, 0x5747U, 0x5847U, 0x5947U, 0x5A47U, 0x6147U, 0x6247U, 0x6347U, 0x6447U, 0x6547U, 0x6647U, 0x6747U, 0x6847U, 0x6947U, 0x6A47U, 0x6B47U, 0x6C47U, 0x6D47U, 0x6E47U, 0x6F47U, 0x7047U, 0x7147U, 0x7247U, 0x7347U, 0x7447U, 0x7547U, 0x7647U, 0x7747U, 0x7847U, 0x7947U, 0x7A47U, 0x3047U, 0x3147U, 0x3247U, 0x3347U, 0x3447U, 0x3547U, 0x3647U, 0x3747U, 0x3847U, 0x3947U, 0x2B47U, 0x2F47U, 0x4148U, 0x4248U, 0x4348U, 0x4448U, 0x4548U, 0x4648U, 0x4748U, 0x4848U, 0x4948U, 0x4A48U, 0x4B48U, 0x4C48U, 0x4D48U, 0x4E48U, 0x4F48U, 0x5048U, 0x5148U, 0x5248U, 0x5348U, 0x5448U, 0x5548U, 0x5648U, 0x5748U, 0x5848U, 0x5948U, 0x5A48U, 0x6148U, 0x6248U, 0x6348U, 0x6448U, 0x6548U, 0x6648U, 0x6748U, 0x6848U, 0x6948U, 0x6A48U, 0x6B48U, 0x6C48U, 0x6D48U, 0x6E48U, 0x6F48U, 0x7048U, 0x7148U, 0x7248U, 0x7348U, 0x7448U, 0x7548U, 0x7648U, 0x7748U, 0x7848U, 0x7948U, 0x7A48U, 0x3048U, 0x3148U, 0x3248U, 0x3348U, 0x3448U, 0x3548U, 0x3648U, 0x3748U, 0x3848U, 0x3948U, 0x2B48U, 0x2F48U, 0x4149U, 0x4249U, 0x4349U, 0x4449U, 0x4549U, 0x4649U, 0x4749U, 0x4849U, 0x4949U, 0x4A49U, 0x4B49U, 0x4C49U, 0x4D49U, 0x4E49U, 0x4F49U, 0x5049U, 0x5149U, 0x5249U, 0x5349U, 0x5449U, 0x5549U, 0x5649U, 0x5749U, 0x5849U, 0x5949U, 0x5A49U, 0x6149U, 0x6249U, 0x6349U, 0x6449U, 0x6549U, 0x6649U, 0x6749U, 0x6849U, 0x6949U, 0x6A49U, 0x6B49U, 0x6C49U, 0x6D49U, 0x6E49U, 0x6F49U, 0x7049U, 0x7149U, 0x7249U, 0x7349U, 0x7449U, 0x7549U, 0x7649U, 0x7749U, 0x7849U, 0x7949U, 0x7A49U, 0x3049U, 0x3149U, 0x3249U, 0x3349U, 0x3449U, 0x3549U, 0x3649U, 0x3749U, 0x3849U, 0x3949U, 0x2B49U, 0x2F49U, 0x414AU, 0x424AU, 0x434AU, 0x444AU, 0x454AU, 0x464AU, 0x474AU, 0x484AU, 0x494AU, 0x4A4AU, 0x4B4AU, 0x4C4AU, 0x4D4AU, 0x4E4AU, 0x4F4AU, 0x504AU, 0x514AU, 0x524AU, 0x534AU, 0x544AU, 0x554AU, 0x564AU, 0x574AU, 0x584AU, 0x594AU, 0x5A4AU, 0x614AU, 0x624AU, 0x634AU, 0x644AU, 0x654AU, 0x664AU, 0x674AU, 0x684AU, 0x694AU, 0x6A4AU, 0x6B4AU, 0x6C4AU, 0x6D4AU, 0x6E4AU, 0x6F4AU, 0x704AU, 0x714AU, 0x724AU, 0x734AU, 0x744AU, 0x754AU, 0x764AU, 0x774AU, 0x784AU, 0x794AU, 0x7A4AU, 0x304AU, 0x314AU, 0x324AU, 0x334AU, 0x344AU, 0x354AU, 0x364AU, 0x374AU, 0x384AU, 0x394AU, 0x2B4AU, 0x2F4AU, 0x414BU, 0x424BU, 0x434BU, 0x444BU, 0x454BU, 0x464BU, 0x474BU, 0x484BU, 0x494BU, 0x4A4BU, 0x4B4BU, 0x4C4BU, 0x4D4BU, 0x4E4BU, 0x4F4BU, 0x504BU, 0x514BU, 0x524BU, 0x534BU, 0x544BU, 0x554BU, 0x564BU, 0x574BU, 0x584BU, 0x594BU, 0x5A4BU, 0x614BU, 0x624BU, 0x634BU, 0x644BU, 0x654BU, 0x664BU, 0x674BU, 0x684BU, 0x694BU, 0x6A4BU, 0x6B4BU, 0x6C4BU, 0x6D4BU, 0x6E4BU, 0x6F4BU, 0x704BU, 0x714BU, 0x724BU, 0x734BU, 0x744BU, 0x754BU, 0x764BU, 0x774BU, 0x784BU, 0x794BU, 0x7A4BU, 0x304BU, 0x314BU, 0x324BU, 0x334BU, 0x344BU, 0x354BU, 0x364BU, 0x374BU, 0x384BU, 0x394BU, 0x2B4BU, 0x2F4BU, 0x414CU, 0x424CU, 0x434CU, 0x444CU, 0x454CU, 0x464CU, 0x474CU, 0x484CU, 0x494CU, 0x4A4CU, 0x4B4CU, 0x4C4CU, 0x4D4CU, 0x4E4CU, 0x4F4CU, 0x504CU, 0x514CU, 0x524CU, 0x534CU, 0x544CU, 0x554CU, 0x564CU, 0x574CU, 0x584CU, 0x594CU, 0x5A4CU, 0x614CU, 0x624CU, 0x634CU, 0x644CU, 0x654CU, 0x664CU, 0x674CU, 0x684CU, 0x694CU, 0x6A4CU, 0x6B4CU, 0x6C4CU, 0x6D4CU, 0x6E4CU, 0x6F4CU, 0x704CU, 0x714CU, 0x724CU, 0x734CU, 0x744CU, 0x754CU, 0x764CU, 0x774CU, 0x784CU, 0x794CU, 0x7A4CU, 0x304CU, 0x314CU, 0x324CU, 0x334CU, 0x344CU, 0x354CU, 0x364CU, 0x374CU, 0x384CU, 0x394CU, 0x2B4CU, 0x2F4CU, 0x414DU, 0x424DU, 0x434DU, 0x444DU, 0x454DU, 0x464DU, 0x474DU, 0x484DU, 0x494DU, 0x4A4DU, 0x4B4DU, 0x4C4DU, 0x4D4DU, 0x4E4DU, 0x4F4DU, 0x504DU, 0x514DU, 0x524DU, 0x534DU, 0x544DU, 0x554DU, 0x564DU, 0x574DU, 0x584DU, 0x594DU, 0x5A4DU, 0x614DU, 0x624DU, 0x634DU, 0x644DU, 0x654DU, 0x664DU, 0x674DU, 0x684DU, 0x694DU, 0x6A4DU, 0x6B4DU, 0x6C4DU, 0x6D4DU, 0x6E4DU, 0x6F4DU, 0x704DU, 0x714DU, 0x724DU, 0x734DU, 0x744DU, 0x754DU, 0x764DU, 0x774DU, 0x784DU, 0x794DU, 0x7A4DU, 0x304DU, 0x314DU, 0x324DU, 0x334DU, 0x344DU, 0x354DU, 0x364DU, 0x374DU, 0x384DU, 0x394DU, 0x2B4DU, 0x2F4DU, 0x414EU, 0x424EU, 0x434EU, 0x444EU, 0x454EU, 0x464EU, 0x474EU, 0x484EU, 0x494EU, 0x4A4EU, 0x4B4EU, 0x4C4EU, 0x4D4EU, 0x4E4EU, 0x4F4EU, 0x504EU, 0x514EU, 0x524EU, 0x534EU, 0x544EU, 0x554EU, 0x564EU, 0x574EU, 0x584EU, 0x594EU, 0x5A4EU, 0x614EU, 0x624EU, 0x634EU, 0x644EU, 0x654EU, 0x664EU, 0x674EU, 0x684EU, 0x694EU, 0x6A4EU, 0x6B4EU, 0x6C4EU, 0x6D4EU, 0x6E4EU, 0x6F4EU, 0x704EU, 0x714EU, 0x724EU, 0x734EU, 0x744EU, 0x754EU, 0x764EU, 0x774EU, 0x784EU, 0x794EU, 0x7A4EU, 0x304EU, 0x314EU, 0x324EU, 0x334EU, 0x344EU, 0x354EU, 0x364EU, 0x374EU, 0x384EU, 0x394EU, 0x2B4EU, 0x2F4EU, 0x414FU, 0x424FU, 0x434FU, 0x444FU, 0x454FU, 0x464FU, 0x474FU, 0x484FU, 0x494FU, 0x4A4FU, 0x4B4FU, 0x4C4FU, 0x4D4FU, 0x4E4FU, 0x4F4FU, 0x504FU, 0x514FU, 0x524FU, 0x534FU, 0x544FU, 0x554FU, 0x564FU, 0x574FU, 0x584FU, 0x594FU, 0x5A4FU, 0x614FU, 0x624FU, 0x634FU, 0x644FU, 0x654FU, 0x664FU, 0x674FU, 0x684FU, 0x694FU, 0x6A4FU, 0x6B4FU, 0x6C4FU, 0x6D4FU, 0x6E4FU, 0x6F4FU, 0x704FU, 0x714FU, 0x724FU, 0x734FU, 0x744FU, 0x754FU, 0x764FU, 0x774FU, 0x784FU, 0x794FU, 0x7A4FU, 0x304FU, 0x314FU, 0x324FU, 0x334FU, 0x344FU, 0x354FU, 0x364FU, 0x374FU, 0x384FU, 0x394FU, 0x2B4FU, 0x2F4FU, 0x4150U, 0x4250U, 0x4350U, 0x4450U, 0x4550U, 0x4650U, 0x4750U, 0x4850U, 0x4950U, 0x4A50U, 0x4B50U, 0x4C50U, 0x4D50U, 0x4E50U, 0x4F50U, 0x5050U, 0x5150U, 0x5250U, 0x5350U, 0x5450U, 0x5550U, 0x5650U, 0x5750U, 0x5850U, 0x5950U, 0x5A50U, 0x6150U, 0x6250U, 0x6350U, 0x6450U, 0x6550U, 0x6650U, 0x6750U, 0x6850U, 0x6950U, 0x6A50U, 0x6B50U, 0x6C50U, 0x6D50U, 0x6E50U, 0x6F50U, 0x7050U, 0x7150U, 0x7250U, 0x7350U, 0x7450U, 0x7550U, 0x7650U, 0x7750U, 0x7850U, 0x7950U, 0x7A50U, 0x3050U, 0x3150U, 0x3250U, 0x3350U, 0x3450U, 0x3550U, 0x3650U, 0x3750U, 0x3850U, 0x3950U, 0x2B50U, 0x2F50U, 0x4151U, 0x4251U, 0x4351U, 0x4451U, 0x4551U, 0x4651U, 0x4751U, 0x4851U, 0x4951U, 0x4A51U, 0x4B51U, 0x4C51U, 0x4D51U, 0x4E51U, 0x4F51U, 0x5051U, 0x5151U, 0x5251U, 0x5351U, 0x5451U, 0x5551U, 0x5651U, 0x5751U, 0x5851U, 0x5951U, 0x5A51U, 0x6151U, 0x6251U, 0x6351U, 0x6451U, 0x6551U, 0x6651U, 0x6751U, 0x6851U, 0x6951U, 0x6A51U, 0x6B51U, 0x6C51U, 0x6D51U, 0x6E51U, 0x6F51U, 0x7051U, 0x7151U, 0x7251U, 0x7351U, 0x7451U, 0x7551U, 0x7651U, 0x7751U, 0x7851U, 0x7951U, 0x7A51U, 0x3051U, 0x3151U, 0x3251U, 0x3351U, 0x3451U, 0x3551U, 0x3651U, 0x3751U, 0x3851U, 0x3951U, 0x2B51U, 0x2F51U, 0x4152U, 0x4252U, 0x4352U, 0x4452U, 0x4552U, 0x4652U, 0x4752U, 0x4852U, 0x4952U, 0x4A52U, 0x4B52U, 0x4C52U, 0x4D52U, 0x4E52U, 0x4F52U, 0x5052U, 0x5152U, 0x5252U, 0x5352U, 0x5452U, 0x5552U, 0x5652U, 0x5752U, 0x5852U, 0x5952U, 0x5A52U, 0x6152U, 0x6252U, 0x6352U, 0x6452U, 0x6552U, 0x6652U, 0x6752U, 0x6852U, 0x6952U, 0x6A52U, 0x6B52U, 0x6C52U, 0x6D52U, 0x6E52U, 0x6F52U, 0x7052U, 0x7152U, 0x7252U, 0x7352U, 0x7452U, 0x7552U, 0x7652U, 0x7752U, 0x7852U, 0x7952U, 0x7A52U, 0x3052U, 0x3152U, 0x3252U, 0x3352U, 0x3452U, 0x3552U, 0x3652U, 0x3752U, 0x3852U, 0x3952U, 0x2B52U, 0x2F52U, 0x4153U, 0x4253U, 0x4353U, 0x4453U, 0x4553U, 0x4653U, 0x4753U, 0x4853U, 0x4953U, 0x4A53U, 0x4B53U, 0x4C53U, 0x4D53U, 0x4E53U, 0x4F53U, 0x5053U, 0x5153U, 0x5253U, 0x5353U, 0x5453U, 0x5553U, 0x5653U, 0x5753U, 0x5853U, 0x5953U, 0x5A53U, 0x6153U, 0x6253U, 0x6353U, 0x6453U, 0x6553U, 0x6653U, 0x6753U, 0x6853U, 0x6953U, 0x6A53U, 0x6B53U, 0x6C53U, 0x6D53U, 0x6E53U, 0x6F53U, 0x7053U, 0x7153U, 0x7253U, 0x7353U, 0x7453U, 0x7553U, 0x7653U, 0x7753U, 0x7853U, 0x7953U, 0x7A53U, 0x3053U, 0x3153U, 0x3253U, 0x3353U, 0x3453U, 0x3553U, 0x3653U, 0x3753U, 0x3853U, 0x3953U, 0x2B53U, 0x2F53U, 0x4154U, 0x4254U, 0x4354U, 0x4454U, 0x4554U, 0x4654U, 0x4754U, 0x4854U, 0x4954U, 0x4A54U, 0x4B54U, 0x4C54U, 0x4D54U, 0x4E54U, 0x4F54U, 0x5054U, 0x5154U, 0x5254U, 0x5354U, 0x5454U, 0x5554U, 0x5654U, 0x5754U, 0x5854U, 0x5954U, 0x5A54U, 0x6154U, 0x6254U, 0x6354U, 0x6454U, 0x6554U, 0x6654U, 0x6754U, 0x6854U, 0x6954U, 0x6A54U, 0x6B54U, 0x6C54U, 0x6D54U, 0x6E54U, 0x6F54U, 0x7054U, 0x7154U, 0x7254U, 0x7354U, 0x7454U, 0x7554U, 0x7654U, 0x7754U, 0x7854U, 0x7954U, 0x7A54U, 0x3054U, 0x3154U, 0x3254U, 0x3354U, 0x3454U, 0x3554U, 0x3654U, 0x3754U, 0x3854U, 0x3954U, 0x2B54U, 0x2F54U, 0x4155U, 0x4255U, 0x4355U, 0x4455U, 0x4555U, 0x4655U, 0x4755U, 0x4855U, 0x4955U, 0x4A55U, 0x4B55U, 0x4C55U, 0x4D55U, 0x4E55U, 0x4F55U, 0x5055U, 0x5155U, 0x5255U, 0x5355U, 0x5455U, 0x5555U, 0x5655U, 0x5755U, 0x5855U, 0x5955U, 0x5A55U, 0x6155U, 0x6255U, 0x6355U, 0x6455U, 0x6555U, 0x6655U, 0x6755U, 0x6855U, 0x6955U, 0x6A55U, 0x6B55U, 0x6C55U, 0x6D55U, 0x6E55U, 0x6F55U, 0x7055U, 0x7155U, 0x7255U, 0x7355U, 0x7455U, 0x7555U, 0x7655U, 0x7755U, 0x7855U, 0x7955U, 0x7A55U, 0x3055U, 0x3155U, 0x3255U, 0x3355U, 0x3455U, 0x3555U, 0x3655U, 0x3755U, 0x3855U, 0x3955U, 0x2B55U, 0x2F55U, 0x4156U, 0x4256U, 0x4356U, 0x4456U, 0x4556U, 0x4656U, 0x4756U, 0x4856U, 0x4956U, 0x4A56U, 0x4B56U, 0x4C56U, 0x4D56U, 0x4E56U, 0x4F56U, 0x5056U, 0x5156U, 0x5256U, 0x5356U, 0x5456U, 0x5556U, 0x5656U, 0x5756U, 0x5856U, 0x5956U, 0x5A56U, 0x6156U, 0x6256U, 0x6356U, 0x6456U, 0x6556U, 0x6656U, 0x6756U, 0x6856U, 0x6956U, 0x6A56U, 0x6B56U, 0x6C56U, 0x6D56U, 0x6E56U, 0x6F56U, 0x7056U, 0x7156U, 0x7256U, 0x7356U, 0x7456U, 0x7556U, 0x7656U, 0x7756U, 0x7856U, 0x7956U, 0x7A56U, 0x3056U, 0x3156U, 0x3256U, 0x3356U, 0x3456U, 0x3556U, 0x3656U, 0x3756U, 0x3856U, 0x3956U, 0x2B56U, 0x2F56U, 0x4157U, 0x4257U, 0x4357U, 0x4457U, 0x4557U, 0x4657U, 0x4757U, 0x4857U, 0x4957U, 0x4A57U, 0x4B57U, 0x4C57U, 0x4D57U, 0x4E57U, 0x4F57U, 0x5057U, 0x5157U, 0x5257U, 0x5357U, 0x5457U, 0x5557U, 0x5657U, 0x5757U, 0x5857U, 0x5957U, 0x5A57U, 0x6157U, 0x6257U, 0x6357U, 0x6457U, 0x6557U, 0x6657U, 0x6757U, 0x6857U, 0x6957U, 0x6A57U, 0x6B57U, 0x6C57U, 0x6D57U, 0x6E57U, 0x6F57U, 0x7057U, 0x7157U, 0x7257U, 0x7357U, 0x7457U, 0x7557U, 0x7657U, 0x7757U, 0x7857U, 0x7957U, 0x7A57U, 0x3057U, 0x3157U, 0x3257U, 0x3357U, 0x3457U, 0x3557U, 0x3657U, 0x3757U, 0x3857U, 0x3957U, 0x2B57U, 0x2F57U, 0x4158U, 0x4258U, 0x4358U, 0x4458U, 0x4558U, 0x4658U, 0x4758U, 0x4858U, 0x4958U, 0x4A58U, 0x4B58U, 0x4C58U, 0x4D58U, 0x4E58U, 0x4F58U, 0x5058U, 0x5158U, 0x5258U, 0x5358U, 0x5458U, 0x5558U, 0x5658U, 0x5758U, 0x5858U, 0x5958U, 0x5A58U, 0x6158U, 0x6258U, 0x6358U, 0x6458U, 0x6558U, 0x6658U, 0x6758U, 0x6858U, 0x6958U, 0x6A58U, 0x6B58U, 0x6C58U, 0x6D58U, 0x6E58U, 0x6F58U, 0x7058U, 0x7158U, 0x7258U, 0x7358U, 0x7458U, 0x7558U, 0x7658U, 0x7758U, 0x7858U, 0x7958U, 0x7A58U, 0x3058U, 0x3158U, 0x3258U, 0x3358U, 0x3458U, 0x3558U, 0x3658U, 0x3758U, 0x3858U, 0x3958U, 0x2B58U, 0x2F58U, 0x4159U, 0x4259U, 0x4359U, 0x4459U, 0x4559U, 0x4659U, 0x4759U, 0x4859U, 0x4959U, 0x4A59U, 0x4B59U, 0x4C59U, 0x4D59U, 0x4E59U, 0x4F59U, 0x5059U, 0x5159U, 0x5259U, 0x5359U, 0x5459U, 0x5559U, 0x5659U, 0x5759U, 0x5859U, 0x5959U, 0x5A59U, 0x6159U, 0x6259U, 0x6359U, 0x6459U, 0x6559U, 0x6659U, 0x6759U, 0x6859U, 0x6959U, 0x6A59U, 0x6B59U, 0x6C59U, 0x6D59U, 0x6E59U, 0x6F59U, 0x7059U, 0x7159U, 0x7259U, 0x7359U, 0x7459U, 0x7559U, 0x7659U, 0x7759U, 0x7859U, 0x7959U, 0x7A59U, 0x3059U, 0x3159U, 0x3259U, 0x3359U, 0x3459U, 0x3559U, 0x3659U, 0x3759U, 0x3859U, 0x3959U, 0x2B59U, 0x2F59U, 0x415AU, 0x425AU, 0x435AU, 0x445AU, 0x455AU, 0x465AU, 0x475AU, 0x485AU, 0x495AU, 0x4A5AU, 0x4B5AU, 0x4C5AU, 0x4D5AU, 0x4E5AU, 0x4F5AU, 0x505AU, 0x515AU, 0x525AU, 0x535AU, 0x545AU, 0x555AU, 0x565AU, 0x575AU, 0x585AU, 0x595AU, 0x5A5AU, 0x615AU, 0x625AU, 0x635AU, 0x645AU, 0x655AU, 0x665AU, 0x675AU, 0x685AU, 0x695AU, 0x6A5AU, 0x6B5AU, 0x6C5AU, 0x6D5AU, 0x6E5AU, 0x6F5AU, 0x705AU, 0x715AU, 0x725AU, 0x735AU, 0x745AU, 0x755AU, 0x765AU, 0x775AU, 0x785AU, 0x795AU, 0x7A5AU, 0x305AU, 0x315AU, 0x325AU, 0x335AU, 0x345AU, 0x355AU, 0x365AU, 0x375AU, 0x385AU, 0x395AU, 0x2B5AU, 0x2F5AU, 0x4161U, 0x4261U, 0x4361U, 0x4461U, 0x4561U, 0x4661U, 0x4761U, 0x4861U, 0x4961U, 0x4A61U, 0x4B61U, 0x4C61U, 0x4D61U, 0x4E61U, 0x4F61U, 0x5061U, 0x5161U, 0x5261U, 0x5361U, 0x5461U, 0x5561U, 0x5661U, 0x5761U, 0x5861U, 0x5961U, 0x5A61U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U, 0x6761U, 0x6861U, 0x6961U, 0x6A61U, 0x6B61U, 0x6C61U, 0x6D61U, 0x6E61U, 0x6F61U, 0x7061U, 0x7161U, 0x7261U, 0x7361U, 0x7461U, 0x7561U, 0x7661U, 0x7761U, 0x7861U, 0x7961U, 0x7A61U, 0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U, 0x3861U, 0x3961U, 0x2B61U, 0x2F61U, 0x4162U, 0x4262U, 0x4362U, 0x4462U, 0x4562U, 0x4662U, 0x4762U, 0x4862U, 0x4962U, 0x4A62U, 0x4B62U, 0x4C62U, 0x4D62U, 0x4E62U, 0x4F62U, 0x5062U, 0x5162U, 0x5262U, 0x5362U, 0x5462U, 0x5562U, 0x5662U, 0x5762U, 0x5862U, 0x5962U, 0x5A62U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U, 0x6762U, 0x6862U, 0x6962U, 0x6A62U, 0x6B62U, 0x6C62U, 0x6D62U, 0x6E62U, 0x6F62U, 0x7062U, 0x7162U, 0x7262U, 0x7362U, 0x7462U, 0x7562U, 0x7662U, 0x7762U, 0x7862U, 0x7962U, 0x7A62U, 0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U, 0x3862U, 0x3962U, 0x2B62U, 0x2F62U, 0x4163U, 0x4263U, 0x4363U, 0x4463U, 0x4563U, 0x4663U, 0x4763U, 0x4863U, 0x4963U, 0x4A63U, 0x4B63U, 0x4C63U, 0x4D63U, 0x4E63U, 0x4F63U, 0x5063U, 0x5163U, 0x5263U, 0x5363U, 0x5463U, 0x5563U, 0x5663U, 0x5763U, 0x5863U, 0x5963U, 0x5A63U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U, 0x6763U, 0x6863U, 0x6963U, 0x6A63U, 0x6B63U, 0x6C63U, 0x6D63U, 0x6E63U, 0x6F63U, 0x7063U, 0x7163U, 0x7263U, 0x7363U, 0x7463U, 0x7563U, 0x7663U, 0x7763U, 0x7863U, 0x7963U, 0x7A63U, 0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U, 0x3863U, 0x3963U, 0x2B63U, 0x2F63U, 0x4164U, 0x4264U, 0x4364U, 0x4464U, 0x4564U, 0x4664U, 0x4764U, 0x4864U, 0x4964U, 0x4A64U, 0x4B64U, 0x4C64U, 0x4D64U, 0x4E64U, 0x4F64U, 0x5064U, 0x5164U, 0x5264U, 0x5364U, 0x5464U, 0x5564U, 0x5664U, 0x5764U, 0x5864U, 0x5964U, 0x5A64U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U, 0x6764U, 0x6864U, 0x6964U, 0x6A64U, 0x6B64U, 0x6C64U, 0x6D64U, 0x6E64U, 0x6F64U, 0x7064U, 0x7164U, 0x7264U, 0x7364U, 0x7464U, 0x7564U, 0x7664U, 0x7764U, 0x7864U, 0x7964U, 0x7A64U, 0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U, 0x3864U, 0x3964U, 0x2B64U, 0x2F64U, 0x4165U, 0x4265U, 0x4365U, 0x4465U, 0x4565U, 0x4665U, 0x4765U, 0x4865U, 0x4965U, 0x4A65U, 0x4B65U, 0x4C65U, 0x4D65U, 0x4E65U, 0x4F65U, 0x5065U, 0x5165U, 0x5265U, 0x5365U, 0x5465U, 0x5565U, 0x5665U, 0x5765U, 0x5865U, 0x5965U, 0x5A65U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U, 0x6765U, 0x6865U, 0x6965U, 0x6A65U, 0x6B65U, 0x6C65U, 0x6D65U, 0x6E65U, 0x6F65U, 0x7065U, 0x7165U, 0x7265U, 0x7365U, 0x7465U, 0x7565U, 0x7665U, 0x7765U, 0x7865U, 0x7965U, 0x7A65U, 0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U, 0x3865U, 0x3965U, 0x2B65U, 0x2F65U, 0x4166U, 0x4266U, 0x4366U, 0x4466U, 0x4566U, 0x4666U, 0x4766U, 0x4866U, 0x4966U, 0x4A66U, 0x4B66U, 0x4C66U, 0x4D66U, 0x4E66U, 0x4F66U, 0x5066U, 0x5166U, 0x5266U, 0x5366U, 0x5466U, 0x5566U, 0x5666U, 0x5766U, 0x5866U, 0x5966U, 0x5A66U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U, 0x6766U, 0x6866U, 0x6966U, 0x6A66U, 0x6B66U, 0x6C66U, 0x6D66U, 0x6E66U, 0x6F66U, 0x7066U, 0x7166U, 0x7266U, 0x7366U, 0x7466U, 0x7566U, 0x7666U, 0x7766U, 0x7866U, 0x7966U, 0x7A66U, 0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U, 0x3866U, 0x3966U, 0x2B66U, 0x2F66U, 0x4167U, 0x4267U, 0x4367U, 0x4467U, 0x4567U, 0x4667U, 0x4767U, 0x4867U, 0x4967U, 0x4A67U, 0x4B67U, 0x4C67U, 0x4D67U, 0x4E67U, 0x4F67U, 0x5067U, 0x5167U, 0x5267U, 0x5367U, 0x5467U, 0x5567U, 0x5667U, 0x5767U, 0x5867U, 0x5967U, 0x5A67U, 0x6167U, 0x6267U, 0x6367U, 0x6467U, 0x6567U, 0x6667U, 0x6767U, 0x6867U, 0x6967U, 0x6A67U, 0x6B67U, 0x6C67U, 0x6D67U, 0x6E67U, 0x6F67U, 0x7067U, 0x7167U, 0x7267U, 0x7367U, 0x7467U, 0x7567U, 0x7667U, 0x7767U, 0x7867U, 0x7967U, 0x7A67U, 0x3067U, 0x3167U, 0x3267U, 0x3367U, 0x3467U, 0x3567U, 0x3667U, 0x3767U, 0x3867U, 0x3967U, 0x2B67U, 0x2F67U, 0x4168U, 0x4268U, 0x4368U, 0x4468U, 0x4568U, 0x4668U, 0x4768U, 0x4868U, 0x4968U, 0x4A68U, 0x4B68U, 0x4C68U, 0x4D68U, 0x4E68U, 0x4F68U, 0x5068U, 0x5168U, 0x5268U, 0x5368U, 0x5468U, 0x5568U, 0x5668U, 0x5768U, 0x5868U, 0x5968U, 0x5A68U, 0x6168U, 0x6268U, 0x6368U, 0x6468U, 0x6568U, 0x6668U, 0x6768U, 0x6868U, 0x6968U, 0x6A68U, 0x6B68U, 0x6C68U, 0x6D68U, 0x6E68U, 0x6F68U, 0x7068U, 0x7168U, 0x7268U, 0x7368U, 0x7468U, 0x7568U, 0x7668U, 0x7768U, 0x7868U, 0x7968U, 0x7A68U, 0x3068U, 0x3168U, 0x3268U, 0x3368U, 0x3468U, 0x3568U, 0x3668U, 0x3768U, 0x3868U, 0x3968U, 0x2B68U, 0x2F68U, 0x4169U, 0x4269U, 0x4369U, 0x4469U, 0x4569U, 0x4669U, 0x4769U, 0x4869U, 0x4969U, 0x4A69U, 0x4B69U, 0x4C69U, 0x4D69U, 0x4E69U, 0x4F69U, 0x5069U, 0x5169U, 0x5269U, 0x5369U, 0x5469U, 0x5569U, 0x5669U, 0x5769U, 0x5869U, 0x5969U, 0x5A69U, 0x6169U, 0x6269U, 0x6369U, 0x6469U, 0x6569U, 0x6669U, 0x6769U, 0x6869U, 0x6969U, 0x6A69U, 0x6B69U, 0x6C69U, 0x6D69U, 0x6E69U, 0x6F69U, 0x7069U, 0x7169U, 0x7269U, 0x7369U, 0x7469U, 0x7569U, 0x7669U, 0x7769U, 0x7869U, 0x7969U, 0x7A69U, 0x3069U, 0x3169U, 0x3269U, 0x3369U, 0x3469U, 0x3569U, 0x3669U, 0x3769U, 0x3869U, 0x3969U, 0x2B69U, 0x2F69U, 0x416AU, 0x426AU, 0x436AU, 0x446AU, 0x456AU, 0x466AU, 0x476AU, 0x486AU, 0x496AU, 0x4A6AU, 0x4B6AU, 0x4C6AU, 0x4D6AU, 0x4E6AU, 0x4F6AU, 0x506AU, 0x516AU, 0x526AU, 0x536AU, 0x546AU, 0x556AU, 0x566AU, 0x576AU, 0x586AU, 0x596AU, 0x5A6AU, 0x616AU, 0x626AU, 0x636AU, 0x646AU, 0x656AU, 0x666AU, 0x676AU, 0x686AU, 0x696AU, 0x6A6AU, 0x6B6AU, 0x6C6AU, 0x6D6AU, 0x6E6AU, 0x6F6AU, 0x706AU, 0x716AU, 0x726AU, 0x736AU, 0x746AU, 0x756AU, 0x766AU, 0x776AU, 0x786AU, 0x796AU, 0x7A6AU, 0x306AU, 0x316AU, 0x326AU, 0x336AU, 0x346AU, 0x356AU, 0x366AU, 0x376AU, 0x386AU, 0x396AU, 0x2B6AU, 0x2F6AU, 0x416BU, 0x426BU, 0x436BU, 0x446BU, 0x456BU, 0x466BU, 0x476BU, 0x486BU, 0x496BU, 0x4A6BU, 0x4B6BU, 0x4C6BU, 0x4D6BU, 0x4E6BU, 0x4F6BU, 0x506BU, 0x516BU, 0x526BU, 0x536BU, 0x546BU, 0x556BU, 0x566BU, 0x576BU, 0x586BU, 0x596BU, 0x5A6BU, 0x616BU, 0x626BU, 0x636BU, 0x646BU, 0x656BU, 0x666BU, 0x676BU, 0x686BU, 0x696BU, 0x6A6BU, 0x6B6BU, 0x6C6BU, 0x6D6BU, 0x6E6BU, 0x6F6BU, 0x706BU, 0x716BU, 0x726BU, 0x736BU, 0x746BU, 0x756BU, 0x766BU, 0x776BU, 0x786BU, 0x796BU, 0x7A6BU, 0x306BU, 0x316BU, 0x326BU, 0x336BU, 0x346BU, 0x356BU, 0x366BU, 0x376BU, 0x386BU, 0x396BU, 0x2B6BU, 0x2F6BU, 0x416CU, 0x426CU, 0x436CU, 0x446CU, 0x456CU, 0x466CU, 0x476CU, 0x486CU, 0x496CU, 0x4A6CU, 0x4B6CU, 0x4C6CU, 0x4D6CU, 0x4E6CU, 0x4F6CU, 0x506CU, 0x516CU, 0x526CU, 0x536CU, 0x546CU, 0x556CU, 0x566CU, 0x576CU, 0x586CU, 0x596CU, 0x5A6CU, 0x616CU, 0x626CU, 0x636CU, 0x646CU, 0x656CU, 0x666CU, 0x676CU, 0x686CU, 0x696CU, 0x6A6CU, 0x6B6CU, 0x6C6CU, 0x6D6CU, 0x6E6CU, 0x6F6CU, 0x706CU, 0x716CU, 0x726CU, 0x736CU, 0x746CU, 0x756CU, 0x766CU, 0x776CU, 0x786CU, 0x796CU, 0x7A6CU, 0x306CU, 0x316CU, 0x326CU, 0x336CU, 0x346CU, 0x356CU, 0x366CU, 0x376CU, 0x386CU, 0x396CU, 0x2B6CU, 0x2F6CU, 0x416DU, 0x426DU, 0x436DU, 0x446DU, 0x456DU, 0x466DU, 0x476DU, 0x486DU, 0x496DU, 0x4A6DU, 0x4B6DU, 0x4C6DU, 0x4D6DU, 0x4E6DU, 0x4F6DU, 0x506DU, 0x516DU, 0x526DU, 0x536DU, 0x546DU, 0x556DU, 0x566DU, 0x576DU, 0x586DU, 0x596DU, 0x5A6DU, 0x616DU, 0x626DU, 0x636DU, 0x646DU, 0x656DU, 0x666DU, 0x676DU, 0x686DU, 0x696DU, 0x6A6DU, 0x6B6DU, 0x6C6DU, 0x6D6DU, 0x6E6DU, 0x6F6DU, 0x706DU, 0x716DU, 0x726DU, 0x736DU, 0x746DU, 0x756DU, 0x766DU, 0x776DU, 0x786DU, 0x796DU, 0x7A6DU, 0x306DU, 0x316DU, 0x326DU, 0x336DU, 0x346DU, 0x356DU, 0x366DU, 0x376DU, 0x386DU, 0x396DU, 0x2B6DU, 0x2F6DU, 0x416EU, 0x426EU, 0x436EU, 0x446EU, 0x456EU, 0x466EU, 0x476EU, 0x486EU, 0x496EU, 0x4A6EU, 0x4B6EU, 0x4C6EU, 0x4D6EU, 0x4E6EU, 0x4F6EU, 0x506EU, 0x516EU, 0x526EU, 0x536EU, 0x546EU, 0x556EU, 0x566EU, 0x576EU, 0x586EU, 0x596EU, 0x5A6EU, 0x616EU, 0x626EU, 0x636EU, 0x646EU, 0x656EU, 0x666EU, 0x676EU, 0x686EU, 0x696EU, 0x6A6EU, 0x6B6EU, 0x6C6EU, 0x6D6EU, 0x6E6EU, 0x6F6EU, 0x706EU, 0x716EU, 0x726EU, 0x736EU, 0x746EU, 0x756EU, 0x766EU, 0x776EU, 0x786EU, 0x796EU, 0x7A6EU, 0x306EU, 0x316EU, 0x326EU, 0x336EU, 0x346EU, 0x356EU, 0x366EU, 0x376EU, 0x386EU, 0x396EU, 0x2B6EU, 0x2F6EU, 0x416FU, 0x426FU, 0x436FU, 0x446FU, 0x456FU, 0x466FU, 0x476FU, 0x486FU, 0x496FU, 0x4A6FU, 0x4B6FU, 0x4C6FU, 0x4D6FU, 0x4E6FU, 0x4F6FU, 0x506FU, 0x516FU, 0x526FU, 0x536FU, 0x546FU, 0x556FU, 0x566FU, 0x576FU, 0x586FU, 0x596FU, 0x5A6FU, 0x616FU, 0x626FU, 0x636FU, 0x646FU, 0x656FU, 0x666FU, 0x676FU, 0x686FU, 0x696FU, 0x6A6FU, 0x6B6FU, 0x6C6FU, 0x6D6FU, 0x6E6FU, 0x6F6FU, 0x706FU, 0x716FU, 0x726FU, 0x736FU, 0x746FU, 0x756FU, 0x766FU, 0x776FU, 0x786FU, 0x796FU, 0x7A6FU, 0x306FU, 0x316FU, 0x326FU, 0x336FU, 0x346FU, 0x356FU, 0x366FU, 0x376FU, 0x386FU, 0x396FU, 0x2B6FU, 0x2F6FU, 0x4170U, 0x4270U, 0x4370U, 0x4470U, 0x4570U, 0x4670U, 0x4770U, 0x4870U, 0x4970U, 0x4A70U, 0x4B70U, 0x4C70U, 0x4D70U, 0x4E70U, 0x4F70U, 0x5070U, 0x5170U, 0x5270U, 0x5370U, 0x5470U, 0x5570U, 0x5670U, 0x5770U, 0x5870U, 0x5970U, 0x5A70U, 0x6170U, 0x6270U, 0x6370U, 0x6470U, 0x6570U, 0x6670U, 0x6770U, 0x6870U, 0x6970U, 0x6A70U, 0x6B70U, 0x6C70U, 0x6D70U, 0x6E70U, 0x6F70U, 0x7070U, 0x7170U, 0x7270U, 0x7370U, 0x7470U, 0x7570U, 0x7670U, 0x7770U, 0x7870U, 0x7970U, 0x7A70U, 0x3070U, 0x3170U, 0x3270U, 0x3370U, 0x3470U, 0x3570U, 0x3670U, 0x3770U, 0x3870U, 0x3970U, 0x2B70U, 0x2F70U, 0x4171U, 0x4271U, 0x4371U, 0x4471U, 0x4571U, 0x4671U, 0x4771U, 0x4871U, 0x4971U, 0x4A71U, 0x4B71U, 0x4C71U, 0x4D71U, 0x4E71U, 0x4F71U, 0x5071U, 0x5171U, 0x5271U, 0x5371U, 0x5471U, 0x5571U, 0x5671U, 0x5771U, 0x5871U, 0x5971U, 0x5A71U, 0x6171U, 0x6271U, 0x6371U, 0x6471U, 0x6571U, 0x6671U, 0x6771U, 0x6871U, 0x6971U, 0x6A71U, 0x6B71U, 0x6C71U, 0x6D71U, 0x6E71U, 0x6F71U, 0x7071U, 0x7171U, 0x7271U, 0x7371U, 0x7471U, 0x7571U, 0x7671U, 0x7771U, 0x7871U, 0x7971U, 0x7A71U, 0x3071U, 0x3171U, 0x3271U, 0x3371U, 0x3471U, 0x3571U, 0x3671U, 0x3771U, 0x3871U, 0x3971U, 0x2B71U, 0x2F71U, 0x4172U, 0x4272U, 0x4372U, 0x4472U, 0x4572U, 0x4672U, 0x4772U, 0x4872U, 0x4972U, 0x4A72U, 0x4B72U, 0x4C72U, 0x4D72U, 0x4E72U, 0x4F72U, 0x5072U, 0x5172U, 0x5272U, 0x5372U, 0x5472U, 0x5572U, 0x5672U, 0x5772U, 0x5872U, 0x5972U, 0x5A72U, 0x6172U, 0x6272U, 0x6372U, 0x6472U, 0x6572U, 0x6672U, 0x6772U, 0x6872U, 0x6972U, 0x6A72U, 0x6B72U, 0x6C72U, 0x6D72U, 0x6E72U, 0x6F72U, 0x7072U, 0x7172U, 0x7272U, 0x7372U, 0x7472U, 0x7572U, 0x7672U, 0x7772U, 0x7872U, 0x7972U, 0x7A72U, 0x3072U, 0x3172U, 0x3272U, 0x3372U, 0x3472U, 0x3572U, 0x3672U, 0x3772U, 0x3872U, 0x3972U, 0x2B72U, 0x2F72U, 0x4173U, 0x4273U, 0x4373U, 0x4473U, 0x4573U, 0x4673U, 0x4773U, 0x4873U, 0x4973U, 0x4A73U, 0x4B73U, 0x4C73U, 0x4D73U, 0x4E73U, 0x4F73U, 0x5073U, 0x5173U, 0x5273U, 0x5373U, 0x5473U, 0x5573U, 0x5673U, 0x5773U, 0x5873U, 0x5973U, 0x5A73U, 0x6173U, 0x6273U, 0x6373U, 0x6473U, 0x6573U, 0x6673U, 0x6773U, 0x6873U, 0x6973U, 0x6A73U, 0x6B73U, 0x6C73U, 0x6D73U, 0x6E73U, 0x6F73U, 0x7073U, 0x7173U, 0x7273U, 0x7373U, 0x7473U, 0x7573U, 0x7673U, 0x7773U, 0x7873U, 0x7973U, 0x7A73U, 0x3073U, 0x3173U, 0x3273U, 0x3373U, 0x3473U, 0x3573U, 0x3673U, 0x3773U, 0x3873U, 0x3973U, 0x2B73U, 0x2F73U, 0x4174U, 0x4274U, 0x4374U, 0x4474U, 0x4574U, 0x4674U, 0x4774U, 0x4874U, 0x4974U, 0x4A74U, 0x4B74U, 0x4C74U, 0x4D74U, 0x4E74U, 0x4F74U, 0x5074U, 0x5174U, 0x5274U, 0x5374U, 0x5474U, 0x5574U, 0x5674U, 0x5774U, 0x5874U, 0x5974U, 0x5A74U, 0x6174U, 0x6274U, 0x6374U, 0x6474U, 0x6574U, 0x6674U, 0x6774U, 0x6874U, 0x6974U, 0x6A74U, 0x6B74U, 0x6C74U, 0x6D74U, 0x6E74U, 0x6F74U, 0x7074U, 0x7174U, 0x7274U, 0x7374U, 0x7474U, 0x7574U, 0x7674U, 0x7774U, 0x7874U, 0x7974U, 0x7A74U, 0x3074U, 0x3174U, 0x3274U, 0x3374U, 0x3474U, 0x3574U, 0x3674U, 0x3774U, 0x3874U, 0x3974U, 0x2B74U, 0x2F74U, 0x4175U, 0x4275U, 0x4375U, 0x4475U, 0x4575U, 0x4675U, 0x4775U, 0x4875U, 0x4975U, 0x4A75U, 0x4B75U, 0x4C75U, 0x4D75U, 0x4E75U, 0x4F75U, 0x5075U, 0x5175U, 0x5275U, 0x5375U, 0x5475U, 0x5575U, 0x5675U, 0x5775U, 0x5875U, 0x5975U, 0x5A75U, 0x6175U, 0x6275U, 0x6375U, 0x6475U, 0x6575U, 0x6675U, 0x6775U, 0x6875U, 0x6975U, 0x6A75U, 0x6B75U, 0x6C75U, 0x6D75U, 0x6E75U, 0x6F75U, 0x7075U, 0x7175U, 0x7275U, 0x7375U, 0x7475U, 0x7575U, 0x7675U, 0x7775U, 0x7875U, 0x7975U, 0x7A75U, 0x3075U, 0x3175U, 0x3275U, 0x3375U, 0x3475U, 0x3575U, 0x3675U, 0x3775U, 0x3875U, 0x3975U, 0x2B75U, 0x2F75U, 0x4176U, 0x4276U, 0x4376U, 0x4476U, 0x4576U, 0x4676U, 0x4776U, 0x4876U, 0x4976U, 0x4A76U, 0x4B76U, 0x4C76U, 0x4D76U, 0x4E76U, 0x4F76U, 0x5076U, 0x5176U, 0x5276U, 0x5376U, 0x5476U, 0x5576U, 0x5676U, 0x5776U, 0x5876U, 0x5976U, 0x5A76U, 0x6176U, 0x6276U, 0x6376U, 0x6476U, 0x6576U, 0x6676U, 0x6776U, 0x6876U, 0x6976U, 0x6A76U, 0x6B76U, 0x6C76U, 0x6D76U, 0x6E76U, 0x6F76U, 0x7076U, 0x7176U, 0x7276U, 0x7376U, 0x7476U, 0x7576U, 0x7676U, 0x7776U, 0x7876U, 0x7976U, 0x7A76U, 0x3076U, 0x3176U, 0x3276U, 0x3376U, 0x3476U, 0x3576U, 0x3676U, 0x3776U, 0x3876U, 0x3976U, 0x2B76U, 0x2F76U, 0x4177U, 0x4277U, 0x4377U, 0x4477U, 0x4577U, 0x4677U, 0x4777U, 0x4877U, 0x4977U, 0x4A77U, 0x4B77U, 0x4C77U, 0x4D77U, 0x4E77U, 0x4F77U, 0x5077U, 0x5177U, 0x5277U, 0x5377U, 0x5477U, 0x5577U, 0x5677U, 0x5777U, 0x5877U, 0x5977U, 0x5A77U, 0x6177U, 0x6277U, 0x6377U, 0x6477U, 0x6577U, 0x6677U, 0x6777U, 0x6877U, 0x6977U, 0x6A77U, 0x6B77U, 0x6C77U, 0x6D77U, 0x6E77U, 0x6F77U, 0x7077U, 0x7177U, 0x7277U, 0x7377U, 0x7477U, 0x7577U, 0x7677U, 0x7777U, 0x7877U, 0x7977U, 0x7A77U, 0x3077U, 0x3177U, 0x3277U, 0x3377U, 0x3477U, 0x3577U, 0x3677U, 0x3777U, 0x3877U, 0x3977U, 0x2B77U, 0x2F77U, 0x4178U, 0x4278U, 0x4378U, 0x4478U, 0x4578U, 0x4678U, 0x4778U, 0x4878U, 0x4978U, 0x4A78U, 0x4B78U, 0x4C78U, 0x4D78U, 0x4E78U, 0x4F78U, 0x5078U, 0x5178U, 0x5278U, 0x5378U, 0x5478U, 0x5578U, 0x5678U, 0x5778U, 0x5878U, 0x5978U, 0x5A78U, 0x6178U, 0x6278U, 0x6378U, 0x6478U, 0x6578U, 0x6678U, 0x6778U, 0x6878U, 0x6978U, 0x6A78U, 0x6B78U, 0x6C78U, 0x6D78U, 0x6E78U, 0x6F78U, 0x7078U, 0x7178U, 0x7278U, 0x7378U, 0x7478U, 0x7578U, 0x7678U, 0x7778U, 0x7878U, 0x7978U, 0x7A78U, 0x3078U, 0x3178U, 0x3278U, 0x3378U, 0x3478U, 0x3578U, 0x3678U, 0x3778U, 0x3878U, 0x3978U, 0x2B78U, 0x2F78U, 0x4179U, 0x4279U, 0x4379U, 0x4479U, 0x4579U, 0x4679U, 0x4779U, 0x4879U, 0x4979U, 0x4A79U, 0x4B79U, 0x4C79U, 0x4D79U, 0x4E79U, 0x4F79U, 0x5079U, 0x5179U, 0x5279U, 0x5379U, 0x5479U, 0x5579U, 0x5679U, 0x5779U, 0x5879U, 0x5979U, 0x5A79U, 0x6179U, 0x6279U, 0x6379U, 0x6479U, 0x6579U, 0x6679U, 0x6779U, 0x6879U, 0x6979U, 0x6A79U, 0x6B79U, 0x6C79U, 0x6D79U, 0x6E79U, 0x6F79U, 0x7079U, 0x7179U, 0x7279U, 0x7379U, 0x7479U, 0x7579U, 0x7679U, 0x7779U, 0x7879U, 0x7979U, 0x7A79U, 0x3079U, 0x3179U, 0x3279U, 0x3379U, 0x3479U, 0x3579U, 0x3679U, 0x3779U, 0x3879U, 0x3979U, 0x2B79U, 0x2F79U, 0x417AU, 0x427AU, 0x437AU, 0x447AU, 0x457AU, 0x467AU, 0x477AU, 0x487AU, 0x497AU, 0x4A7AU, 0x4B7AU, 0x4C7AU, 0x4D7AU, 0x4E7AU, 0x4F7AU, 0x507AU, 0x517AU, 0x527AU, 0x537AU, 0x547AU, 0x557AU, 0x567AU, 0x577AU, 0x587AU, 0x597AU, 0x5A7AU, 0x617AU, 0x627AU, 0x637AU, 0x647AU, 0x657AU, 0x667AU, 0x677AU, 0x687AU, 0x697AU, 0x6A7AU, 0x6B7AU, 0x6C7AU, 0x6D7AU, 0x6E7AU, 0x6F7AU, 0x707AU, 0x717AU, 0x727AU, 0x737AU, 0x747AU, 0x757AU, 0x767AU, 0x777AU, 0x787AU, 0x797AU, 0x7A7AU, 0x307AU, 0x317AU, 0x327AU, 0x337AU, 0x347AU, 0x357AU, 0x367AU, 0x377AU, 0x387AU, 0x397AU, 0x2B7AU, 0x2F7AU, 0x4130U, 0x4230U, 0x4330U, 0x4430U, 0x4530U, 0x4630U, 0x4730U, 0x4830U, 0x4930U, 0x4A30U, 0x4B30U, 0x4C30U, 0x4D30U, 0x4E30U, 0x4F30U, 0x5030U, 0x5130U, 0x5230U, 0x5330U, 0x5430U, 0x5530U, 0x5630U, 0x5730U, 0x5830U, 0x5930U, 0x5A30U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U, 0x6730U, 0x6830U, 0x6930U, 0x6A30U, 0x6B30U, 0x6C30U, 0x6D30U, 0x6E30U, 0x6F30U, 0x7030U, 0x7130U, 0x7230U, 0x7330U, 0x7430U, 0x7530U, 0x7630U, 0x7730U, 0x7830U, 0x7930U, 0x7A30U, 0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U, 0x3830U, 0x3930U, 0x2B30U, 0x2F30U, 0x4131U, 0x4231U, 0x4331U, 0x4431U, 0x4531U, 0x4631U, 0x4731U, 0x4831U, 0x4931U, 0x4A31U, 0x4B31U, 0x4C31U, 0x4D31U, 0x4E31U, 0x4F31U, 0x5031U, 0x5131U, 0x5231U, 0x5331U, 0x5431U, 0x5531U, 0x5631U, 0x5731U, 0x5831U, 0x5931U, 0x5A31U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U, 0x6731U, 0x6831U, 0x6931U, 0x6A31U, 0x6B31U, 0x6C31U, 0x6D31U, 0x6E31U, 0x6F31U, 0x7031U, 0x7131U, 0x7231U, 0x7331U, 0x7431U, 0x7531U, 0x7631U, 0x7731U, 0x7831U, 0x7931U, 0x7A31U, 0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U, 0x3831U, 0x3931U, 0x2B31U, 0x2F31U, 0x4132U, 0x4232U, 0x4332U, 0x4432U, 0x4532U, 0x4632U, 0x4732U, 0x4832U, 0x4932U, 0x4A32U, 0x4B32U, 0x4C32U, 0x4D32U, 0x4E32U, 0x4F32U, 0x5032U, 0x5132U, 0x5232U, 0x5332U, 0x5432U, 0x5532U, 0x5632U, 0x5732U, 0x5832U, 0x5932U, 0x5A32U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U, 0x6732U, 0x6832U, 0x6932U, 0x6A32U, 0x6B32U, 0x6C32U, 0x6D32U, 0x6E32U, 0x6F32U, 0x7032U, 0x7132U, 0x7232U, 0x7332U, 0x7432U, 0x7532U, 0x7632U, 0x7732U, 0x7832U, 0x7932U, 0x7A32U, 0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U, 0x3832U, 0x3932U, 0x2B32U, 0x2F32U, 0x4133U, 0x4233U, 0x4333U, 0x4433U, 0x4533U, 0x4633U, 0x4733U, 0x4833U, 0x4933U, 0x4A33U, 0x4B33U, 0x4C33U, 0x4D33U, 0x4E33U, 0x4F33U, 0x5033U, 0x5133U, 0x5233U, 0x5333U, 0x5433U, 0x5533U, 0x5633U, 0x5733U, 0x5833U, 0x5933U, 0x5A33U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U, 0x6733U, 0x6833U, 0x6933U, 0x6A33U, 0x6B33U, 0x6C33U, 0x6D33U, 0x6E33U, 0x6F33U, 0x7033U, 0x7133U, 0x7233U, 0x7333U, 0x7433U, 0x7533U, 0x7633U, 0x7733U, 0x7833U, 0x7933U, 0x7A33U, 0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U, 0x3833U, 0x3933U, 0x2B33U, 0x2F33U, 0x4134U, 0x4234U, 0x4334U, 0x4434U, 0x4534U, 0x4634U, 0x4734U, 0x4834U, 0x4934U, 0x4A34U, 0x4B34U, 0x4C34U, 0x4D34U, 0x4E34U, 0x4F34U, 0x5034U, 0x5134U, 0x5234U, 0x5334U, 0x5434U, 0x5534U, 0x5634U, 0x5734U, 0x5834U, 0x5934U, 0x5A34U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U, 0x6734U, 0x6834U, 0x6934U, 0x6A34U, 0x6B34U, 0x6C34U, 0x6D34U, 0x6E34U, 0x6F34U, 0x7034U, 0x7134U, 0x7234U, 0x7334U, 0x7434U, 0x7534U, 0x7634U, 0x7734U, 0x7834U, 0x7934U, 0x7A34U, 0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U, 0x3834U, 0x3934U, 0x2B34U, 0x2F34U, 0x4135U, 0x4235U, 0x4335U, 0x4435U, 0x4535U, 0x4635U, 0x4735U, 0x4835U, 0x4935U, 0x4A35U, 0x4B35U, 0x4C35U, 0x4D35U, 0x4E35U, 0x4F35U, 0x5035U, 0x5135U, 0x5235U, 0x5335U, 0x5435U, 0x5535U, 0x5635U, 0x5735U, 0x5835U, 0x5935U, 0x5A35U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U, 0x6735U, 0x6835U, 0x6935U, 0x6A35U, 0x6B35U, 0x6C35U, 0x6D35U, 0x6E35U, 0x6F35U, 0x7035U, 0x7135U, 0x7235U, 0x7335U, 0x7435U, 0x7535U, 0x7635U, 0x7735U, 0x7835U, 0x7935U, 0x7A35U, 0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U, 0x3835U, 0x3935U, 0x2B35U, 0x2F35U, 0x4136U, 0x4236U, 0x4336U, 0x4436U, 0x4536U, 0x4636U, 0x4736U, 0x4836U, 0x4936U, 0x4A36U, 0x4B36U, 0x4C36U, 0x4D36U, 0x4E36U, 0x4F36U, 0x5036U, 0x5136U, 0x5236U, 0x5336U, 0x5436U, 0x5536U, 0x5636U, 0x5736U, 0x5836U, 0x5936U, 0x5A36U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U, 0x6736U, 0x6836U, 0x6936U, 0x6A36U, 0x6B36U, 0x6C36U, 0x6D36U, 0x6E36U, 0x6F36U, 0x7036U, 0x7136U, 0x7236U, 0x7336U, 0x7436U, 0x7536U, 0x7636U, 0x7736U, 0x7836U, 0x7936U, 0x7A36U, 0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U, 0x3836U, 0x3936U, 0x2B36U, 0x2F36U, 0x4137U, 0x4237U, 0x4337U, 0x4437U, 0x4537U, 0x4637U, 0x4737U, 0x4837U, 0x4937U, 0x4A37U, 0x4B37U, 0x4C37U, 0x4D37U, 0x4E37U, 0x4F37U, 0x5037U, 0x5137U, 0x5237U, 0x5337U, 0x5437U, 0x5537U, 0x5637U, 0x5737U, 0x5837U, 0x5937U, 0x5A37U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U, 0x6737U, 0x6837U, 0x6937U, 0x6A37U, 0x6B37U, 0x6C37U, 0x6D37U, 0x6E37U, 0x6F37U, 0x7037U, 0x7137U, 0x7237U, 0x7337U, 0x7437U, 0x7537U, 0x7637U, 0x7737U, 0x7837U, 0x7937U, 0x7A37U, 0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U, 0x3837U, 0x3937U, 0x2B37U, 0x2F37U, 0x4138U, 0x4238U, 0x4338U, 0x4438U, 0x4538U, 0x4638U, 0x4738U, 0x4838U, 0x4938U, 0x4A38U, 0x4B38U, 0x4C38U, 0x4D38U, 0x4E38U, 0x4F38U, 0x5038U, 0x5138U, 0x5238U, 0x5338U, 0x5438U, 0x5538U, 0x5638U, 0x5738U, 0x5838U, 0x5938U, 0x5A38U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U, 0x6738U, 0x6838U, 0x6938U, 0x6A38U, 0x6B38U, 0x6C38U, 0x6D38U, 0x6E38U, 0x6F38U, 0x7038U, 0x7138U, 0x7238U, 0x7338U, 0x7438U, 0x7538U, 0x7638U, 0x7738U, 0x7838U, 0x7938U, 0x7A38U, 0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U, 0x3838U, 0x3938U, 0x2B38U, 0x2F38U, 0x4139U, 0x4239U, 0x4339U, 0x4439U, 0x4539U, 0x4639U, 0x4739U, 0x4839U, 0x4939U, 0x4A39U, 0x4B39U, 0x4C39U, 0x4D39U, 0x4E39U, 0x4F39U, 0x5039U, 0x5139U, 0x5239U, 0x5339U, 0x5439U, 0x5539U, 0x5639U, 0x5739U, 0x5839U, 0x5939U, 0x5A39U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U, 0x6739U, 0x6839U, 0x6939U, 0x6A39U, 0x6B39U, 0x6C39U, 0x6D39U, 0x6E39U, 0x6F39U, 0x7039U, 0x7139U, 0x7239U, 0x7339U, 0x7439U, 0x7539U, 0x7639U, 0x7739U, 0x7839U, 0x7939U, 0x7A39U, 0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U, 0x3839U, 0x3939U, 0x2B39U, 0x2F39U, 0x412BU, 0x422BU, 0x432BU, 0x442BU, 0x452BU, 0x462BU, 0x472BU, 0x482BU, 0x492BU, 0x4A2BU, 0x4B2BU, 0x4C2BU, 0x4D2BU, 0x4E2BU, 0x4F2BU, 0x502BU, 0x512BU, 0x522BU, 0x532BU, 0x542BU, 0x552BU, 0x562BU, 0x572BU, 0x582BU, 0x592BU, 0x5A2BU, 0x612BU, 0x622BU, 0x632BU, 0x642BU, 0x652BU, 0x662BU, 0x672BU, 0x682BU, 0x692BU, 0x6A2BU, 0x6B2BU, 0x6C2BU, 0x6D2BU, 0x6E2BU, 0x6F2BU, 0x702BU, 0x712BU, 0x722BU, 0x732BU, 0x742BU, 0x752BU, 0x762BU, 0x772BU, 0x782BU, 0x792BU, 0x7A2BU, 0x302BU, 0x312BU, 0x322BU, 0x332BU, 0x342BU, 0x352BU, 0x362BU, 0x372BU, 0x382BU, 0x392BU, 0x2B2BU, 0x2F2BU, 0x412FU, 0x422FU, 0x432FU, 0x442FU, 0x452FU, 0x462FU, 0x472FU, 0x482FU, 0x492FU, 0x4A2FU, 0x4B2FU, 0x4C2FU, 0x4D2FU, 0x4E2FU, 0x4F2FU, 0x502FU, 0x512FU, 0x522FU, 0x532FU, 0x542FU, 0x552FU, 0x562FU, 0x572FU, 0x582FU, 0x592FU, 0x5A2FU, 0x612FU, 0x622FU, 0x632FU, 0x642FU, 0x652FU, 0x662FU, 0x672FU, 0x682FU, 0x692FU, 0x6A2FU, 0x6B2FU, 0x6C2FU, 0x6D2FU, 0x6E2FU, 0x6F2FU, 0x702FU, 0x712FU, 0x722FU, 0x732FU, 0x742FU, 0x752FU, 0x762FU, 0x772FU, 0x782FU, 0x792FU, 0x7A2FU, 0x302FU, 0x312FU, 0x322FU, 0x332FU, 0x342FU, 0x352FU, 0x362FU, 0x372FU, 0x382FU, 0x392FU, 0x2B2FU, 0x2F2FU, #else 0x4141U, 0x4142U, 0x4143U, 0x4144U, 0x4145U, 0x4146U, 0x4147U, 0x4148U, 0x4149U, 0x414AU, 0x414BU, 0x414CU, 0x414DU, 0x414EU, 0x414FU, 0x4150U, 0x4151U, 0x4152U, 0x4153U, 0x4154U, 0x4155U, 0x4156U, 0x4157U, 0x4158U, 0x4159U, 0x415AU, 0x4161U, 0x4162U, 0x4163U, 0x4164U, 0x4165U, 0x4166U, 0x4167U, 0x4168U, 0x4169U, 0x416AU, 0x416BU, 0x416CU, 0x416DU, 0x416EU, 0x416FU, 0x4170U, 0x4171U, 0x4172U, 0x4173U, 0x4174U, 0x4175U, 0x4176U, 0x4177U, 0x4178U, 0x4179U, 0x417AU, 0x4130U, 0x4131U, 0x4132U, 0x4133U, 0x4134U, 0x4135U, 0x4136U, 0x4137U, 0x4138U, 0x4139U, 0x412BU, 0x412FU, 0x4241U, 0x4242U, 0x4243U, 0x4244U, 0x4245U, 0x4246U, 0x4247U, 0x4248U, 0x4249U, 0x424AU, 0x424BU, 0x424CU, 0x424DU, 0x424EU, 0x424FU, 0x4250U, 0x4251U, 0x4252U, 0x4253U, 0x4254U, 0x4255U, 0x4256U, 0x4257U, 0x4258U, 0x4259U, 0x425AU, 0x4261U, 0x4262U, 0x4263U, 0x4264U, 0x4265U, 0x4266U, 0x4267U, 0x4268U, 0x4269U, 0x426AU, 0x426BU, 0x426CU, 0x426DU, 0x426EU, 0x426FU, 0x4270U, 0x4271U, 0x4272U, 0x4273U, 0x4274U, 0x4275U, 0x4276U, 0x4277U, 0x4278U, 0x4279U, 0x427AU, 0x4230U, 0x4231U, 0x4232U, 0x4233U, 0x4234U, 0x4235U, 0x4236U, 0x4237U, 0x4238U, 0x4239U, 0x422BU, 0x422FU, 0x4341U, 0x4342U, 0x4343U, 0x4344U, 0x4345U, 0x4346U, 0x4347U, 0x4348U, 0x4349U, 0x434AU, 0x434BU, 0x434CU, 0x434DU, 0x434EU, 0x434FU, 0x4350U, 0x4351U, 0x4352U, 0x4353U, 0x4354U, 0x4355U, 0x4356U, 0x4357U, 0x4358U, 0x4359U, 0x435AU, 0x4361U, 0x4362U, 0x4363U, 0x4364U, 0x4365U, 0x4366U, 0x4367U, 0x4368U, 0x4369U, 0x436AU, 0x436BU, 0x436CU, 0x436DU, 0x436EU, 0x436FU, 0x4370U, 0x4371U, 0x4372U, 0x4373U, 0x4374U, 0x4375U, 0x4376U, 0x4377U, 0x4378U, 0x4379U, 0x437AU, 0x4330U, 0x4331U, 0x4332U, 0x4333U, 0x4334U, 0x4335U, 0x4336U, 0x4337U, 0x4338U, 0x4339U, 0x432BU, 0x432FU, 0x4441U, 0x4442U, 0x4443U, 0x4444U, 0x4445U, 0x4446U, 0x4447U, 0x4448U, 0x4449U, 0x444AU, 0x444BU, 0x444CU, 0x444DU, 0x444EU, 0x444FU, 0x4450U, 0x4451U, 0x4452U, 0x4453U, 0x4454U, 0x4455U, 0x4456U, 0x4457U, 0x4458U, 0x4459U, 0x445AU, 0x4461U, 0x4462U, 0x4463U, 0x4464U, 0x4465U, 0x4466U, 0x4467U, 0x4468U, 0x4469U, 0x446AU, 0x446BU, 0x446CU, 0x446DU, 0x446EU, 0x446FU, 0x4470U, 0x4471U, 0x4472U, 0x4473U, 0x4474U, 0x4475U, 0x4476U, 0x4477U, 0x4478U, 0x4479U, 0x447AU, 0x4430U, 0x4431U, 0x4432U, 0x4433U, 0x4434U, 0x4435U, 0x4436U, 0x4437U, 0x4438U, 0x4439U, 0x442BU, 0x442FU, 0x4541U, 0x4542U, 0x4543U, 0x4544U, 0x4545U, 0x4546U, 0x4547U, 0x4548U, 0x4549U, 0x454AU, 0x454BU, 0x454CU, 0x454DU, 0x454EU, 0x454FU, 0x4550U, 0x4551U, 0x4552U, 0x4553U, 0x4554U, 0x4555U, 0x4556U, 0x4557U, 0x4558U, 0x4559U, 0x455AU, 0x4561U, 0x4562U, 0x4563U, 0x4564U, 0x4565U, 0x4566U, 0x4567U, 0x4568U, 0x4569U, 0x456AU, 0x456BU, 0x456CU, 0x456DU, 0x456EU, 0x456FU, 0x4570U, 0x4571U, 0x4572U, 0x4573U, 0x4574U, 0x4575U, 0x4576U, 0x4577U, 0x4578U, 0x4579U, 0x457AU, 0x4530U, 0x4531U, 0x4532U, 0x4533U, 0x4534U, 0x4535U, 0x4536U, 0x4537U, 0x4538U, 0x4539U, 0x452BU, 0x452FU, 0x4641U, 0x4642U, 0x4643U, 0x4644U, 0x4645U, 0x4646U, 0x4647U, 0x4648U, 0x4649U, 0x464AU, 0x464BU, 0x464CU, 0x464DU, 0x464EU, 0x464FU, 0x4650U, 0x4651U, 0x4652U, 0x4653U, 0x4654U, 0x4655U, 0x4656U, 0x4657U, 0x4658U, 0x4659U, 0x465AU, 0x4661U, 0x4662U, 0x4663U, 0x4664U, 0x4665U, 0x4666U, 0x4667U, 0x4668U, 0x4669U, 0x466AU, 0x466BU, 0x466CU, 0x466DU, 0x466EU, 0x466FU, 0x4670U, 0x4671U, 0x4672U, 0x4673U, 0x4674U, 0x4675U, 0x4676U, 0x4677U, 0x4678U, 0x4679U, 0x467AU, 0x4630U, 0x4631U, 0x4632U, 0x4633U, 0x4634U, 0x4635U, 0x4636U, 0x4637U, 0x4638U, 0x4639U, 0x462BU, 0x462FU, 0x4741U, 0x4742U, 0x4743U, 0x4744U, 0x4745U, 0x4746U, 0x4747U, 0x4748U, 0x4749U, 0x474AU, 0x474BU, 0x474CU, 0x474DU, 0x474EU, 0x474FU, 0x4750U, 0x4751U, 0x4752U, 0x4753U, 0x4754U, 0x4755U, 0x4756U, 0x4757U, 0x4758U, 0x4759U, 0x475AU, 0x4761U, 0x4762U, 0x4763U, 0x4764U, 0x4765U, 0x4766U, 0x4767U, 0x4768U, 0x4769U, 0x476AU, 0x476BU, 0x476CU, 0x476DU, 0x476EU, 0x476FU, 0x4770U, 0x4771U, 0x4772U, 0x4773U, 0x4774U, 0x4775U, 0x4776U, 0x4777U, 0x4778U, 0x4779U, 0x477AU, 0x4730U, 0x4731U, 0x4732U, 0x4733U, 0x4734U, 0x4735U, 0x4736U, 0x4737U, 0x4738U, 0x4739U, 0x472BU, 0x472FU, 0x4841U, 0x4842U, 0x4843U, 0x4844U, 0x4845U, 0x4846U, 0x4847U, 0x4848U, 0x4849U, 0x484AU, 0x484BU, 0x484CU, 0x484DU, 0x484EU, 0x484FU, 0x4850U, 0x4851U, 0x4852U, 0x4853U, 0x4854U, 0x4855U, 0x4856U, 0x4857U, 0x4858U, 0x4859U, 0x485AU, 0x4861U, 0x4862U, 0x4863U, 0x4864U, 0x4865U, 0x4866U, 0x4867U, 0x4868U, 0x4869U, 0x486AU, 0x486BU, 0x486CU, 0x486DU, 0x486EU, 0x486FU, 0x4870U, 0x4871U, 0x4872U, 0x4873U, 0x4874U, 0x4875U, 0x4876U, 0x4877U, 0x4878U, 0x4879U, 0x487AU, 0x4830U, 0x4831U, 0x4832U, 0x4833U, 0x4834U, 0x4835U, 0x4836U, 0x4837U, 0x4838U, 0x4839U, 0x482BU, 0x482FU, 0x4941U, 0x4942U, 0x4943U, 0x4944U, 0x4945U, 0x4946U, 0x4947U, 0x4948U, 0x4949U, 0x494AU, 0x494BU, 0x494CU, 0x494DU, 0x494EU, 0x494FU, 0x4950U, 0x4951U, 0x4952U, 0x4953U, 0x4954U, 0x4955U, 0x4956U, 0x4957U, 0x4958U, 0x4959U, 0x495AU, 0x4961U, 0x4962U, 0x4963U, 0x4964U, 0x4965U, 0x4966U, 0x4967U, 0x4968U, 0x4969U, 0x496AU, 0x496BU, 0x496CU, 0x496DU, 0x496EU, 0x496FU, 0x4970U, 0x4971U, 0x4972U, 0x4973U, 0x4974U, 0x4975U, 0x4976U, 0x4977U, 0x4978U, 0x4979U, 0x497AU, 0x4930U, 0x4931U, 0x4932U, 0x4933U, 0x4934U, 0x4935U, 0x4936U, 0x4937U, 0x4938U, 0x4939U, 0x492BU, 0x492FU, 0x4A41U, 0x4A42U, 0x4A43U, 0x4A44U, 0x4A45U, 0x4A46U, 0x4A47U, 0x4A48U, 0x4A49U, 0x4A4AU, 0x4A4BU, 0x4A4CU, 0x4A4DU, 0x4A4EU, 0x4A4FU, 0x4A50U, 0x4A51U, 0x4A52U, 0x4A53U, 0x4A54U, 0x4A55U, 0x4A56U, 0x4A57U, 0x4A58U, 0x4A59U, 0x4A5AU, 0x4A61U, 0x4A62U, 0x4A63U, 0x4A64U, 0x4A65U, 0x4A66U, 0x4A67U, 0x4A68U, 0x4A69U, 0x4A6AU, 0x4A6BU, 0x4A6CU, 0x4A6DU, 0x4A6EU, 0x4A6FU, 0x4A70U, 0x4A71U, 0x4A72U, 0x4A73U, 0x4A74U, 0x4A75U, 0x4A76U, 0x4A77U, 0x4A78U, 0x4A79U, 0x4A7AU, 0x4A30U, 0x4A31U, 0x4A32U, 0x4A33U, 0x4A34U, 0x4A35U, 0x4A36U, 0x4A37U, 0x4A38U, 0x4A39U, 0x4A2BU, 0x4A2FU, 0x4B41U, 0x4B42U, 0x4B43U, 0x4B44U, 0x4B45U, 0x4B46U, 0x4B47U, 0x4B48U, 0x4B49U, 0x4B4AU, 0x4B4BU, 0x4B4CU, 0x4B4DU, 0x4B4EU, 0x4B4FU, 0x4B50U, 0x4B51U, 0x4B52U, 0x4B53U, 0x4B54U, 0x4B55U, 0x4B56U, 0x4B57U, 0x4B58U, 0x4B59U, 0x4B5AU, 0x4B61U, 0x4B62U, 0x4B63U, 0x4B64U, 0x4B65U, 0x4B66U, 0x4B67U, 0x4B68U, 0x4B69U, 0x4B6AU, 0x4B6BU, 0x4B6CU, 0x4B6DU, 0x4B6EU, 0x4B6FU, 0x4B70U, 0x4B71U, 0x4B72U, 0x4B73U, 0x4B74U, 0x4B75U, 0x4B76U, 0x4B77U, 0x4B78U, 0x4B79U, 0x4B7AU, 0x4B30U, 0x4B31U, 0x4B32U, 0x4B33U, 0x4B34U, 0x4B35U, 0x4B36U, 0x4B37U, 0x4B38U, 0x4B39U, 0x4B2BU, 0x4B2FU, 0x4C41U, 0x4C42U, 0x4C43U, 0x4C44U, 0x4C45U, 0x4C46U, 0x4C47U, 0x4C48U, 0x4C49U, 0x4C4AU, 0x4C4BU, 0x4C4CU, 0x4C4DU, 0x4C4EU, 0x4C4FU, 0x4C50U, 0x4C51U, 0x4C52U, 0x4C53U, 0x4C54U, 0x4C55U, 0x4C56U, 0x4C57U, 0x4C58U, 0x4C59U, 0x4C5AU, 0x4C61U, 0x4C62U, 0x4C63U, 0x4C64U, 0x4C65U, 0x4C66U, 0x4C67U, 0x4C68U, 0x4C69U, 0x4C6AU, 0x4C6BU, 0x4C6CU, 0x4C6DU, 0x4C6EU, 0x4C6FU, 0x4C70U, 0x4C71U, 0x4C72U, 0x4C73U, 0x4C74U, 0x4C75U, 0x4C76U, 0x4C77U, 0x4C78U, 0x4C79U, 0x4C7AU, 0x4C30U, 0x4C31U, 0x4C32U, 0x4C33U, 0x4C34U, 0x4C35U, 0x4C36U, 0x4C37U, 0x4C38U, 0x4C39U, 0x4C2BU, 0x4C2FU, 0x4D41U, 0x4D42U, 0x4D43U, 0x4D44U, 0x4D45U, 0x4D46U, 0x4D47U, 0x4D48U, 0x4D49U, 0x4D4AU, 0x4D4BU, 0x4D4CU, 0x4D4DU, 0x4D4EU, 0x4D4FU, 0x4D50U, 0x4D51U, 0x4D52U, 0x4D53U, 0x4D54U, 0x4D55U, 0x4D56U, 0x4D57U, 0x4D58U, 0x4D59U, 0x4D5AU, 0x4D61U, 0x4D62U, 0x4D63U, 0x4D64U, 0x4D65U, 0x4D66U, 0x4D67U, 0x4D68U, 0x4D69U, 0x4D6AU, 0x4D6BU, 0x4D6CU, 0x4D6DU, 0x4D6EU, 0x4D6FU, 0x4D70U, 0x4D71U, 0x4D72U, 0x4D73U, 0x4D74U, 0x4D75U, 0x4D76U, 0x4D77U, 0x4D78U, 0x4D79U, 0x4D7AU, 0x4D30U, 0x4D31U, 0x4D32U, 0x4D33U, 0x4D34U, 0x4D35U, 0x4D36U, 0x4D37U, 0x4D38U, 0x4D39U, 0x4D2BU, 0x4D2FU, 0x4E41U, 0x4E42U, 0x4E43U, 0x4E44U, 0x4E45U, 0x4E46U, 0x4E47U, 0x4E48U, 0x4E49U, 0x4E4AU, 0x4E4BU, 0x4E4CU, 0x4E4DU, 0x4E4EU, 0x4E4FU, 0x4E50U, 0x4E51U, 0x4E52U, 0x4E53U, 0x4E54U, 0x4E55U, 0x4E56U, 0x4E57U, 0x4E58U, 0x4E59U, 0x4E5AU, 0x4E61U, 0x4E62U, 0x4E63U, 0x4E64U, 0x4E65U, 0x4E66U, 0x4E67U, 0x4E68U, 0x4E69U, 0x4E6AU, 0x4E6BU, 0x4E6CU, 0x4E6DU, 0x4E6EU, 0x4E6FU, 0x4E70U, 0x4E71U, 0x4E72U, 0x4E73U, 0x4E74U, 0x4E75U, 0x4E76U, 0x4E77U, 0x4E78U, 0x4E79U, 0x4E7AU, 0x4E30U, 0x4E31U, 0x4E32U, 0x4E33U, 0x4E34U, 0x4E35U, 0x4E36U, 0x4E37U, 0x4E38U, 0x4E39U, 0x4E2BU, 0x4E2FU, 0x4F41U, 0x4F42U, 0x4F43U, 0x4F44U, 0x4F45U, 0x4F46U, 0x4F47U, 0x4F48U, 0x4F49U, 0x4F4AU, 0x4F4BU, 0x4F4CU, 0x4F4DU, 0x4F4EU, 0x4F4FU, 0x4F50U, 0x4F51U, 0x4F52U, 0x4F53U, 0x4F54U, 0x4F55U, 0x4F56U, 0x4F57U, 0x4F58U, 0x4F59U, 0x4F5AU, 0x4F61U, 0x4F62U, 0x4F63U, 0x4F64U, 0x4F65U, 0x4F66U, 0x4F67U, 0x4F68U, 0x4F69U, 0x4F6AU, 0x4F6BU, 0x4F6CU, 0x4F6DU, 0x4F6EU, 0x4F6FU, 0x4F70U, 0x4F71U, 0x4F72U, 0x4F73U, 0x4F74U, 0x4F75U, 0x4F76U, 0x4F77U, 0x4F78U, 0x4F79U, 0x4F7AU, 0x4F30U, 0x4F31U, 0x4F32U, 0x4F33U, 0x4F34U, 0x4F35U, 0x4F36U, 0x4F37U, 0x4F38U, 0x4F39U, 0x4F2BU, 0x4F2FU, 0x5041U, 0x5042U, 0x5043U, 0x5044U, 0x5045U, 0x5046U, 0x5047U, 0x5048U, 0x5049U, 0x504AU, 0x504BU, 0x504CU, 0x504DU, 0x504EU, 0x504FU, 0x5050U, 0x5051U, 0x5052U, 0x5053U, 0x5054U, 0x5055U, 0x5056U, 0x5057U, 0x5058U, 0x5059U, 0x505AU, 0x5061U, 0x5062U, 0x5063U, 0x5064U, 0x5065U, 0x5066U, 0x5067U, 0x5068U, 0x5069U, 0x506AU, 0x506BU, 0x506CU, 0x506DU, 0x506EU, 0x506FU, 0x5070U, 0x5071U, 0x5072U, 0x5073U, 0x5074U, 0x5075U, 0x5076U, 0x5077U, 0x5078U, 0x5079U, 0x507AU, 0x5030U, 0x5031U, 0x5032U, 0x5033U, 0x5034U, 0x5035U, 0x5036U, 0x5037U, 0x5038U, 0x5039U, 0x502BU, 0x502FU, 0x5141U, 0x5142U, 0x5143U, 0x5144U, 0x5145U, 0x5146U, 0x5147U, 0x5148U, 0x5149U, 0x514AU, 0x514BU, 0x514CU, 0x514DU, 0x514EU, 0x514FU, 0x5150U, 0x5151U, 0x5152U, 0x5153U, 0x5154U, 0x5155U, 0x5156U, 0x5157U, 0x5158U, 0x5159U, 0x515AU, 0x5161U, 0x5162U, 0x5163U, 0x5164U, 0x5165U, 0x5166U, 0x5167U, 0x5168U, 0x5169U, 0x516AU, 0x516BU, 0x516CU, 0x516DU, 0x516EU, 0x516FU, 0x5170U, 0x5171U, 0x5172U, 0x5173U, 0x5174U, 0x5175U, 0x5176U, 0x5177U, 0x5178U, 0x5179U, 0x517AU, 0x5130U, 0x5131U, 0x5132U, 0x5133U, 0x5134U, 0x5135U, 0x5136U, 0x5137U, 0x5138U, 0x5139U, 0x512BU, 0x512FU, 0x5241U, 0x5242U, 0x5243U, 0x5244U, 0x5245U, 0x5246U, 0x5247U, 0x5248U, 0x5249U, 0x524AU, 0x524BU, 0x524CU, 0x524DU, 0x524EU, 0x524FU, 0x5250U, 0x5251U, 0x5252U, 0x5253U, 0x5254U, 0x5255U, 0x5256U, 0x5257U, 0x5258U, 0x5259U, 0x525AU, 0x5261U, 0x5262U, 0x5263U, 0x5264U, 0x5265U, 0x5266U, 0x5267U, 0x5268U, 0x5269U, 0x526AU, 0x526BU, 0x526CU, 0x526DU, 0x526EU, 0x526FU, 0x5270U, 0x5271U, 0x5272U, 0x5273U, 0x5274U, 0x5275U, 0x5276U, 0x5277U, 0x5278U, 0x5279U, 0x527AU, 0x5230U, 0x5231U, 0x5232U, 0x5233U, 0x5234U, 0x5235U, 0x5236U, 0x5237U, 0x5238U, 0x5239U, 0x522BU, 0x522FU, 0x5341U, 0x5342U, 0x5343U, 0x5344U, 0x5345U, 0x5346U, 0x5347U, 0x5348U, 0x5349U, 0x534AU, 0x534BU, 0x534CU, 0x534DU, 0x534EU, 0x534FU, 0x5350U, 0x5351U, 0x5352U, 0x5353U, 0x5354U, 0x5355U, 0x5356U, 0x5357U, 0x5358U, 0x5359U, 0x535AU, 0x5361U, 0x5362U, 0x5363U, 0x5364U, 0x5365U, 0x5366U, 0x5367U, 0x5368U, 0x5369U, 0x536AU, 0x536BU, 0x536CU, 0x536DU, 0x536EU, 0x536FU, 0x5370U, 0x5371U, 0x5372U, 0x5373U, 0x5374U, 0x5375U, 0x5376U, 0x5377U, 0x5378U, 0x5379U, 0x537AU, 0x5330U, 0x5331U, 0x5332U, 0x5333U, 0x5334U, 0x5335U, 0x5336U, 0x5337U, 0x5338U, 0x5339U, 0x532BU, 0x532FU, 0x5441U, 0x5442U, 0x5443U, 0x5444U, 0x5445U, 0x5446U, 0x5447U, 0x5448U, 0x5449U, 0x544AU, 0x544BU, 0x544CU, 0x544DU, 0x544EU, 0x544FU, 0x5450U, 0x5451U, 0x5452U, 0x5453U, 0x5454U, 0x5455U, 0x5456U, 0x5457U, 0x5458U, 0x5459U, 0x545AU, 0x5461U, 0x5462U, 0x5463U, 0x5464U, 0x5465U, 0x5466U, 0x5467U, 0x5468U, 0x5469U, 0x546AU, 0x546BU, 0x546CU, 0x546DU, 0x546EU, 0x546FU, 0x5470U, 0x5471U, 0x5472U, 0x5473U, 0x5474U, 0x5475U, 0x5476U, 0x5477U, 0x5478U, 0x5479U, 0x547AU, 0x5430U, 0x5431U, 0x5432U, 0x5433U, 0x5434U, 0x5435U, 0x5436U, 0x5437U, 0x5438U, 0x5439U, 0x542BU, 0x542FU, 0x5541U, 0x5542U, 0x5543U, 0x5544U, 0x5545U, 0x5546U, 0x5547U, 0x5548U, 0x5549U, 0x554AU, 0x554BU, 0x554CU, 0x554DU, 0x554EU, 0x554FU, 0x5550U, 0x5551U, 0x5552U, 0x5553U, 0x5554U, 0x5555U, 0x5556U, 0x5557U, 0x5558U, 0x5559U, 0x555AU, 0x5561U, 0x5562U, 0x5563U, 0x5564U, 0x5565U, 0x5566U, 0x5567U, 0x5568U, 0x5569U, 0x556AU, 0x556BU, 0x556CU, 0x556DU, 0x556EU, 0x556FU, 0x5570U, 0x5571U, 0x5572U, 0x5573U, 0x5574U, 0x5575U, 0x5576U, 0x5577U, 0x5578U, 0x5579U, 0x557AU, 0x5530U, 0x5531U, 0x5532U, 0x5533U, 0x5534U, 0x5535U, 0x5536U, 0x5537U, 0x5538U, 0x5539U, 0x552BU, 0x552FU, 0x5641U, 0x5642U, 0x5643U, 0x5644U, 0x5645U, 0x5646U, 0x5647U, 0x5648U, 0x5649U, 0x564AU, 0x564BU, 0x564CU, 0x564DU, 0x564EU, 0x564FU, 0x5650U, 0x5651U, 0x5652U, 0x5653U, 0x5654U, 0x5655U, 0x5656U, 0x5657U, 0x5658U, 0x5659U, 0x565AU, 0x5661U, 0x5662U, 0x5663U, 0x5664U, 0x5665U, 0x5666U, 0x5667U, 0x5668U, 0x5669U, 0x566AU, 0x566BU, 0x566CU, 0x566DU, 0x566EU, 0x566FU, 0x5670U, 0x5671U, 0x5672U, 0x5673U, 0x5674U, 0x5675U, 0x5676U, 0x5677U, 0x5678U, 0x5679U, 0x567AU, 0x5630U, 0x5631U, 0x5632U, 0x5633U, 0x5634U, 0x5635U, 0x5636U, 0x5637U, 0x5638U, 0x5639U, 0x562BU, 0x562FU, 0x5741U, 0x5742U, 0x5743U, 0x5744U, 0x5745U, 0x5746U, 0x5747U, 0x5748U, 0x5749U, 0x574AU, 0x574BU, 0x574CU, 0x574DU, 0x574EU, 0x574FU, 0x5750U, 0x5751U, 0x5752U, 0x5753U, 0x5754U, 0x5755U, 0x5756U, 0x5757U, 0x5758U, 0x5759U, 0x575AU, 0x5761U, 0x5762U, 0x5763U, 0x5764U, 0x5765U, 0x5766U, 0x5767U, 0x5768U, 0x5769U, 0x576AU, 0x576BU, 0x576CU, 0x576DU, 0x576EU, 0x576FU, 0x5770U, 0x5771U, 0x5772U, 0x5773U, 0x5774U, 0x5775U, 0x5776U, 0x5777U, 0x5778U, 0x5779U, 0x577AU, 0x5730U, 0x5731U, 0x5732U, 0x5733U, 0x5734U, 0x5735U, 0x5736U, 0x5737U, 0x5738U, 0x5739U, 0x572BU, 0x572FU, 0x5841U, 0x5842U, 0x5843U, 0x5844U, 0x5845U, 0x5846U, 0x5847U, 0x5848U, 0x5849U, 0x584AU, 0x584BU, 0x584CU, 0x584DU, 0x584EU, 0x584FU, 0x5850U, 0x5851U, 0x5852U, 0x5853U, 0x5854U, 0x5855U, 0x5856U, 0x5857U, 0x5858U, 0x5859U, 0x585AU, 0x5861U, 0x5862U, 0x5863U, 0x5864U, 0x5865U, 0x5866U, 0x5867U, 0x5868U, 0x5869U, 0x586AU, 0x586BU, 0x586CU, 0x586DU, 0x586EU, 0x586FU, 0x5870U, 0x5871U, 0x5872U, 0x5873U, 0x5874U, 0x5875U, 0x5876U, 0x5877U, 0x5878U, 0x5879U, 0x587AU, 0x5830U, 0x5831U, 0x5832U, 0x5833U, 0x5834U, 0x5835U, 0x5836U, 0x5837U, 0x5838U, 0x5839U, 0x582BU, 0x582FU, 0x5941U, 0x5942U, 0x5943U, 0x5944U, 0x5945U, 0x5946U, 0x5947U, 0x5948U, 0x5949U, 0x594AU, 0x594BU, 0x594CU, 0x594DU, 0x594EU, 0x594FU, 0x5950U, 0x5951U, 0x5952U, 0x5953U, 0x5954U, 0x5955U, 0x5956U, 0x5957U, 0x5958U, 0x5959U, 0x595AU, 0x5961U, 0x5962U, 0x5963U, 0x5964U, 0x5965U, 0x5966U, 0x5967U, 0x5968U, 0x5969U, 0x596AU, 0x596BU, 0x596CU, 0x596DU, 0x596EU, 0x596FU, 0x5970U, 0x5971U, 0x5972U, 0x5973U, 0x5974U, 0x5975U, 0x5976U, 0x5977U, 0x5978U, 0x5979U, 0x597AU, 0x5930U, 0x5931U, 0x5932U, 0x5933U, 0x5934U, 0x5935U, 0x5936U, 0x5937U, 0x5938U, 0x5939U, 0x592BU, 0x592FU, 0x5A41U, 0x5A42U, 0x5A43U, 0x5A44U, 0x5A45U, 0x5A46U, 0x5A47U, 0x5A48U, 0x5A49U, 0x5A4AU, 0x5A4BU, 0x5A4CU, 0x5A4DU, 0x5A4EU, 0x5A4FU, 0x5A50U, 0x5A51U, 0x5A52U, 0x5A53U, 0x5A54U, 0x5A55U, 0x5A56U, 0x5A57U, 0x5A58U, 0x5A59U, 0x5A5AU, 0x5A61U, 0x5A62U, 0x5A63U, 0x5A64U, 0x5A65U, 0x5A66U, 0x5A67U, 0x5A68U, 0x5A69U, 0x5A6AU, 0x5A6BU, 0x5A6CU, 0x5A6DU, 0x5A6EU, 0x5A6FU, 0x5A70U, 0x5A71U, 0x5A72U, 0x5A73U, 0x5A74U, 0x5A75U, 0x5A76U, 0x5A77U, 0x5A78U, 0x5A79U, 0x5A7AU, 0x5A30U, 0x5A31U, 0x5A32U, 0x5A33U, 0x5A34U, 0x5A35U, 0x5A36U, 0x5A37U, 0x5A38U, 0x5A39U, 0x5A2BU, 0x5A2FU, 0x6141U, 0x6142U, 0x6143U, 0x6144U, 0x6145U, 0x6146U, 0x6147U, 0x6148U, 0x6149U, 0x614AU, 0x614BU, 0x614CU, 0x614DU, 0x614EU, 0x614FU, 0x6150U, 0x6151U, 0x6152U, 0x6153U, 0x6154U, 0x6155U, 0x6156U, 0x6157U, 0x6158U, 0x6159U, 0x615AU, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U, 0x6167U, 0x6168U, 0x6169U, 0x616AU, 0x616BU, 0x616CU, 0x616DU, 0x616EU, 0x616FU, 0x6170U, 0x6171U, 0x6172U, 0x6173U, 0x6174U, 0x6175U, 0x6176U, 0x6177U, 0x6178U, 0x6179U, 0x617AU, 0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U, 0x6138U, 0x6139U, 0x612BU, 0x612FU, 0x6241U, 0x6242U, 0x6243U, 0x6244U, 0x6245U, 0x6246U, 0x6247U, 0x6248U, 0x6249U, 0x624AU, 0x624BU, 0x624CU, 0x624DU, 0x624EU, 0x624FU, 0x6250U, 0x6251U, 0x6252U, 0x6253U, 0x6254U, 0x6255U, 0x6256U, 0x6257U, 0x6258U, 0x6259U, 0x625AU, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U, 0x6267U, 0x6268U, 0x6269U, 0x626AU, 0x626BU, 0x626CU, 0x626DU, 0x626EU, 0x626FU, 0x6270U, 0x6271U, 0x6272U, 0x6273U, 0x6274U, 0x6275U, 0x6276U, 0x6277U, 0x6278U, 0x6279U, 0x627AU, 0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U, 0x6238U, 0x6239U, 0x622BU, 0x622FU, 0x6341U, 0x6342U, 0x6343U, 0x6344U, 0x6345U, 0x6346U, 0x6347U, 0x6348U, 0x6349U, 0x634AU, 0x634BU, 0x634CU, 0x634DU, 0x634EU, 0x634FU, 0x6350U, 0x6351U, 0x6352U, 0x6353U, 0x6354U, 0x6355U, 0x6356U, 0x6357U, 0x6358U, 0x6359U, 0x635AU, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U, 0x6367U, 0x6368U, 0x6369U, 0x636AU, 0x636BU, 0x636CU, 0x636DU, 0x636EU, 0x636FU, 0x6370U, 0x6371U, 0x6372U, 0x6373U, 0x6374U, 0x6375U, 0x6376U, 0x6377U, 0x6378U, 0x6379U, 0x637AU, 0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U, 0x6338U, 0x6339U, 0x632BU, 0x632FU, 0x6441U, 0x6442U, 0x6443U, 0x6444U, 0x6445U, 0x6446U, 0x6447U, 0x6448U, 0x6449U, 0x644AU, 0x644BU, 0x644CU, 0x644DU, 0x644EU, 0x644FU, 0x6450U, 0x6451U, 0x6452U, 0x6453U, 0x6454U, 0x6455U, 0x6456U, 0x6457U, 0x6458U, 0x6459U, 0x645AU, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U, 0x6467U, 0x6468U, 0x6469U, 0x646AU, 0x646BU, 0x646CU, 0x646DU, 0x646EU, 0x646FU, 0x6470U, 0x6471U, 0x6472U, 0x6473U, 0x6474U, 0x6475U, 0x6476U, 0x6477U, 0x6478U, 0x6479U, 0x647AU, 0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U, 0x6438U, 0x6439U, 0x642BU, 0x642FU, 0x6541U, 0x6542U, 0x6543U, 0x6544U, 0x6545U, 0x6546U, 0x6547U, 0x6548U, 0x6549U, 0x654AU, 0x654BU, 0x654CU, 0x654DU, 0x654EU, 0x654FU, 0x6550U, 0x6551U, 0x6552U, 0x6553U, 0x6554U, 0x6555U, 0x6556U, 0x6557U, 0x6558U, 0x6559U, 0x655AU, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U, 0x6567U, 0x6568U, 0x6569U, 0x656AU, 0x656BU, 0x656CU, 0x656DU, 0x656EU, 0x656FU, 0x6570U, 0x6571U, 0x6572U, 0x6573U, 0x6574U, 0x6575U, 0x6576U, 0x6577U, 0x6578U, 0x6579U, 0x657AU, 0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U, 0x6538U, 0x6539U, 0x652BU, 0x652FU, 0x6641U, 0x6642U, 0x6643U, 0x6644U, 0x6645U, 0x6646U, 0x6647U, 0x6648U, 0x6649U, 0x664AU, 0x664BU, 0x664CU, 0x664DU, 0x664EU, 0x664FU, 0x6650U, 0x6651U, 0x6652U, 0x6653U, 0x6654U, 0x6655U, 0x6656U, 0x6657U, 0x6658U, 0x6659U, 0x665AU, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U, 0x6667U, 0x6668U, 0x6669U, 0x666AU, 0x666BU, 0x666CU, 0x666DU, 0x666EU, 0x666FU, 0x6670U, 0x6671U, 0x6672U, 0x6673U, 0x6674U, 0x6675U, 0x6676U, 0x6677U, 0x6678U, 0x6679U, 0x667AU, 0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U, 0x6638U, 0x6639U, 0x662BU, 0x662FU, 0x6741U, 0x6742U, 0x6743U, 0x6744U, 0x6745U, 0x6746U, 0x6747U, 0x6748U, 0x6749U, 0x674AU, 0x674BU, 0x674CU, 0x674DU, 0x674EU, 0x674FU, 0x6750U, 0x6751U, 0x6752U, 0x6753U, 0x6754U, 0x6755U, 0x6756U, 0x6757U, 0x6758U, 0x6759U, 0x675AU, 0x6761U, 0x6762U, 0x6763U, 0x6764U, 0x6765U, 0x6766U, 0x6767U, 0x6768U, 0x6769U, 0x676AU, 0x676BU, 0x676CU, 0x676DU, 0x676EU, 0x676FU, 0x6770U, 0x6771U, 0x6772U, 0x6773U, 0x6774U, 0x6775U, 0x6776U, 0x6777U, 0x6778U, 0x6779U, 0x677AU, 0x6730U, 0x6731U, 0x6732U, 0x6733U, 0x6734U, 0x6735U, 0x6736U, 0x6737U, 0x6738U, 0x6739U, 0x672BU, 0x672FU, 0x6841U, 0x6842U, 0x6843U, 0x6844U, 0x6845U, 0x6846U, 0x6847U, 0x6848U, 0x6849U, 0x684AU, 0x684BU, 0x684CU, 0x684DU, 0x684EU, 0x684FU, 0x6850U, 0x6851U, 0x6852U, 0x6853U, 0x6854U, 0x6855U, 0x6856U, 0x6857U, 0x6858U, 0x6859U, 0x685AU, 0x6861U, 0x6862U, 0x6863U, 0x6864U, 0x6865U, 0x6866U, 0x6867U, 0x6868U, 0x6869U, 0x686AU, 0x686BU, 0x686CU, 0x686DU, 0x686EU, 0x686FU, 0x6870U, 0x6871U, 0x6872U, 0x6873U, 0x6874U, 0x6875U, 0x6876U, 0x6877U, 0x6878U, 0x6879U, 0x687AU, 0x6830U, 0x6831U, 0x6832U, 0x6833U, 0x6834U, 0x6835U, 0x6836U, 0x6837U, 0x6838U, 0x6839U, 0x682BU, 0x682FU, 0x6941U, 0x6942U, 0x6943U, 0x6944U, 0x6945U, 0x6946U, 0x6947U, 0x6948U, 0x6949U, 0x694AU, 0x694BU, 0x694CU, 0x694DU, 0x694EU, 0x694FU, 0x6950U, 0x6951U, 0x6952U, 0x6953U, 0x6954U, 0x6955U, 0x6956U, 0x6957U, 0x6958U, 0x6959U, 0x695AU, 0x6961U, 0x6962U, 0x6963U, 0x6964U, 0x6965U, 0x6966U, 0x6967U, 0x6968U, 0x6969U, 0x696AU, 0x696BU, 0x696CU, 0x696DU, 0x696EU, 0x696FU, 0x6970U, 0x6971U, 0x6972U, 0x6973U, 0x6974U, 0x6975U, 0x6976U, 0x6977U, 0x6978U, 0x6979U, 0x697AU, 0x6930U, 0x6931U, 0x6932U, 0x6933U, 0x6934U, 0x6935U, 0x6936U, 0x6937U, 0x6938U, 0x6939U, 0x692BU, 0x692FU, 0x6A41U, 0x6A42U, 0x6A43U, 0x6A44U, 0x6A45U, 0x6A46U, 0x6A47U, 0x6A48U, 0x6A49U, 0x6A4AU, 0x6A4BU, 0x6A4CU, 0x6A4DU, 0x6A4EU, 0x6A4FU, 0x6A50U, 0x6A51U, 0x6A52U, 0x6A53U, 0x6A54U, 0x6A55U, 0x6A56U, 0x6A57U, 0x6A58U, 0x6A59U, 0x6A5AU, 0x6A61U, 0x6A62U, 0x6A63U, 0x6A64U, 0x6A65U, 0x6A66U, 0x6A67U, 0x6A68U, 0x6A69U, 0x6A6AU, 0x6A6BU, 0x6A6CU, 0x6A6DU, 0x6A6EU, 0x6A6FU, 0x6A70U, 0x6A71U, 0x6A72U, 0x6A73U, 0x6A74U, 0x6A75U, 0x6A76U, 0x6A77U, 0x6A78U, 0x6A79U, 0x6A7AU, 0x6A30U, 0x6A31U, 0x6A32U, 0x6A33U, 0x6A34U, 0x6A35U, 0x6A36U, 0x6A37U, 0x6A38U, 0x6A39U, 0x6A2BU, 0x6A2FU, 0x6B41U, 0x6B42U, 0x6B43U, 0x6B44U, 0x6B45U, 0x6B46U, 0x6B47U, 0x6B48U, 0x6B49U, 0x6B4AU, 0x6B4BU, 0x6B4CU, 0x6B4DU, 0x6B4EU, 0x6B4FU, 0x6B50U, 0x6B51U, 0x6B52U, 0x6B53U, 0x6B54U, 0x6B55U, 0x6B56U, 0x6B57U, 0x6B58U, 0x6B59U, 0x6B5AU, 0x6B61U, 0x6B62U, 0x6B63U, 0x6B64U, 0x6B65U, 0x6B66U, 0x6B67U, 0x6B68U, 0x6B69U, 0x6B6AU, 0x6B6BU, 0x6B6CU, 0x6B6DU, 0x6B6EU, 0x6B6FU, 0x6B70U, 0x6B71U, 0x6B72U, 0x6B73U, 0x6B74U, 0x6B75U, 0x6B76U, 0x6B77U, 0x6B78U, 0x6B79U, 0x6B7AU, 0x6B30U, 0x6B31U, 0x6B32U, 0x6B33U, 0x6B34U, 0x6B35U, 0x6B36U, 0x6B37U, 0x6B38U, 0x6B39U, 0x6B2BU, 0x6B2FU, 0x6C41U, 0x6C42U, 0x6C43U, 0x6C44U, 0x6C45U, 0x6C46U, 0x6C47U, 0x6C48U, 0x6C49U, 0x6C4AU, 0x6C4BU, 0x6C4CU, 0x6C4DU, 0x6C4EU, 0x6C4FU, 0x6C50U, 0x6C51U, 0x6C52U, 0x6C53U, 0x6C54U, 0x6C55U, 0x6C56U, 0x6C57U, 0x6C58U, 0x6C59U, 0x6C5AU, 0x6C61U, 0x6C62U, 0x6C63U, 0x6C64U, 0x6C65U, 0x6C66U, 0x6C67U, 0x6C68U, 0x6C69U, 0x6C6AU, 0x6C6BU, 0x6C6CU, 0x6C6DU, 0x6C6EU, 0x6C6FU, 0x6C70U, 0x6C71U, 0x6C72U, 0x6C73U, 0x6C74U, 0x6C75U, 0x6C76U, 0x6C77U, 0x6C78U, 0x6C79U, 0x6C7AU, 0x6C30U, 0x6C31U, 0x6C32U, 0x6C33U, 0x6C34U, 0x6C35U, 0x6C36U, 0x6C37U, 0x6C38U, 0x6C39U, 0x6C2BU, 0x6C2FU, 0x6D41U, 0x6D42U, 0x6D43U, 0x6D44U, 0x6D45U, 0x6D46U, 0x6D47U, 0x6D48U, 0x6D49U, 0x6D4AU, 0x6D4BU, 0x6D4CU, 0x6D4DU, 0x6D4EU, 0x6D4FU, 0x6D50U, 0x6D51U, 0x6D52U, 0x6D53U, 0x6D54U, 0x6D55U, 0x6D56U, 0x6D57U, 0x6D58U, 0x6D59U, 0x6D5AU, 0x6D61U, 0x6D62U, 0x6D63U, 0x6D64U, 0x6D65U, 0x6D66U, 0x6D67U, 0x6D68U, 0x6D69U, 0x6D6AU, 0x6D6BU, 0x6D6CU, 0x6D6DU, 0x6D6EU, 0x6D6FU, 0x6D70U, 0x6D71U, 0x6D72U, 0x6D73U, 0x6D74U, 0x6D75U, 0x6D76U, 0x6D77U, 0x6D78U, 0x6D79U, 0x6D7AU, 0x6D30U, 0x6D31U, 0x6D32U, 0x6D33U, 0x6D34U, 0x6D35U, 0x6D36U, 0x6D37U, 0x6D38U, 0x6D39U, 0x6D2BU, 0x6D2FU, 0x6E41U, 0x6E42U, 0x6E43U, 0x6E44U, 0x6E45U, 0x6E46U, 0x6E47U, 0x6E48U, 0x6E49U, 0x6E4AU, 0x6E4BU, 0x6E4CU, 0x6E4DU, 0x6E4EU, 0x6E4FU, 0x6E50U, 0x6E51U, 0x6E52U, 0x6E53U, 0x6E54U, 0x6E55U, 0x6E56U, 0x6E57U, 0x6E58U, 0x6E59U, 0x6E5AU, 0x6E61U, 0x6E62U, 0x6E63U, 0x6E64U, 0x6E65U, 0x6E66U, 0x6E67U, 0x6E68U, 0x6E69U, 0x6E6AU, 0x6E6BU, 0x6E6CU, 0x6E6DU, 0x6E6EU, 0x6E6FU, 0x6E70U, 0x6E71U, 0x6E72U, 0x6E73U, 0x6E74U, 0x6E75U, 0x6E76U, 0x6E77U, 0x6E78U, 0x6E79U, 0x6E7AU, 0x6E30U, 0x6E31U, 0x6E32U, 0x6E33U, 0x6E34U, 0x6E35U, 0x6E36U, 0x6E37U, 0x6E38U, 0x6E39U, 0x6E2BU, 0x6E2FU, 0x6F41U, 0x6F42U, 0x6F43U, 0x6F44U, 0x6F45U, 0x6F46U, 0x6F47U, 0x6F48U, 0x6F49U, 0x6F4AU, 0x6F4BU, 0x6F4CU, 0x6F4DU, 0x6F4EU, 0x6F4FU, 0x6F50U, 0x6F51U, 0x6F52U, 0x6F53U, 0x6F54U, 0x6F55U, 0x6F56U, 0x6F57U, 0x6F58U, 0x6F59U, 0x6F5AU, 0x6F61U, 0x6F62U, 0x6F63U, 0x6F64U, 0x6F65U, 0x6F66U, 0x6F67U, 0x6F68U, 0x6F69U, 0x6F6AU, 0x6F6BU, 0x6F6CU, 0x6F6DU, 0x6F6EU, 0x6F6FU, 0x6F70U, 0x6F71U, 0x6F72U, 0x6F73U, 0x6F74U, 0x6F75U, 0x6F76U, 0x6F77U, 0x6F78U, 0x6F79U, 0x6F7AU, 0x6F30U, 0x6F31U, 0x6F32U, 0x6F33U, 0x6F34U, 0x6F35U, 0x6F36U, 0x6F37U, 0x6F38U, 0x6F39U, 0x6F2BU, 0x6F2FU, 0x7041U, 0x7042U, 0x7043U, 0x7044U, 0x7045U, 0x7046U, 0x7047U, 0x7048U, 0x7049U, 0x704AU, 0x704BU, 0x704CU, 0x704DU, 0x704EU, 0x704FU, 0x7050U, 0x7051U, 0x7052U, 0x7053U, 0x7054U, 0x7055U, 0x7056U, 0x7057U, 0x7058U, 0x7059U, 0x705AU, 0x7061U, 0x7062U, 0x7063U, 0x7064U, 0x7065U, 0x7066U, 0x7067U, 0x7068U, 0x7069U, 0x706AU, 0x706BU, 0x706CU, 0x706DU, 0x706EU, 0x706FU, 0x7070U, 0x7071U, 0x7072U, 0x7073U, 0x7074U, 0x7075U, 0x7076U, 0x7077U, 0x7078U, 0x7079U, 0x707AU, 0x7030U, 0x7031U, 0x7032U, 0x7033U, 0x7034U, 0x7035U, 0x7036U, 0x7037U, 0x7038U, 0x7039U, 0x702BU, 0x702FU, 0x7141U, 0x7142U, 0x7143U, 0x7144U, 0x7145U, 0x7146U, 0x7147U, 0x7148U, 0x7149U, 0x714AU, 0x714BU, 0x714CU, 0x714DU, 0x714EU, 0x714FU, 0x7150U, 0x7151U, 0x7152U, 0x7153U, 0x7154U, 0x7155U, 0x7156U, 0x7157U, 0x7158U, 0x7159U, 0x715AU, 0x7161U, 0x7162U, 0x7163U, 0x7164U, 0x7165U, 0x7166U, 0x7167U, 0x7168U, 0x7169U, 0x716AU, 0x716BU, 0x716CU, 0x716DU, 0x716EU, 0x716FU, 0x7170U, 0x7171U, 0x7172U, 0x7173U, 0x7174U, 0x7175U, 0x7176U, 0x7177U, 0x7178U, 0x7179U, 0x717AU, 0x7130U, 0x7131U, 0x7132U, 0x7133U, 0x7134U, 0x7135U, 0x7136U, 0x7137U, 0x7138U, 0x7139U, 0x712BU, 0x712FU, 0x7241U, 0x7242U, 0x7243U, 0x7244U, 0x7245U, 0x7246U, 0x7247U, 0x7248U, 0x7249U, 0x724AU, 0x724BU, 0x724CU, 0x724DU, 0x724EU, 0x724FU, 0x7250U, 0x7251U, 0x7252U, 0x7253U, 0x7254U, 0x7255U, 0x7256U, 0x7257U, 0x7258U, 0x7259U, 0x725AU, 0x7261U, 0x7262U, 0x7263U, 0x7264U, 0x7265U, 0x7266U, 0x7267U, 0x7268U, 0x7269U, 0x726AU, 0x726BU, 0x726CU, 0x726DU, 0x726EU, 0x726FU, 0x7270U, 0x7271U, 0x7272U, 0x7273U, 0x7274U, 0x7275U, 0x7276U, 0x7277U, 0x7278U, 0x7279U, 0x727AU, 0x7230U, 0x7231U, 0x7232U, 0x7233U, 0x7234U, 0x7235U, 0x7236U, 0x7237U, 0x7238U, 0x7239U, 0x722BU, 0x722FU, 0x7341U, 0x7342U, 0x7343U, 0x7344U, 0x7345U, 0x7346U, 0x7347U, 0x7348U, 0x7349U, 0x734AU, 0x734BU, 0x734CU, 0x734DU, 0x734EU, 0x734FU, 0x7350U, 0x7351U, 0x7352U, 0x7353U, 0x7354U, 0x7355U, 0x7356U, 0x7357U, 0x7358U, 0x7359U, 0x735AU, 0x7361U, 0x7362U, 0x7363U, 0x7364U, 0x7365U, 0x7366U, 0x7367U, 0x7368U, 0x7369U, 0x736AU, 0x736BU, 0x736CU, 0x736DU, 0x736EU, 0x736FU, 0x7370U, 0x7371U, 0x7372U, 0x7373U, 0x7374U, 0x7375U, 0x7376U, 0x7377U, 0x7378U, 0x7379U, 0x737AU, 0x7330U, 0x7331U, 0x7332U, 0x7333U, 0x7334U, 0x7335U, 0x7336U, 0x7337U, 0x7338U, 0x7339U, 0x732BU, 0x732FU, 0x7441U, 0x7442U, 0x7443U, 0x7444U, 0x7445U, 0x7446U, 0x7447U, 0x7448U, 0x7449U, 0x744AU, 0x744BU, 0x744CU, 0x744DU, 0x744EU, 0x744FU, 0x7450U, 0x7451U, 0x7452U, 0x7453U, 0x7454U, 0x7455U, 0x7456U, 0x7457U, 0x7458U, 0x7459U, 0x745AU, 0x7461U, 0x7462U, 0x7463U, 0x7464U, 0x7465U, 0x7466U, 0x7467U, 0x7468U, 0x7469U, 0x746AU, 0x746BU, 0x746CU, 0x746DU, 0x746EU, 0x746FU, 0x7470U, 0x7471U, 0x7472U, 0x7473U, 0x7474U, 0x7475U, 0x7476U, 0x7477U, 0x7478U, 0x7479U, 0x747AU, 0x7430U, 0x7431U, 0x7432U, 0x7433U, 0x7434U, 0x7435U, 0x7436U, 0x7437U, 0x7438U, 0x7439U, 0x742BU, 0x742FU, 0x7541U, 0x7542U, 0x7543U, 0x7544U, 0x7545U, 0x7546U, 0x7547U, 0x7548U, 0x7549U, 0x754AU, 0x754BU, 0x754CU, 0x754DU, 0x754EU, 0x754FU, 0x7550U, 0x7551U, 0x7552U, 0x7553U, 0x7554U, 0x7555U, 0x7556U, 0x7557U, 0x7558U, 0x7559U, 0x755AU, 0x7561U, 0x7562U, 0x7563U, 0x7564U, 0x7565U, 0x7566U, 0x7567U, 0x7568U, 0x7569U, 0x756AU, 0x756BU, 0x756CU, 0x756DU, 0x756EU, 0x756FU, 0x7570U, 0x7571U, 0x7572U, 0x7573U, 0x7574U, 0x7575U, 0x7576U, 0x7577U, 0x7578U, 0x7579U, 0x757AU, 0x7530U, 0x7531U, 0x7532U, 0x7533U, 0x7534U, 0x7535U, 0x7536U, 0x7537U, 0x7538U, 0x7539U, 0x752BU, 0x752FU, 0x7641U, 0x7642U, 0x7643U, 0x7644U, 0x7645U, 0x7646U, 0x7647U, 0x7648U, 0x7649U, 0x764AU, 0x764BU, 0x764CU, 0x764DU, 0x764EU, 0x764FU, 0x7650U, 0x7651U, 0x7652U, 0x7653U, 0x7654U, 0x7655U, 0x7656U, 0x7657U, 0x7658U, 0x7659U, 0x765AU, 0x7661U, 0x7662U, 0x7663U, 0x7664U, 0x7665U, 0x7666U, 0x7667U, 0x7668U, 0x7669U, 0x766AU, 0x766BU, 0x766CU, 0x766DU, 0x766EU, 0x766FU, 0x7670U, 0x7671U, 0x7672U, 0x7673U, 0x7674U, 0x7675U, 0x7676U, 0x7677U, 0x7678U, 0x7679U, 0x767AU, 0x7630U, 0x7631U, 0x7632U, 0x7633U, 0x7634U, 0x7635U, 0x7636U, 0x7637U, 0x7638U, 0x7639U, 0x762BU, 0x762FU, 0x7741U, 0x7742U, 0x7743U, 0x7744U, 0x7745U, 0x7746U, 0x7747U, 0x7748U, 0x7749U, 0x774AU, 0x774BU, 0x774CU, 0x774DU, 0x774EU, 0x774FU, 0x7750U, 0x7751U, 0x7752U, 0x7753U, 0x7754U, 0x7755U, 0x7756U, 0x7757U, 0x7758U, 0x7759U, 0x775AU, 0x7761U, 0x7762U, 0x7763U, 0x7764U, 0x7765U, 0x7766U, 0x7767U, 0x7768U, 0x7769U, 0x776AU, 0x776BU, 0x776CU, 0x776DU, 0x776EU, 0x776FU, 0x7770U, 0x7771U, 0x7772U, 0x7773U, 0x7774U, 0x7775U, 0x7776U, 0x7777U, 0x7778U, 0x7779U, 0x777AU, 0x7730U, 0x7731U, 0x7732U, 0x7733U, 0x7734U, 0x7735U, 0x7736U, 0x7737U, 0x7738U, 0x7739U, 0x772BU, 0x772FU, 0x7841U, 0x7842U, 0x7843U, 0x7844U, 0x7845U, 0x7846U, 0x7847U, 0x7848U, 0x7849U, 0x784AU, 0x784BU, 0x784CU, 0x784DU, 0x784EU, 0x784FU, 0x7850U, 0x7851U, 0x7852U, 0x7853U, 0x7854U, 0x7855U, 0x7856U, 0x7857U, 0x7858U, 0x7859U, 0x785AU, 0x7861U, 0x7862U, 0x7863U, 0x7864U, 0x7865U, 0x7866U, 0x7867U, 0x7868U, 0x7869U, 0x786AU, 0x786BU, 0x786CU, 0x786DU, 0x786EU, 0x786FU, 0x7870U, 0x7871U, 0x7872U, 0x7873U, 0x7874U, 0x7875U, 0x7876U, 0x7877U, 0x7878U, 0x7879U, 0x787AU, 0x7830U, 0x7831U, 0x7832U, 0x7833U, 0x7834U, 0x7835U, 0x7836U, 0x7837U, 0x7838U, 0x7839U, 0x782BU, 0x782FU, 0x7941U, 0x7942U, 0x7943U, 0x7944U, 0x7945U, 0x7946U, 0x7947U, 0x7948U, 0x7949U, 0x794AU, 0x794BU, 0x794CU, 0x794DU, 0x794EU, 0x794FU, 0x7950U, 0x7951U, 0x7952U, 0x7953U, 0x7954U, 0x7955U, 0x7956U, 0x7957U, 0x7958U, 0x7959U, 0x795AU, 0x7961U, 0x7962U, 0x7963U, 0x7964U, 0x7965U, 0x7966U, 0x7967U, 0x7968U, 0x7969U, 0x796AU, 0x796BU, 0x796CU, 0x796DU, 0x796EU, 0x796FU, 0x7970U, 0x7971U, 0x7972U, 0x7973U, 0x7974U, 0x7975U, 0x7976U, 0x7977U, 0x7978U, 0x7979U, 0x797AU, 0x7930U, 0x7931U, 0x7932U, 0x7933U, 0x7934U, 0x7935U, 0x7936U, 0x7937U, 0x7938U, 0x7939U, 0x792BU, 0x792FU, 0x7A41U, 0x7A42U, 0x7A43U, 0x7A44U, 0x7A45U, 0x7A46U, 0x7A47U, 0x7A48U, 0x7A49U, 0x7A4AU, 0x7A4BU, 0x7A4CU, 0x7A4DU, 0x7A4EU, 0x7A4FU, 0x7A50U, 0x7A51U, 0x7A52U, 0x7A53U, 0x7A54U, 0x7A55U, 0x7A56U, 0x7A57U, 0x7A58U, 0x7A59U, 0x7A5AU, 0x7A61U, 0x7A62U, 0x7A63U, 0x7A64U, 0x7A65U, 0x7A66U, 0x7A67U, 0x7A68U, 0x7A69U, 0x7A6AU, 0x7A6BU, 0x7A6CU, 0x7A6DU, 0x7A6EU, 0x7A6FU, 0x7A70U, 0x7A71U, 0x7A72U, 0x7A73U, 0x7A74U, 0x7A75U, 0x7A76U, 0x7A77U, 0x7A78U, 0x7A79U, 0x7A7AU, 0x7A30U, 0x7A31U, 0x7A32U, 0x7A33U, 0x7A34U, 0x7A35U, 0x7A36U, 0x7A37U, 0x7A38U, 0x7A39U, 0x7A2BU, 0x7A2FU, 0x3041U, 0x3042U, 0x3043U, 0x3044U, 0x3045U, 0x3046U, 0x3047U, 0x3048U, 0x3049U, 0x304AU, 0x304BU, 0x304CU, 0x304DU, 0x304EU, 0x304FU, 0x3050U, 0x3051U, 0x3052U, 0x3053U, 0x3054U, 0x3055U, 0x3056U, 0x3057U, 0x3058U, 0x3059U, 0x305AU, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U, 0x3067U, 0x3068U, 0x3069U, 0x306AU, 0x306BU, 0x306CU, 0x306DU, 0x306EU, 0x306FU, 0x3070U, 0x3071U, 0x3072U, 0x3073U, 0x3074U, 0x3075U, 0x3076U, 0x3077U, 0x3078U, 0x3079U, 0x307AU, 0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U, 0x3038U, 0x3039U, 0x302BU, 0x302FU, 0x3141U, 0x3142U, 0x3143U, 0x3144U, 0x3145U, 0x3146U, 0x3147U, 0x3148U, 0x3149U, 0x314AU, 0x314BU, 0x314CU, 0x314DU, 0x314EU, 0x314FU, 0x3150U, 0x3151U, 0x3152U, 0x3153U, 0x3154U, 0x3155U, 0x3156U, 0x3157U, 0x3158U, 0x3159U, 0x315AU, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U, 0x3167U, 0x3168U, 0x3169U, 0x316AU, 0x316BU, 0x316CU, 0x316DU, 0x316EU, 0x316FU, 0x3170U, 0x3171U, 0x3172U, 0x3173U, 0x3174U, 0x3175U, 0x3176U, 0x3177U, 0x3178U, 0x3179U, 0x317AU, 0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U, 0x3138U, 0x3139U, 0x312BU, 0x312FU, 0x3241U, 0x3242U, 0x3243U, 0x3244U, 0x3245U, 0x3246U, 0x3247U, 0x3248U, 0x3249U, 0x324AU, 0x324BU, 0x324CU, 0x324DU, 0x324EU, 0x324FU, 0x3250U, 0x3251U, 0x3252U, 0x3253U, 0x3254U, 0x3255U, 0x3256U, 0x3257U, 0x3258U, 0x3259U, 0x325AU, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U, 0x3267U, 0x3268U, 0x3269U, 0x326AU, 0x326BU, 0x326CU, 0x326DU, 0x326EU, 0x326FU, 0x3270U, 0x3271U, 0x3272U, 0x3273U, 0x3274U, 0x3275U, 0x3276U, 0x3277U, 0x3278U, 0x3279U, 0x327AU, 0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U, 0x3238U, 0x3239U, 0x322BU, 0x322FU, 0x3341U, 0x3342U, 0x3343U, 0x3344U, 0x3345U, 0x3346U, 0x3347U, 0x3348U, 0x3349U, 0x334AU, 0x334BU, 0x334CU, 0x334DU, 0x334EU, 0x334FU, 0x3350U, 0x3351U, 0x3352U, 0x3353U, 0x3354U, 0x3355U, 0x3356U, 0x3357U, 0x3358U, 0x3359U, 0x335AU, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U, 0x3367U, 0x3368U, 0x3369U, 0x336AU, 0x336BU, 0x336CU, 0x336DU, 0x336EU, 0x336FU, 0x3370U, 0x3371U, 0x3372U, 0x3373U, 0x3374U, 0x3375U, 0x3376U, 0x3377U, 0x3378U, 0x3379U, 0x337AU, 0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U, 0x3338U, 0x3339U, 0x332BU, 0x332FU, 0x3441U, 0x3442U, 0x3443U, 0x3444U, 0x3445U, 0x3446U, 0x3447U, 0x3448U, 0x3449U, 0x344AU, 0x344BU, 0x344CU, 0x344DU, 0x344EU, 0x344FU, 0x3450U, 0x3451U, 0x3452U, 0x3453U, 0x3454U, 0x3455U, 0x3456U, 0x3457U, 0x3458U, 0x3459U, 0x345AU, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U, 0x3467U, 0x3468U, 0x3469U, 0x346AU, 0x346BU, 0x346CU, 0x346DU, 0x346EU, 0x346FU, 0x3470U, 0x3471U, 0x3472U, 0x3473U, 0x3474U, 0x3475U, 0x3476U, 0x3477U, 0x3478U, 0x3479U, 0x347AU, 0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U, 0x3438U, 0x3439U, 0x342BU, 0x342FU, 0x3541U, 0x3542U, 0x3543U, 0x3544U, 0x3545U, 0x3546U, 0x3547U, 0x3548U, 0x3549U, 0x354AU, 0x354BU, 0x354CU, 0x354DU, 0x354EU, 0x354FU, 0x3550U, 0x3551U, 0x3552U, 0x3553U, 0x3554U, 0x3555U, 0x3556U, 0x3557U, 0x3558U, 0x3559U, 0x355AU, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U, 0x3567U, 0x3568U, 0x3569U, 0x356AU, 0x356BU, 0x356CU, 0x356DU, 0x356EU, 0x356FU, 0x3570U, 0x3571U, 0x3572U, 0x3573U, 0x3574U, 0x3575U, 0x3576U, 0x3577U, 0x3578U, 0x3579U, 0x357AU, 0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U, 0x3538U, 0x3539U, 0x352BU, 0x352FU, 0x3641U, 0x3642U, 0x3643U, 0x3644U, 0x3645U, 0x3646U, 0x3647U, 0x3648U, 0x3649U, 0x364AU, 0x364BU, 0x364CU, 0x364DU, 0x364EU, 0x364FU, 0x3650U, 0x3651U, 0x3652U, 0x3653U, 0x3654U, 0x3655U, 0x3656U, 0x3657U, 0x3658U, 0x3659U, 0x365AU, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U, 0x3667U, 0x3668U, 0x3669U, 0x366AU, 0x366BU, 0x366CU, 0x366DU, 0x366EU, 0x366FU, 0x3670U, 0x3671U, 0x3672U, 0x3673U, 0x3674U, 0x3675U, 0x3676U, 0x3677U, 0x3678U, 0x3679U, 0x367AU, 0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U, 0x3638U, 0x3639U, 0x362BU, 0x362FU, 0x3741U, 0x3742U, 0x3743U, 0x3744U, 0x3745U, 0x3746U, 0x3747U, 0x3748U, 0x3749U, 0x374AU, 0x374BU, 0x374CU, 0x374DU, 0x374EU, 0x374FU, 0x3750U, 0x3751U, 0x3752U, 0x3753U, 0x3754U, 0x3755U, 0x3756U, 0x3757U, 0x3758U, 0x3759U, 0x375AU, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U, 0x3767U, 0x3768U, 0x3769U, 0x376AU, 0x376BU, 0x376CU, 0x376DU, 0x376EU, 0x376FU, 0x3770U, 0x3771U, 0x3772U, 0x3773U, 0x3774U, 0x3775U, 0x3776U, 0x3777U, 0x3778U, 0x3779U, 0x377AU, 0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U, 0x3738U, 0x3739U, 0x372BU, 0x372FU, 0x3841U, 0x3842U, 0x3843U, 0x3844U, 0x3845U, 0x3846U, 0x3847U, 0x3848U, 0x3849U, 0x384AU, 0x384BU, 0x384CU, 0x384DU, 0x384EU, 0x384FU, 0x3850U, 0x3851U, 0x3852U, 0x3853U, 0x3854U, 0x3855U, 0x3856U, 0x3857U, 0x3858U, 0x3859U, 0x385AU, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U, 0x3867U, 0x3868U, 0x3869U, 0x386AU, 0x386BU, 0x386CU, 0x386DU, 0x386EU, 0x386FU, 0x3870U, 0x3871U, 0x3872U, 0x3873U, 0x3874U, 0x3875U, 0x3876U, 0x3877U, 0x3878U, 0x3879U, 0x387AU, 0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U, 0x3838U, 0x3839U, 0x382BU, 0x382FU, 0x3941U, 0x3942U, 0x3943U, 0x3944U, 0x3945U, 0x3946U, 0x3947U, 0x3948U, 0x3949U, 0x394AU, 0x394BU, 0x394CU, 0x394DU, 0x394EU, 0x394FU, 0x3950U, 0x3951U, 0x3952U, 0x3953U, 0x3954U, 0x3955U, 0x3956U, 0x3957U, 0x3958U, 0x3959U, 0x395AU, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U, 0x3967U, 0x3968U, 0x3969U, 0x396AU, 0x396BU, 0x396CU, 0x396DU, 0x396EU, 0x396FU, 0x3970U, 0x3971U, 0x3972U, 0x3973U, 0x3974U, 0x3975U, 0x3976U, 0x3977U, 0x3978U, 0x3979U, 0x397AU, 0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U, 0x3938U, 0x3939U, 0x392BU, 0x392FU, 0x2B41U, 0x2B42U, 0x2B43U, 0x2B44U, 0x2B45U, 0x2B46U, 0x2B47U, 0x2B48U, 0x2B49U, 0x2B4AU, 0x2B4BU, 0x2B4CU, 0x2B4DU, 0x2B4EU, 0x2B4FU, 0x2B50U, 0x2B51U, 0x2B52U, 0x2B53U, 0x2B54U, 0x2B55U, 0x2B56U, 0x2B57U, 0x2B58U, 0x2B59U, 0x2B5AU, 0x2B61U, 0x2B62U, 0x2B63U, 0x2B64U, 0x2B65U, 0x2B66U, 0x2B67U, 0x2B68U, 0x2B69U, 0x2B6AU, 0x2B6BU, 0x2B6CU, 0x2B6DU, 0x2B6EU, 0x2B6FU, 0x2B70U, 0x2B71U, 0x2B72U, 0x2B73U, 0x2B74U, 0x2B75U, 0x2B76U, 0x2B77U, 0x2B78U, 0x2B79U, 0x2B7AU, 0x2B30U, 0x2B31U, 0x2B32U, 0x2B33U, 0x2B34U, 0x2B35U, 0x2B36U, 0x2B37U, 0x2B38U, 0x2B39U, 0x2B2BU, 0x2B2FU, 0x2F41U, 0x2F42U, 0x2F43U, 0x2F44U, 0x2F45U, 0x2F46U, 0x2F47U, 0x2F48U, 0x2F49U, 0x2F4AU, 0x2F4BU, 0x2F4CU, 0x2F4DU, 0x2F4EU, 0x2F4FU, 0x2F50U, 0x2F51U, 0x2F52U, 0x2F53U, 0x2F54U, 0x2F55U, 0x2F56U, 0x2F57U, 0x2F58U, 0x2F59U, 0x2F5AU, 0x2F61U, 0x2F62U, 0x2F63U, 0x2F64U, 0x2F65U, 0x2F66U, 0x2F67U, 0x2F68U, 0x2F69U, 0x2F6AU, 0x2F6BU, 0x2F6CU, 0x2F6DU, 0x2F6EU, 0x2F6FU, 0x2F70U, 0x2F71U, 0x2F72U, 0x2F73U, 0x2F74U, 0x2F75U, 0x2F76U, 0x2F77U, 0x2F78U, 0x2F79U, 0x2F7AU, 0x2F30U, 0x2F31U, 0x2F32U, 0x2F33U, 0x2F34U, 0x2F35U, 0x2F36U, 0x2F37U, 0x2F38U, 0x2F39U, 0x2F2BU, 0x2F2FU, #endif }; pybase64-1.4.3/base64/lib/tables/table_enc_12bit.py000077500000000000000000000021441500645130400215510ustar00rootroot00000000000000#!/usr/bin/python3 def tr(x): """Translate a 6-bit value to the Base64 alphabet.""" s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' \ + 'abcdefghijklmnopqrstuvwxyz' \ + '0123456789' \ + '+/' return ord(s[x]) def table(fn): """Generate a 12-bit lookup table.""" ret = [] for n in range(0, 2**12): pre = "\n\t" if n % 8 == 0 else " " pre = "\t" if n == 0 else pre ret.append("{}0x{:04X}U,".format(pre, fn(n))) return "".join(ret) def table_be(): """Generate a 12-bit big-endian lookup table.""" return table(lambda n: (tr(n & 0x3F) << 0) | (tr(n >> 6) << 8)) def table_le(): """Generate a 12-bit little-endian lookup table.""" return table(lambda n: (tr(n >> 6) << 0) | (tr(n & 0x3F) << 8)) def main(): """Entry point.""" lines = [ "#include ", "", "const uint16_t base64_table_enc_12bit[] = {", "#if BASE64_LITTLE_ENDIAN", table_le(), "#else", table_be(), "#endif", "};" ] for line in lines: print(line) if __name__ == "__main__": main() pybase64-1.4.3/base64/lib/tables/table_generator.c000066400000000000000000000120461500645130400215620ustar00rootroot00000000000000/** * * Copyright 2005, 2006 Nick Galbreath -- nickg [at] modp [dot] com * Copyright 2017 Matthieu Darbois * All rights reserved. * * http://modp.com/release/base64 * * 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. * */ /****************************/ #include #include #include #include #include static uint8_t b64chars[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; static uint8_t padchar = '='; static void printStart(void) { printf("#include \n"); printf("#define CHAR62 '%c'\n", b64chars[62]); printf("#define CHAR63 '%c'\n", b64chars[63]); printf("#define CHARPAD '%c'\n", padchar); } static void clearDecodeTable(uint32_t* ary) { int i = 0; for (i = 0; i < 256; ++i) { ary[i] = 0xFFFFFFFF; } } /* dump uint32_t as hex digits */ void uint32_array_to_c_hex(const uint32_t* ary, size_t sz, const char* name) { size_t i = 0; printf("const uint32_t %s[%d] = {\n", name, (int)sz); for (;;) { printf("0x%08" PRIx32, ary[i]); ++i; if (i == sz) break; if (i % 6 == 0) { printf(",\n"); } else { printf(", "); } } printf("\n};\n"); } int main(int argc, char** argv) { uint32_t x; uint32_t i = 0; uint32_t ary[256]; /* over-ride standard alphabet */ if (argc == 2) { uint8_t* replacements = (uint8_t*)argv[1]; if (strlen((char*)replacements) != 3) { fprintf(stderr, "input must be a string of 3 characters '-', '.' or '_'\n"); exit(1); } fprintf(stderr, "fusing '%s' as replacements in base64 encoding\n", replacements); b64chars[62] = replacements[0]; b64chars[63] = replacements[1]; padchar = replacements[2]; } printStart(); printf("\n\n#if BASE64_LITTLE_ENDIAN\n"); printf("\n\n/* SPECIAL DECODE TABLES FOR LITTLE ENDIAN (INTEL) CPUS */\n\n"); clearDecodeTable(ary); for (i = 0; i < 64; ++i) { x = b64chars[i]; ary[x] = i << 2; } uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d0"); printf("\n\n"); clearDecodeTable(ary); for (i = 0; i < 64; ++i) { x = b64chars[i]; ary[x] = ((i & 0x30) >> 4) | ((i & 0x0F) << 12); } uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d1"); printf("\n\n"); clearDecodeTable(ary); for (i = 0; i < 64; ++i) { x = b64chars[i]; ary[x] = ((i & 0x03) << 22) | ((i & 0x3c) << 6); } uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d2"); printf("\n\n"); clearDecodeTable(ary); for (i = 0; i < 64; ++i) { x = b64chars[i]; ary[x] = i << 16; } uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d3"); printf("\n\n"); printf("#else\n"); printf("\n\n/* SPECIAL DECODE TABLES FOR BIG ENDIAN (IBM/MOTOROLA/SUN) CPUS */\n\n"); clearDecodeTable(ary); for (i = 0; i < 64; ++i) { x = b64chars[i]; ary[x] = i << 26; } uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d0"); printf("\n\n"); clearDecodeTable(ary); for (i = 0; i < 64; ++i) { x = b64chars[i]; ary[x] = i << 20; } uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d1"); printf("\n\n"); clearDecodeTable(ary); for (i = 0; i < 64; ++i) { x = b64chars[i]; ary[x] = i << 14; } uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d2"); printf("\n\n"); clearDecodeTable(ary); for (i = 0; i < 64; ++i) { x = b64chars[i]; ary[x] = i << 8; } uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d3"); printf("\n\n"); printf("#endif\n"); return 0; } pybase64-1.4.3/base64/lib/tables/tables.c000066400000000000000000000040031500645130400176710ustar00rootroot00000000000000#include "tables.h" const uint8_t base64_table_enc_6bit[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" "+/"; // In the lookup table below, note that the value for '=' (character 61) is // 254, not 255. This character is used for in-band signaling of the end of // the datastream, and we will use that later. The characters A-Z, a-z, 0-9 // and + / are mapped to their "decoded" values. The other bytes all map to // the value 255, which flags them as "invalid input". const uint8_t base64_table_dec_8bit[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0..15 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 16..31 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, // 32..47 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 254, 255, 255, // 48..63 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64..79 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // 80..95 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96..111 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, // 112..127 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 128..143 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, }; #if BASE64_WORDSIZE >= 32 # include "table_dec_32bit.h" # include "table_enc_12bit.h" #endif pybase64-1.4.3/base64/lib/tables/tables.h000066400000000000000000000013001500645130400176730ustar00rootroot00000000000000#ifndef BASE64_TABLES_H #define BASE64_TABLES_H #include #include "../env.h" // These tables are used by all codecs for fallback plain encoding/decoding: extern const uint8_t base64_table_enc_6bit[]; extern const uint8_t base64_table_dec_8bit[]; // These tables are used for the 32-bit and 64-bit generic decoders: #if BASE64_WORDSIZE >= 32 extern const uint32_t base64_table_dec_32bit_d0[]; extern const uint32_t base64_table_dec_32bit_d1[]; extern const uint32_t base64_table_dec_32bit_d2[]; extern const uint32_t base64_table_dec_32bit_d3[]; // This table is used by the 32 and 64-bit generic encoders: extern const uint16_t base64_table_enc_12bit[]; #endif #endif // BASE64_TABLES_H pybase64-1.4.3/base64/test/000077500000000000000000000000001500645130400152155ustar00rootroot00000000000000pybase64-1.4.3/base64/test/CMakeLists.txt000066400000000000000000000022201500645130400177510ustar00rootroot00000000000000# Written in 2016 by Henrik Steffen Gaßmann henrik@gassmann.onl # # To the extent possible under law, the author(s) have dedicated all # copyright and related and neighboring rights to this software to the # public domain worldwide. This software is distributed without any warranty. # # You should have received a copy of the CC0 Public Domain Dedication # along with this software. If not, see # # http://creativecommons.org/publicdomain/zero/1.0/ # ######################################################################## function(add_base64_test TEST_NAME) unset(SRC_FILE) foreach(SRC_FILE ${ARGN}) list(APPEND SRC_FILES "${SRC_FILE}") endforeach() add_executable(${TEST_NAME} ${SRC_FILES}) target_link_libraries(${TEST_NAME} PRIVATE base64) add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} ) install(TARGETS ${TEST_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) endfunction() add_base64_test(test_base64 codec_supported.c test_base64.c ) add_base64_test(benchmark codec_supported.c benchmark.c ) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_link_libraries(benchmark PRIVATE rt) endif() pybase64-1.4.3/base64/test/Makefile000066400000000000000000000014361500645130400166610ustar00rootroot00000000000000CFLAGS += -std=c99 -O3 -Wall -Wextra -pedantic -DBASE64_STATIC_DEFINE ifdef OPENMP CFLAGS += -fopenmp endif TARGET := $(shell $(CC) -dumpmachine) ifneq (, $(findstring darwin, $(TARGET))) BENCH_LDFLAGS= else ifneq (, $(findstring mingw, $(TARGET))) BENCH_LDFLAGS= else # default to linux, -lrt needed BENCH_LDFLAGS=-lrt endif .PHONY: clean test valgrind test: clean test_base64 benchmark ./test_base64 ./benchmark valgrind: clean test_base64 valgrind --error-exitcode=2 ./test_base64 test_base64: test_base64.c codec_supported.o ../lib/libbase64.o $(CC) $(CFLAGS) -o $@ $^ benchmark: benchmark.c codec_supported.o ../lib/libbase64.o $(CC) $(CFLAGS) -o $@ $^ $(BENCH_LDFLAGS) ../%: make -C .. $* %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< clean: rm -f benchmark test_base64 *.o pybase64-1.4.3/base64/test/benchmark.c000066400000000000000000000141661500645130400173230ustar00rootroot00000000000000// For clock_gettime(2): #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 199309L #endif // For CLOCK_REALTIME on FreeBSD: #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 600 #endif // Standard cross-platform includes. #include #include #include // Platform-specific includes. #if defined(_WIN32) || defined(_WIN64) # include # include #else # include # include # include # include # include #endif #if defined(__MACH__) # include #endif #include "../include/libbase64.h" #include "codec_supported.h" #define KB 1024 #define MB (1024 * KB) #define RANDOMDEV "/dev/urandom" struct buffers { char *reg; char *enc; size_t regsz; size_t encsz; }; // Define buffer sizes to test with: static struct bufsize { char *label; size_t len; int repeat; int batch; } sizes[] = { { "10 MB", MB * 10, 10, 1 }, { "1 MB", MB * 1, 10, 10 }, { "100 KB", KB * 100, 10, 100 }, { "10 KB", KB * 10, 100, 100 }, { "1 KB", KB * 1, 100, 1000 }, }; static inline float bytes_to_mb (size_t bytes) { return bytes / (float) MB; } static bool get_random_data (struct buffers *b, char **errmsg) { #if defined(_WIN32) || defined(_WIN64) HCRYPTPROV hProvider = 0; if (!CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { *errmsg = "Error: CryptAcquireContext"; return false; } if (!CryptGenRandom(hProvider, b->regsz, b->reg)) { CryptReleaseContext(hProvider, 0); *errmsg = "Error: CryptGenRandom"; return false; } if (!CryptReleaseContext(hProvider, 0)) { *errmsg = "Error: CryptReleaseContext"; return false; } return true; #else int fd; ssize_t nread; size_t total_read = 0; // Open random device for semi-random data: if ((fd = open(RANDOMDEV, O_RDONLY)) < 0) { *errmsg = "Cannot open " RANDOMDEV; return false; } printf("Filling buffer with %.1f MB of random data...\n", bytes_to_mb(b->regsz)); while (total_read < b->regsz) { if ((nread = read(fd, b->reg + total_read, b->regsz - total_read)) < 0) { *errmsg = "Read error"; close(fd); return false; } total_read += nread; } close(fd); return true; #endif } #if defined(__MACH__) typedef uint64_t base64_timespec; static void base64_gettime (base64_timespec *t) { *t = mach_absolute_time(); } static float timediff_sec (base64_timespec *start, base64_timespec *end) { uint64_t diff = *end - *start; mach_timebase_info_data_t tb = { 0, 0 }; mach_timebase_info(&tb); return (float)((diff * tb.numer) / tb.denom) / 1e9f; } #elif defined(_WIN32) || defined(_WIN64) typedef ULARGE_INTEGER base64_timespec; static void base64_gettime (base64_timespec *t) { FILETIME current_time_ft; GetSystemTimePreciseAsFileTime(¤t_time_ft); t->LowPart = current_time_ft.dwLowDateTime; t->HighPart = current_time_ft.dwHighDateTime; } static float timediff_sec (base64_timespec *start, base64_timespec *end) { // Timer resolution is 100 nanoseconds (10^-7 sec). return (end->QuadPart - start->QuadPart) / 1e7f; } #else typedef struct timespec base64_timespec; static void base64_gettime (base64_timespec *t) { clock_gettime(CLOCK_REALTIME, t); } static float timediff_sec (base64_timespec *start, base64_timespec *end) { return (end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec) / 1e9f; } #endif static void codec_bench_enc (struct buffers *b, const struct bufsize *bs, const char *name, unsigned int flags) { float timediff, fastest = -1.0f; base64_timespec start, end; // Reset buffer size: b->regsz = bs->len; // Repeat benchmark a number of times for a fair test: for (int i = bs->repeat; i; i--) { // Timing loop, use batches to increase timer resolution: base64_gettime(&start); for (int j = bs->batch; j; j--) base64_encode(b->reg, b->regsz, b->enc, &b->encsz, flags); base64_gettime(&end); // Calculate average time of batch: timediff = timediff_sec(&start, &end) / bs->batch; // Update fastest time seen: if (fastest < 0.0f || timediff < fastest) fastest = timediff; } printf("%s\tencode\t%.02f MB/sec\n", name, bytes_to_mb(b->regsz) / fastest); } static void codec_bench_dec (struct buffers *b, const struct bufsize *bs, const char *name, unsigned int flags) { float timediff, fastest = -1.0f; base64_timespec start, end; // Reset buffer size: b->encsz = bs->len; // Repeat benchmark a number of times for a fair test: for (int i = bs->repeat; i; i--) { // Timing loop, use batches to increase timer resolution: base64_gettime(&start); for (int j = bs->batch; j; j--) base64_decode(b->enc, b->encsz, b->reg, &b->regsz, flags); base64_gettime(&end); // Calculate average time of batch: timediff = timediff_sec(&start, &end) / bs->batch; // Update fastest time seen: if (fastest < 0.0f || timediff < fastest) fastest = timediff; } printf("%s\tdecode\t%.02f MB/sec\n", name, bytes_to_mb(b->encsz) / fastest); } static void codec_bench (struct buffers *b, const struct bufsize *bs, const char *name, unsigned int flags) { codec_bench_enc(b, bs, name, flags); codec_bench_dec(b, bs, name, flags); } int main () { int ret = 0; char *errmsg = NULL; struct buffers b; // Set buffer sizes to largest buffer length: b.regsz = sizes[0].len; b.encsz = sizes[0].len * 5 / 3; // Allocate space for megabytes of random data: if ((b.reg = malloc(b.regsz)) == NULL) { errmsg = "Out of memory"; ret = 1; goto err0; } // Allocate space for encoded output: if ((b.enc = malloc(b.encsz)) == NULL) { errmsg = "Out of memory"; ret = 1; goto err1; } // Fill buffer with random data: if (get_random_data(&b, &errmsg) == false) { ret = 1; goto err2; } // Loop over all buffer sizes: for (size_t i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++) { printf("Testing with buffer size %s, fastest of %d * %d\n", sizes[i].label, sizes[i].repeat, sizes[i].batch); // Loop over all codecs: for (size_t j = 0; codecs[j]; j++) { int flags = codec_supported(j); if (flags) codec_bench(&b, &sizes[i], codecs[j], flags); } } // Free memory: err2: free(b.enc); err1: free(b.reg); err0: if (errmsg) fputs(errmsg, stderr); return ret; } pybase64-1.4.3/base64/test/ci/000077500000000000000000000000001500645130400156105ustar00rootroot00000000000000pybase64-1.4.3/base64/test/ci/.gitattributes000066400000000000000000000000711500645130400205010ustar00rootroot00000000000000πŸ˜΅β€πŸ’«.bin binary -text checksums.txt text eol=lf pybase64-1.4.3/base64/test/ci/analysis.sh000077500000000000000000000021451500645130400177740ustar00rootroot00000000000000#!/bin/bash set -ve MACHINE=$(uname -m) export CC=gcc uname -a clang --version # make analyse ${CC} --version # make -C test valgrind for USE_ASSEMBLY in 0 1; do if [ "${MACHINE}" == "x86_64" ]; then export SSSE3_CFLAGS="-mssse3 -DBASE64_SSSE3_USE_ASM=${USE_ASSEMBLY}" export SSE41_CFLAGS="-msse4.1 -DBASE64_SSE41_USE_ASM=${USE_ASSEMBLY}" export SSE42_CFLAGS="-msse4.2 -DBASE64_SSE42_USE_ASM=${USE_ASSEMBLY}" export AVX_CFLAGS="-mavx -DBASE64_AVX_USE_ASM=${USE_ASSEMBLY}" export AVX2_CFLAGS="-mavx2 -DBASE64_AVX2_USE_ASM=${USE_ASSEMBLY}" export AVX512_CFLAGS="-mavx512vl -mavx512vbmi" # Temporarily disable AVX512; it is not available in CI yet. export BASE64_TEST_SKIP_AVX512=1 elif [ "${MACHINE}" == "aarch64" ]; then export NEON64_CFLAGS="-march=armv8-a" elif [ "${MACHINE}" == "armv7l" ]; then export NEON32_CFLAGS="-march=armv7-a -mfloat-abi=hard -mfpu=neon" fi if [ ${USE_ASSEMBLY} -eq 0 ]; then echo "::group::analyze" make analyze echo "::endgroup::" fi echo "::group::valgrind (USE_ASSEMBLY=${USE_ASSEMBLY})" make clean make make -C test valgrind echo "::endgroup::" done pybase64-1.4.3/base64/test/ci/checksums.txt000066400000000000000000000001221500645130400203310ustar00rootroot000000000000004cd842ba8dce30216f77d2d5bf8a648e2dba6d95be5b12884f81e55bfab7b3cc *πŸ˜΅β€πŸ’«.bin pybase64-1.4.3/base64/test/ci/test.sh000077500000000000000000000012131500645130400171230ustar00rootroot00000000000000#!/bin/bash set -ve MACHINE=$(uname -m) if [ "${MACHINE}" == "x86_64" ]; then export SSSE3_CFLAGS=-mssse3 export SSE41_CFLAGS=-msse4.1 export SSE42_CFLAGS=-msse4.2 export AVX_CFLAGS=-mavx export AVX2_CFLAGS=-mavx2 export AVX512_CFLAGS="-mavx512vl -mavx512vbmi" # Temporarily disable AVX512; it is not available in CI yet. export BASE64_TEST_SKIP_AVX512=1 elif [ "${MACHINE}" == "aarch64" ]; then export NEON64_CFLAGS="-march=armv8-a" elif [ "${MACHINE}" == "armv7l" ]; then export NEON32_CFLAGS="-march=armv7-a -mfloat-abi=hard -mfpu=neon" fi if [ "${OPENMP:-}" == "0" ]; then unset OPENMP fi uname -a ${CC} --version make make -C test pybase64-1.4.3/base64/test/ci/πŸ˜΅β€πŸ’«.bin000066400000000000000000000007141500645130400222120ustar00rootroot00000000000000Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. πŸ˜΅β€πŸ’« pybase64-1.4.3/base64/test/codec_supported.c000066400000000000000000000014411500645130400205430ustar00rootroot00000000000000#include #include #include #include "../include/libbase64.h" static char *_codecs[] = { "AVX2" , "NEON32" , "NEON64" , "plain" , "SSSE3" , "SSE41" , "SSE42" , "AVX" , "AVX512" , NULL } ; char **codecs = _codecs; int codec_supported (size_t index) { if (index >= (sizeof(_codecs) / sizeof(_codecs[0])) - 1) { return 0; } // Check if given codec is supported by trying to decode a test string: char *a = "aGVsbG8="; char b[10]; size_t outlen; char envVariable[32]; sprintf(envVariable, "BASE64_TEST_SKIP_%s", _codecs[index]); const char* envOverride = getenv(envVariable); if ((envOverride != NULL) && (strcmp(envOverride, "1") == 0)) { return 0; } int flags = 1 << index; return (base64_decode(a, strlen(a), b, &outlen, flags) != -1) ? flags : 0; } pybase64-1.4.3/base64/test/codec_supported.h000066400000000000000000000000731500645130400205500ustar00rootroot00000000000000extern char **codecs; int codec_supported (size_t index); pybase64-1.4.3/base64/test/moby_dick.h000066400000000000000000000054311500645130400173310ustar00rootroot00000000000000static const char *moby_dick_plain = "Call me Ishmael. Some years ago--never mind how long precisely--having\n" "little or no money in my purse, and nothing particular to interest me on\n" "shore, I thought I would sail about a little and see the watery part of\n" "the world. It is a way I have of driving off the spleen and regulating\n" "the circulation. Whenever I find myself growing grim about the mouth;\n" "whenever it is a damp, drizzly November in my soul; whenever I find\n" "myself involuntarily pausing before coffin warehouses, and bringing up\n" "the rear of every funeral I meet; and especially whenever my hypos get\n" "such an upper hand of me, that it requires a strong moral principle to\n" "prevent me from deliberately stepping into the street, and methodically\n" "knocking people's hats off--then, I account it high time to get to sea\n" "as soon as I can. This is my substitute for pistol and ball. With a\n" "philosophical flourish Cato throws himself upon his sword; I quietly\n" "take to the ship. There is nothing surprising in this. If they but knew\n" "it, almost all men in their degree, some time or other, cherish very\n" "nearly the same feelings towards the ocean with me.\n"; static const char *moby_dick_base64 = "Q2FsbCBtZSBJc2htYWVsLiBTb21lIHllYXJzIGFnby0tbmV2ZXIgbWluZCBob3cgbG9uZ" "yBwcmVjaXNlbHktLWhhdmluZwpsaXR0bGUgb3Igbm8gbW9uZXkgaW4gbXkgcHVyc2UsIG" "FuZCBub3RoaW5nIHBhcnRpY3VsYXIgdG8gaW50ZXJlc3QgbWUgb24Kc2hvcmUsIEkgdGh" "vdWdodCBJIHdvdWxkIHNhaWwgYWJvdXQgYSBsaXR0bGUgYW5kIHNlZSB0aGUgd2F0ZXJ5" "IHBhcnQgb2YKdGhlIHdvcmxkLiBJdCBpcyBhIHdheSBJIGhhdmUgb2YgZHJpdmluZyBvZ" "mYgdGhlIHNwbGVlbiBhbmQgcmVndWxhdGluZwp0aGUgY2lyY3VsYXRpb24uIFdoZW5ldm" "VyIEkgZmluZCBteXNlbGYgZ3Jvd2luZyBncmltIGFib3V0IHRoZSBtb3V0aDsKd2hlbmV" "2ZXIgaXQgaXMgYSBkYW1wLCBkcml6emx5IE5vdmVtYmVyIGluIG15IHNvdWw7IHdoZW5l" "dmVyIEkgZmluZApteXNlbGYgaW52b2x1bnRhcmlseSBwYXVzaW5nIGJlZm9yZSBjb2Zma" "W4gd2FyZWhvdXNlcywgYW5kIGJyaW5naW5nIHVwCnRoZSByZWFyIG9mIGV2ZXJ5IGZ1bm" "VyYWwgSSBtZWV0OyBhbmQgZXNwZWNpYWxseSB3aGVuZXZlciBteSBoeXBvcyBnZXQKc3V" "jaCBhbiB1cHBlciBoYW5kIG9mIG1lLCB0aGF0IGl0IHJlcXVpcmVzIGEgc3Ryb25nIG1v" "cmFsIHByaW5jaXBsZSB0bwpwcmV2ZW50IG1lIGZyb20gZGVsaWJlcmF0ZWx5IHN0ZXBwa" "W5nIGludG8gdGhlIHN0cmVldCwgYW5kIG1ldGhvZGljYWxseQprbm9ja2luZyBwZW9wbG" "UncyBoYXRzIG9mZi0tdGhlbiwgSSBhY2NvdW50IGl0IGhpZ2ggdGltZSB0byBnZXQgdG8" "gc2VhCmFzIHNvb24gYXMgSSBjYW4uIFRoaXMgaXMgbXkgc3Vic3RpdHV0ZSBmb3IgcGlz" "dG9sIGFuZCBiYWxsLiBXaXRoIGEKcGhpbG9zb3BoaWNhbCBmbG91cmlzaCBDYXRvIHRoc" "m93cyBoaW1zZWxmIHVwb24gaGlzIHN3b3JkOyBJIHF1aWV0bHkKdGFrZSB0byB0aGUgc2" "hpcC4gVGhlcmUgaXMgbm90aGluZyBzdXJwcmlzaW5nIGluIHRoaXMuIElmIHRoZXkgYnV" "0IGtuZXcKaXQsIGFsbW9zdCBhbGwgbWVuIGluIHRoZWlyIGRlZ3JlZSwgc29tZSB0aW1l" "IG9yIG90aGVyLCBjaGVyaXNoIHZlcnkKbmVhcmx5IHRoZSBzYW1lIGZlZWxpbmdzIHRvd" "2FyZHMgdGhlIG9jZWFuIHdpdGggbWUuCg=="; pybase64-1.4.3/base64/test/moby_dick_base64.txt000066400000000000000000000027141500645130400210660ustar00rootroot00000000000000Q2FsbCBtZSBJc2htYWVsLiBTb21lIHllYXJzIGFnby0tbmV2ZXIgbWluZCBob3cgbG9uZyBwcmVjaXNlbHktLWhhdmluZwpsaXR0bGUgb3Igbm8gbW9uZXkgaW4gbXkgcHVyc2UsIGFuZCBub3RoaW5nIHBhcnRpY3VsYXIgdG8gaW50ZXJlc3QgbWUgb24Kc2hvcmUsIEkgdGhvdWdodCBJIHdvdWxkIHNhaWwgYWJvdXQgYSBsaXR0bGUgYW5kIHNlZSB0aGUgd2F0ZXJ5IHBhcnQgb2YKdGhlIHdvcmxkLiBJdCBpcyBhIHdheSBJIGhhdmUgb2YgZHJpdmluZyBvZmYgdGhlIHNwbGVlbiBhbmQgcmVndWxhdGluZwp0aGUgY2lyY3VsYXRpb24uIFdoZW5ldmVyIEkgZmluZCBteXNlbGYgZ3Jvd2luZyBncmltIGFib3V0IHRoZSBtb3V0aDsKd2hlbmV2ZXIgaXQgaXMgYSBkYW1wLCBkcml6emx5IE5vdmVtYmVyIGluIG15IHNvdWw7IHdoZW5ldmVyIEkgZmluZApteXNlbGYgaW52b2x1bnRhcmlseSBwYXVzaW5nIGJlZm9yZSBjb2ZmaW4gd2FyZWhvdXNlcywgYW5kIGJyaW5naW5nIHVwCnRoZSByZWFyIG9mIGV2ZXJ5IGZ1bmVyYWwgSSBtZWV0OyBhbmQgZXNwZWNpYWxseSB3aGVuZXZlciBteSBoeXBvcyBnZXQKc3VjaCBhbiB1cHBlciBoYW5kIG9mIG1lLCB0aGF0IGl0IHJlcXVpcmVzIGEgc3Ryb25nIG1vcmFsIHByaW5jaXBsZSB0bwpwcmV2ZW50IG1lIGZyb20gZGVsaWJlcmF0ZWx5IHN0ZXBwaW5nIGludG8gdGhlIHN0cmVldCwgYW5kIG1ldGhvZGljYWxseQprbm9ja2luZyBwZW9wbGUncyBoYXRzIG9mZi0tdGhlbiwgSSBhY2NvdW50IGl0IGhpZ2ggdGltZSB0byBnZXQgdG8gc2VhCmFzIHNvb24gYXMgSSBjYW4uIFRoaXMgaXMgbXkgc3Vic3RpdHV0ZSBmb3IgcGlzdG9sIGFuZCBiYWxsLiBXaXRoIGEKcGhpbG9zb3BoaWNhbCBmbG91cmlzaCBDYXRvIHRocm93cyBoaW1zZWxmIHVwb24gaGlzIHN3b3JkOyBJIHF1aWV0bHkKdGFrZSB0byB0aGUgc2hpcC4gVGhlcmUgaXMgbm90aGluZyBzdXJwcmlzaW5nIGluIHRoaXMuIElmIHRoZXkgYnV0IGtuZXcKaXQsIGFsbW9zdCBhbGwgbWVuIGluIHRoZWlyIGRlZ3JlZSwgc29tZSB0aW1lIG9yIG90aGVyLCBjaGVyaXNoIHZlcnkKbmVhcmx5IHRoZSBzYW1lIGZlZWxpbmdzIHRvd2FyZHMgdGhlIG9jZWFuIHdpdGggbWUuCg==pybase64-1.4.3/base64/test/moby_dick_plain.txt000066400000000000000000000021271500645130400211030ustar00rootroot00000000000000Call me Ishmael. Some years ago--never mind how long precisely--having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off--then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me. pybase64-1.4.3/base64/test/test_base64.c000066400000000000000000000215711500645130400175120ustar00rootroot00000000000000#include #include #include #include #include "../include/libbase64.h" #include "codec_supported.h" #include "moby_dick.h" static char out[2000]; static size_t outlen; static bool assert_enc (int flags, const char *src, const char *dst) { size_t srclen = strlen(src); size_t dstlen = strlen(dst); base64_encode(src, srclen, out, &outlen, flags); if (outlen != dstlen) { printf("FAIL: encoding of '%s': length expected %lu, got %lu\n", src, (unsigned long)dstlen, (unsigned long)outlen ); return true; } if (strncmp(dst, out, outlen) != 0) { out[outlen] = '\0'; printf("FAIL: encoding of '%s': expected output '%s', got '%s'\n", src, dst, out); return true; } return false; } static bool assert_dec (int flags, const char *src, const char *dst) { size_t srclen = strlen(src); size_t dstlen = strlen(dst); if (!base64_decode(src, srclen, out, &outlen, flags)) { printf("FAIL: decoding of '%s': decoding error\n", src); return true; } if (outlen != dstlen) { printf("FAIL: encoding of '%s': " "length expected %lu, got %lu\n", src, (unsigned long)dstlen, (unsigned long)outlen ); return true; } if (strncmp(dst, out, outlen) != 0) { out[outlen] = '\0'; printf("FAIL: decoding of '%s': expected output '%s', got '%s'\n", src, dst, out); return true; } return false; } static int assert_roundtrip (int flags, const char *src) { char tmp[1500]; size_t tmplen; size_t srclen = strlen(src); // Encode the input into global buffer: base64_encode(src, srclen, out, &outlen, flags); // Decode the global buffer into local temp buffer: if (!base64_decode(out, outlen, tmp, &tmplen, flags)) { printf("FAIL: decoding of '%s': decoding error\n", out); return true; } // Check that 'src' is identical to 'tmp': if (srclen != tmplen) { printf("FAIL: roundtrip of '%s': " "length expected %lu, got %lu\n", src, (unsigned long)srclen, (unsigned long)tmplen ); return true; } if (strncmp(src, tmp, tmplen) != 0) { tmp[tmplen] = '\0'; printf("FAIL: roundtrip of '%s': got '%s'\n", src, tmp); return true; } return false; } static int test_char_table (int flags, bool use_malloc) { bool fail = false; char chr[256]; char enc[400], dec[400]; size_t enclen, declen; // Fill array with all characters 0..255: for (int i = 0; i < 256; i++) chr[i] = (unsigned char)i; // Loop, using each char as a starting position to increase test coverage: for (int i = 0; i < 256; i++) { size_t chrlen = 256 - i; char* src = &chr[i]; if (use_malloc) { src = malloc(chrlen); /* malloc/copy this so valgrind can find out-of-bound access */ if (src == NULL) { printf( "FAIL: encoding @ %d: allocation of %lu bytes failed\n", i, (unsigned long)chrlen ); fail = true; continue; } memcpy(src, &chr[i], chrlen); } base64_encode(src, chrlen, enc, &enclen, flags); if (use_malloc) { free(src); } if (!base64_decode(enc, enclen, dec, &declen, flags)) { printf("FAIL: decoding @ %d: decoding error\n", i); fail = true; continue; } if (declen != chrlen) { printf("FAIL: roundtrip @ %d: " "length expected %lu, got %lu\n", i, (unsigned long)chrlen, (unsigned long)declen ); fail = true; continue; } if (strncmp(&chr[i], dec, declen) != 0) { printf("FAIL: roundtrip @ %d: decoded output not same as input\n", i); fail = true; } } return fail; } static int test_streaming (int flags) { bool fail = false; char chr[256]; char ref[400], enc[400]; size_t reflen; struct base64_state state; // Fill array with all characters 0..255: for (int i = 0; i < 256; i++) chr[i] = (unsigned char)i; // Create reference base64 encoding: base64_encode(chr, 256, ref, &reflen, BASE64_FORCE_PLAIN); // Encode the table with various block sizes and compare to reference: for (size_t bs = 1; bs < 255; bs++) { size_t inpos = 0; size_t partlen = 0; size_t enclen = 0; base64_stream_encode_init(&state, flags); memset(enc, 0, 400); for (;;) { base64_stream_encode(&state, &chr[inpos], (inpos + bs > 256) ? 256 - inpos : bs, &enc[enclen], &partlen); enclen += partlen; if (inpos + bs > 256) { break; } inpos += bs; } base64_stream_encode_final(&state, &enc[enclen], &partlen); enclen += partlen; if (enclen != reflen) { printf("FAIL: stream encoding gave incorrect size: " "%lu instead of %lu\n", (unsigned long)enclen, (unsigned long)reflen ); fail = true; } if (strncmp(ref, enc, reflen) != 0) { printf("FAIL: stream encoding with blocksize %lu failed\n", (unsigned long)bs ); fail = true; } } // Decode the reference encoding with various block sizes and // compare to input char table: for (size_t bs = 1; bs < 255; bs++) { size_t inpos = 0; size_t partlen = 0; size_t enclen = 0; base64_stream_decode_init(&state, flags); memset(enc, 0, 400); while (base64_stream_decode(&state, &ref[inpos], (inpos + bs > reflen) ? reflen - inpos : bs, &enc[enclen], &partlen)) { enclen += partlen; inpos += bs; // Has the entire buffer been consumed? if (inpos >= 400) { break; } } if (enclen != 256) { printf("FAIL: stream decoding gave incorrect size: " "%lu instead of 255\n", (unsigned long)enclen ); fail = true; } if (strncmp(chr, enc, 256) != 0) { printf("FAIL: stream decoding with blocksize %lu failed\n", (unsigned long)bs ); fail = true; } } return fail; } static int test_invalid_dec_input (int flags) { // Subset of invalid characters to cover all ranges static const char invalid_set[] = { '\0', -1, '!', '-', ';', '_', '|' }; static const char* invalid_strings[] = { "Zm9vYg=", "Zm9vYg", "Zm9vY", "Zm9vYmF=Zm9v" }; bool fail = false; char chr[256]; char enc[400], dec[400]; size_t enclen, declen; // Fill array with all characters 0..255: for (int i = 0; i < 256; i++) chr[i] = (unsigned char)i; // Create reference base64 encoding: base64_encode(chr, 256, enc, &enclen, BASE64_FORCE_PLAIN); // Test invalid strings returns error. for (size_t i = 0U; i < sizeof(invalid_strings) / sizeof(invalid_strings[0]); ++i) { if (base64_decode(invalid_strings[i], strlen(invalid_strings[i]), dec, &declen, flags)) { printf("FAIL: decoding invalid input \"%s\": no decoding error\n", invalid_strings[i]); fail = true; } } // Loop, corrupting each char to increase test coverage: for (size_t c = 0U; c < sizeof(invalid_set); ++c) { for (size_t i = 0U; i < enclen; i++) { char backup = enc[i]; enc[i] = invalid_set[c]; if (base64_decode(enc, enclen, dec, &declen, flags)) { printf("FAIL: decoding invalid input @ %d: no decoding error\n", (int)i); fail = true; enc[i] = backup; continue; } enc[i] = backup; } } // Loop, corrupting two chars to increase test coverage: for (size_t c = 0U; c < sizeof(invalid_set); ++c) { for (size_t i = 0U; i < enclen - 2U; i++) { char backup = enc[i+0]; char backup2 = enc[i+2]; enc[i+0] = invalid_set[c]; enc[i+2] = invalid_set[c]; if (base64_decode(enc, enclen, dec, &declen, flags)) { printf("FAIL: decoding invalid input @ %d: no decoding error\n", (int)i); fail = true; enc[i+0] = backup; enc[i+2] = backup2; continue; } enc[i+0] = backup; enc[i+2] = backup2; } } return fail; } static int test_one_codec (size_t codec_index) { bool fail = false; const char *codec = codecs[codec_index]; printf("Codec %s:\n", codec); // Skip if this codec is not supported: int flags = codec_supported(codec_index); if (flags == 0) { puts(" skipping"); return false; } // Test vectors: struct { const char *in; const char *out; } vec[] = { // These are the test vectors from RFC4648: { "", "" }, { "f", "Zg==" }, { "fo", "Zm8=" }, { "foo", "Zm9v" }, { "foob", "Zm9vYg==" }, { "fooba", "Zm9vYmE=" }, { "foobar", "Zm9vYmFy" }, // The first paragraph from Moby Dick, // to test the SIMD codecs with larger blocksize: { moby_dick_plain, moby_dick_base64 }, }; for (size_t i = 0; i < sizeof(vec) / sizeof(vec[0]); i++) { // Encode plain string, check against output: fail |= assert_enc(flags, vec[i].in, vec[i].out); // Decode the output string, check if we get the input: fail |= assert_dec(flags, vec[i].out, vec[i].in); // Do a roundtrip on the inputs and the outputs: fail |= assert_roundtrip(flags, vec[i].in); fail |= assert_roundtrip(flags, vec[i].out); } fail |= test_char_table(flags, false); /* test with unaligned input buffer */ fail |= test_char_table(flags, true); /* test for out-of-bound input read */ fail |= test_streaming(flags); fail |= test_invalid_dec_input(flags); if (!fail) puts(" all tests passed."); return fail; } int main () { bool fail = false; // Loop over all codecs: for (size_t i = 0; codecs[i]; i++) { // Test this codec, merge the results: fail |= test_one_codec(i); } return (fail) ? 1 : 0; }