pybase64 1.3.2__tar.gz → 1.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pybase64-1.3.2 → pybase64-1.4.0}/MANIFEST.in +3 -0
- {pybase64-1.3.2/src/pybase64.egg-info → pybase64-1.4.0}/PKG-INFO +11 -4
- {pybase64-1.3.2 → pybase64-1.4.0}/README.rst +8 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/.github/workflows/test.yml +81 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/CMakeLists.txt +5 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/Makefile +14 -5
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/bin/base64.c +225 -25
- pybase64-1.4.0/base64/bin/base64.manifest +23 -0
- pybase64-1.4.0/base64/bin/base64.rc +2 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx/codec.c +6 -4
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx2/codec.c +6 -4
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx2/dec_loop.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx2/dec_reshuffle.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx2/enc_loop.c +2 -2
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx2/enc_reshuffle.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx2/enc_translate.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx512/codec.c +6 -4
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx512/enc_loop.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx512/enc_reshuffle_translate.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/generic/32/dec_loop.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/generic/32/enc_loop.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/generic/64/enc_loop.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/generic/codec.c +4 -2
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon32/codec.c +7 -5
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon32/dec_loop.c +3 -3
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon32/enc_loop.c +2 -2
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon32/enc_reshuffle.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon32/enc_translate.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon64/codec.c +7 -5
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon64/enc_loop.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon64/enc_reshuffle.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/sse41/codec.c +6 -4
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/sse42/codec.c +6 -4
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/ssse3/codec.c +6 -4
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/ssse3/dec_loop.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/ssse3/dec_reshuffle.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/ssse3/enc_loop.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/ssse3/enc_reshuffle.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/ssse3/enc_translate.c +1 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/codec_choose.c +3 -3
- pybase64-1.4.0/base64/lib/codecs.h +57 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/env.h +16 -6
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/CMakeLists.txt +4 -6
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/Makefile +3 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/benchmark.c +66 -13
- pybase64-1.4.0/base64/test/ci/checksums.txt +1 -0
- pybase64-1.4.0/base64/test/ci//360/237/230/265/342/200/215/360/237/222/253.bin +2 -0
- pybase64-1.4.0/pyproject.toml +97 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/setup.cfg +0 -3
- {pybase64-1.3.2 → pybase64-1.4.0}/setup.py +58 -50
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64/__init__.py +31 -8
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64/__main__.py +63 -50
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64/_fallback.py +28 -24
- pybase64-1.4.0/src/pybase64/_license.pyi +1 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64/_pybase64.c +135 -61
- pybase64-1.4.0/src/pybase64/_pybase64.pyi +16 -0
- pybase64-1.4.0/src/pybase64/_typing.py +35 -0
- pybase64-1.4.0/src/pybase64/_version.py +3 -0
- {pybase64-1.3.2 → pybase64-1.4.0/src/pybase64.egg-info}/PKG-INFO +11 -4
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64.egg-info/SOURCES.txt +8 -1
- pybase64-1.4.0/tests/test_benchmark.py +43 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/tests/test_main.py +49 -43
- {pybase64-1.3.2 → pybase64-1.4.0}/tests/test_pybase64.py +139 -173
- pybase64-1.3.2/base64/lib/codecs.h +0 -65
- pybase64-1.3.2/pyproject.toml +0 -19
- pybase64-1.3.2/src/pybase64/_version.py +0 -1
- {pybase64-1.3.2 → pybase64-1.4.0}/LICENSE +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/LICENSE +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/README.md +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/base64-benchmarks.png +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/cmake/Modules/TargetArch.cmake +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/cmake/Modules/TargetSIMDInstructionSet.cmake +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/cmake/base64-config.cmake.in +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/cmake/config.h.in +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/cmake/test-arch.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/include/libbase64.h +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx/enc_loop_asm.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/avx2/enc_loop_asm.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/generic/dec_head.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/generic/dec_tail.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/generic/enc_head.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/generic/enc_tail.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon64/dec_loop.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/neon64/enc_loop_asm.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/arch/ssse3/enc_loop_asm.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/exports.txt +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/lib.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/lib_openmp.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/tables/Makefile +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/tables/table_dec_32bit.h +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/tables/table_enc_12bit.h +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/tables/table_enc_12bit.py +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/tables/table_generator.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/tables/tables.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/lib/tables/tables.h +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/ci/analysis.sh +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/ci/test.sh +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/codec_supported.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/codec_supported.h +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/moby_dick.h +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/moby_dick_base64.txt +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/moby_dick_plain.txt +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/base64/test/test_base64.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64/_license.py +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64/_pybase64_get_simd_flags.c +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64/_pybase64_get_simd_flags.h +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64/py.typed +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64.egg-info/dependency_links.txt +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64.egg-info/entry_points.txt +0 -0
- {pybase64-1.3.2 → pybase64-1.4.0}/src/pybase64.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pybase64
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Fast Base64 encoding/decoding
|
|
5
5
|
Home-page: https://github.com/mayeut/pybase64
|
|
6
6
|
Author: Matthieu Darbois
|
|
@@ -16,14 +16,13 @@ Classifier: Topic :: Utilities
|
|
|
16
16
|
Classifier: License :: OSI Approved :: BSD License
|
|
17
17
|
Classifier: Programming Language :: C
|
|
18
18
|
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
21
19
|
Classifier: Programming Language :: Python :: 3.8
|
|
22
20
|
Classifier: Programming Language :: Python :: 3.9
|
|
23
21
|
Classifier: Programming Language :: Python :: 3.10
|
|
24
22
|
Classifier: Programming Language :: Python :: 3.11
|
|
25
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
26
|
-
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Requires-Python: >=3.8
|
|
27
26
|
Description-Content-Type: text/x-rst
|
|
28
27
|
License-File: LICENSE
|
|
29
28
|
|
|
@@ -150,6 +149,14 @@ Running Python 3.7.2, Apple LLVM version 10.0.0 (clang-1000.11.45.5), Mac OS X 1
|
|
|
150
149
|
|
|
151
150
|
Changelog
|
|
152
151
|
=========
|
|
152
|
+
1.4.0
|
|
153
|
+
-----
|
|
154
|
+
- Publish python 3.13 wheels
|
|
155
|
+
- Add support for free-threaded builds
|
|
156
|
+
- Add MSYS2 support for C-extension
|
|
157
|
+
- Better logging on base64 build failure when C-extension build is optional
|
|
158
|
+
- Drop python 3.6 & 3.7 support
|
|
159
|
+
|
|
153
160
|
1.3.2
|
|
154
161
|
-----
|
|
155
162
|
- Update base64 library
|
|
@@ -121,6 +121,14 @@ Running Python 3.7.2, Apple LLVM version 10.0.0 (clang-1000.11.45.5), Mac OS X 1
|
|
|
121
121
|
|
|
122
122
|
Changelog
|
|
123
123
|
=========
|
|
124
|
+
1.4.0
|
|
125
|
+
-----
|
|
126
|
+
- Publish python 3.13 wheels
|
|
127
|
+
- Add support for free-threaded builds
|
|
128
|
+
- Add MSYS2 support for C-extension
|
|
129
|
+
- Better logging on base64 build failure when C-extension build is optional
|
|
130
|
+
- Drop python 3.6 & 3.7 support
|
|
131
|
+
|
|
124
132
|
1.3.2
|
|
125
133
|
-----
|
|
126
134
|
- Update base64 library
|
|
@@ -169,3 +169,84 @@ jobs:
|
|
|
169
169
|
echo "::group::CTest"
|
|
170
170
|
ctest --no-tests=error --test-dir out -VV --build-config Release
|
|
171
171
|
echo "::endgroup::CTest"
|
|
172
|
+
|
|
173
|
+
msys2-cmake-test:
|
|
174
|
+
name: msys2-cmake-${{ matrix.msystem }}
|
|
175
|
+
needs: makefile-analysis
|
|
176
|
+
runs-on: windows-2022
|
|
177
|
+
strategy:
|
|
178
|
+
fail-fast: false
|
|
179
|
+
matrix:
|
|
180
|
+
include:
|
|
181
|
+
- { msystem: msys, toolchain: "gcc" }
|
|
182
|
+
- { msystem: mingw32, env: mingw-w64-i686- }
|
|
183
|
+
- { msystem: mingw64, env: mingw-w64-x86_64- }
|
|
184
|
+
- { msystem: ucrt64, env: mingw-w64-ucrt-x86_64- }
|
|
185
|
+
- { msystem: clang32, env: mingw-w64-clang-i686- }
|
|
186
|
+
- { msystem: clang64, env: mingw-w64-clang-x86_64- }
|
|
187
|
+
|
|
188
|
+
steps:
|
|
189
|
+
- name: Checkout
|
|
190
|
+
uses: actions/checkout@v3
|
|
191
|
+
- name: Setup MSYS2 ${{matrix.msystem}}
|
|
192
|
+
uses: msys2/setup-msys2@v2
|
|
193
|
+
with:
|
|
194
|
+
msystem: ${{matrix.msystem}}
|
|
195
|
+
update: true
|
|
196
|
+
install: >-
|
|
197
|
+
make
|
|
198
|
+
${{ matrix.env }}${{ matrix.toolchain || 'toolchain' }}
|
|
199
|
+
${{ matrix.env }}cmake
|
|
200
|
+
- name: CMake Configure
|
|
201
|
+
shell: msys2 {0}
|
|
202
|
+
run: >
|
|
203
|
+
cmake
|
|
204
|
+
-B out
|
|
205
|
+
-Werror=dev
|
|
206
|
+
-DBASE64_BUILD_TESTS=ON
|
|
207
|
+
-DCMAKE_BUILD_TYPE=Release
|
|
208
|
+
-DBASE64_WITH_AVX512=OFF
|
|
209
|
+
- name: CMake Build
|
|
210
|
+
shell: msys2 {0}
|
|
211
|
+
run: cmake --build out --config Release --verbose
|
|
212
|
+
- name: CTest
|
|
213
|
+
shell: msys2 {0}
|
|
214
|
+
run: ctest --no-tests=error --test-dir out -VV --build-config Release
|
|
215
|
+
- name: Test demo utility with unicode filenames and file contents on Windows
|
|
216
|
+
shell: msys2 {0}
|
|
217
|
+
run: |
|
|
218
|
+
out/bin/base64 test/ci/😵💫.bin > test/ci/😵💫.bin.b64
|
|
219
|
+
out/bin/base64 -d test/ci/😵💫.bin.b64 > test/ci/😵💫.bin
|
|
220
|
+
cd test/ci
|
|
221
|
+
sha256sum -c checksums.txt
|
|
222
|
+
|
|
223
|
+
msys2-makefile-test:
|
|
224
|
+
name: msys2-makefile-${{ matrix.msystem }}
|
|
225
|
+
needs: makefile-analysis
|
|
226
|
+
runs-on: windows-2022
|
|
227
|
+
strategy:
|
|
228
|
+
fail-fast: false
|
|
229
|
+
matrix:
|
|
230
|
+
include:
|
|
231
|
+
- { msystem: msys, toolchain: "gcc" }
|
|
232
|
+
- { msystem: mingw32, env: mingw-w64-i686- }
|
|
233
|
+
- { msystem: mingw64, env: mingw-w64-x86_64- }
|
|
234
|
+
- { msystem: ucrt64, env: mingw-w64-ucrt-x86_64- }
|
|
235
|
+
# - { msystem: clang32, env: mingw-w64-clang-i686- } disabled, lld does not support the "-r" option
|
|
236
|
+
# - { msystem: clang64, env: mingw-w64-clang-x86_64- } disabled, lld does not support the "-r" option
|
|
237
|
+
env:
|
|
238
|
+
CC: cc.exe
|
|
239
|
+
steps:
|
|
240
|
+
- name: Checkout
|
|
241
|
+
uses: actions/checkout@v3
|
|
242
|
+
- name: Setup MSYS2 ${{matrix.msystem}}
|
|
243
|
+
uses: msys2/setup-msys2@v2
|
|
244
|
+
with:
|
|
245
|
+
msystem: ${{matrix.msystem}}
|
|
246
|
+
update: true
|
|
247
|
+
install: >-
|
|
248
|
+
make
|
|
249
|
+
${{ matrix.env }}${{ matrix.toolchain || 'toolchain' }}
|
|
250
|
+
- name: Run tests
|
|
251
|
+
shell: msys2 {0}
|
|
252
|
+
run: ./test/ci/test.sh
|
|
@@ -17,7 +17,7 @@ if (POLICY CMP0127)
|
|
|
17
17
|
cmake_policy(SET CMP0127 NEW)
|
|
18
18
|
endif()
|
|
19
19
|
|
|
20
|
-
project(base64 LANGUAGES C VERSION 0.5.
|
|
20
|
+
project(base64 LANGUAGES C VERSION 0.5.2)
|
|
21
21
|
|
|
22
22
|
include(GNUInstallDirs)
|
|
23
23
|
include(CMakeDependentOption)
|
|
@@ -249,6 +249,10 @@ if (BASE64_BUILD_CLI)
|
|
|
249
249
|
set_target_properties(base64-bin PROPERTIES
|
|
250
250
|
OUTPUT_NAME base64
|
|
251
251
|
)
|
|
252
|
+
|
|
253
|
+
if (WIN32)
|
|
254
|
+
target_sources(base64-bin PRIVATE bin/base64.rc)
|
|
255
|
+
endif ()
|
|
252
256
|
endif()
|
|
253
257
|
|
|
254
258
|
########################################################################
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
CFLAGS += -std=c99 -O3 -Wall -Wextra -pedantic
|
|
1
|
+
CFLAGS += -std=c99 -O3 -Wall -Wextra -pedantic -DBASE64_STATIC_DEFINE
|
|
2
2
|
|
|
3
3
|
# Set OBJCOPY if not defined by environment:
|
|
4
4
|
OBJCOPY ?= objcopy
|
|
@@ -56,6 +56,7 @@ ifdef OPENMP
|
|
|
56
56
|
CFLAGS += -fopenmp
|
|
57
57
|
endif
|
|
58
58
|
|
|
59
|
+
TARGET := $(shell $(CC) -dumpmachine)
|
|
59
60
|
|
|
60
61
|
.PHONY: all analyze clean
|
|
61
62
|
|
|
@@ -64,9 +65,17 @@ all: bin/base64 lib/libbase64.o
|
|
|
64
65
|
bin/base64: bin/base64.o lib/libbase64.o
|
|
65
66
|
$(CC) $(CFLAGS) -o $@ $^
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
# Workaround: mangle exported function names on MinGW32.
|
|
69
|
+
lib/exports.build.txt: lib/exports.txt
|
|
70
|
+
ifeq (i686-w64-mingw32, $(TARGET))
|
|
71
|
+
sed -e 's/^/_/' $< > $@
|
|
72
|
+
else
|
|
73
|
+
cp -f $< $@
|
|
74
|
+
endif
|
|
75
|
+
|
|
76
|
+
lib/libbase64.o: lib/exports.build.txt $(OBJS)
|
|
77
|
+
$(LD) -r -o $@ $(OBJS)
|
|
78
|
+
$(OBJCOPY) --keep-global-symbols=$< $@
|
|
70
79
|
|
|
71
80
|
lib/config.h:
|
|
72
81
|
@echo "#define HAVE_AVX512 $(HAVE_AVX512)" > $@
|
|
@@ -97,4 +106,4 @@ analyze: clean
|
|
|
97
106
|
scan-build --use-analyzer=`which clang` --status-bugs make
|
|
98
107
|
|
|
99
108
|
clean:
|
|
100
|
-
rm -f bin/base64 bin/base64.o lib/libbase64.o lib/config.h $(OBJS)
|
|
109
|
+
rm -f bin/base64 bin/base64.o lib/libbase64.o lib/config.h lib/exports.build.txt $(OBJS)
|
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
// Test for MinGW.
|
|
2
|
+
#if defined(__MINGW32__) || defined(__MINGW64__)
|
|
3
|
+
# define MINGW
|
|
4
|
+
#endif
|
|
5
|
+
|
|
6
|
+
// Test for Windows.
|
|
7
|
+
#if defined(_WIN32) || defined(_WIN64)
|
|
8
|
+
# define WIN
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
// Decide if the writev(2) system call needs to be emulated as a series of
|
|
12
|
+
// write(2) calls. At least MinGW does not support writev(2).
|
|
13
|
+
#ifdef MINGW
|
|
14
|
+
# define EMULATE_WRITEV
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
// Include the necessary system header when using the system's writev(2).
|
|
18
|
+
#ifndef EMULATE_WRITEV
|
|
19
|
+
# define _XOPEN_SOURCE // Unlock IOV_MAX
|
|
20
|
+
# include <sys/uio.h>
|
|
21
|
+
#endif
|
|
2
22
|
|
|
3
23
|
#include <stdbool.h>
|
|
4
24
|
#include <stdlib.h>
|
|
@@ -8,7 +28,13 @@
|
|
|
8
28
|
#include <getopt.h>
|
|
9
29
|
#include <errno.h>
|
|
10
30
|
#include <limits.h>
|
|
11
|
-
|
|
31
|
+
|
|
32
|
+
// Include Windows-specific headers.
|
|
33
|
+
#ifdef WIN
|
|
34
|
+
# include <io.h>
|
|
35
|
+
# include <fcntl.h>
|
|
36
|
+
#endif
|
|
37
|
+
|
|
12
38
|
#include "../include/libbase64.h"
|
|
13
39
|
|
|
14
40
|
// Size of the buffer for the "raw" (not base64-encoded) data in bytes.
|
|
@@ -38,6 +64,12 @@ struct config {
|
|
|
38
64
|
|
|
39
65
|
// Whether to just print the help text and exit.
|
|
40
66
|
bool print_help;
|
|
67
|
+
|
|
68
|
+
// Whether to strip newlines from the input when decoding.
|
|
69
|
+
bool strip_newlines;
|
|
70
|
+
|
|
71
|
+
// Whether to ignore any character not in the base64 alphabet.
|
|
72
|
+
bool ignore_garbage;
|
|
41
73
|
};
|
|
42
74
|
|
|
43
75
|
// Input/output buffer structure.
|
|
@@ -50,6 +82,59 @@ struct buffer {
|
|
|
50
82
|
char *enc;
|
|
51
83
|
};
|
|
52
84
|
|
|
85
|
+
// Optionally emulate writev(2) as a series of write calls.
|
|
86
|
+
#ifdef EMULATE_WRITEV
|
|
87
|
+
|
|
88
|
+
// Quick and dirty definition of IOV_MAX as it is probably not defined.
|
|
89
|
+
#ifndef IOV_MAX
|
|
90
|
+
# define IOV_MAX 1024
|
|
91
|
+
#endif
|
|
92
|
+
|
|
93
|
+
// Quick and dirty definition of this system struct, for local use only.
|
|
94
|
+
struct iovec {
|
|
95
|
+
|
|
96
|
+
// Opaque data pointer.
|
|
97
|
+
void *iov_base;
|
|
98
|
+
|
|
99
|
+
// Length of the data in bytes.
|
|
100
|
+
size_t iov_len;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
static ssize_t
|
|
104
|
+
writev (const int fd, const struct iovec *iov, int iovcnt)
|
|
105
|
+
{
|
|
106
|
+
ssize_t r, nwrite = 0;
|
|
107
|
+
|
|
108
|
+
// Reset the error marker.
|
|
109
|
+
errno = 0;
|
|
110
|
+
|
|
111
|
+
while (iovcnt-- > 0) {
|
|
112
|
+
|
|
113
|
+
// Write the vector; propagate errors back to the caller. Note
|
|
114
|
+
// that this loses information about how much vectors have been
|
|
115
|
+
// successfully written, but that also seems to be the case
|
|
116
|
+
// with the real function. The API is somewhat flawed.
|
|
117
|
+
if ((r = write(fd, iov->iov_base, iov->iov_len)) < 0) {
|
|
118
|
+
return r;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Update the total write count.
|
|
122
|
+
nwrite += r;
|
|
123
|
+
|
|
124
|
+
// Return early after a partial write; the caller should retry.
|
|
125
|
+
if ((size_t) r != iov->iov_len) {
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Move to the next vector.
|
|
130
|
+
iov++;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return nwrite;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
#endif // EMULATE_WRITEV
|
|
137
|
+
|
|
53
138
|
static bool
|
|
54
139
|
buffer_alloc (const struct config *config, struct buffer *buf)
|
|
55
140
|
{
|
|
@@ -272,10 +357,54 @@ encode (const struct config *config, struct buffer *buf)
|
|
|
272
357
|
return true;
|
|
273
358
|
}
|
|
274
359
|
|
|
275
|
-
static
|
|
360
|
+
static inline size_t
|
|
361
|
+
find_garbage (const char *p, const size_t avail)
|
|
362
|
+
{
|
|
363
|
+
// Use a lookup table to distinguish garbage from non-garbage.
|
|
364
|
+
static const char lut[256] = {
|
|
365
|
+
['A'] = 1, ['B'] = 1, ['C'] = 1, ['D'] = 1, ['E'] = 1,
|
|
366
|
+
['F'] = 1, ['G'] = 1, ['H'] = 1, ['I'] = 1, ['J'] = 1,
|
|
367
|
+
['K'] = 1, ['L'] = 1, ['M'] = 1, ['N'] = 1, ['O'] = 1,
|
|
368
|
+
['P'] = 1, ['Q'] = 1, ['R'] = 1, ['S'] = 1, ['T'] = 1,
|
|
369
|
+
['U'] = 1, ['V'] = 1, ['W'] = 1, ['X'] = 1, ['Y'] = 1,
|
|
370
|
+
['Z'] = 1,
|
|
371
|
+
['a'] = 1, ['b'] = 1, ['c'] = 1, ['d'] = 1, ['e'] = 1,
|
|
372
|
+
['f'] = 1, ['g'] = 1, ['h'] = 1, ['i'] = 1, ['j'] = 1,
|
|
373
|
+
['k'] = 1, ['l'] = 1, ['m'] = 1, ['n'] = 1, ['o'] = 1,
|
|
374
|
+
['p'] = 1, ['q'] = 1, ['r'] = 1, ['s'] = 1, ['t'] = 1,
|
|
375
|
+
['u'] = 1, ['v'] = 1, ['w'] = 1, ['x'] = 1, ['y'] = 1,
|
|
376
|
+
['z'] = 1,
|
|
377
|
+
['0'] = 1, ['1'] = 1, ['2'] = 1, ['3'] = 1, ['4'] = 1,
|
|
378
|
+
['5'] = 1, ['6'] = 1, ['7'] = 1, ['8'] = 1, ['9'] = 1,
|
|
379
|
+
['+'] = 1, ['/'] = 1, ['"'] = 1,
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
for (size_t len = 0; len < avail; len++) {
|
|
383
|
+
if (lut[(unsigned char) p[len]] == 0) {
|
|
384
|
+
return len;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
return avail;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
static inline size_t
|
|
392
|
+
find_newline (const char *p, const size_t avail)
|
|
393
|
+
{
|
|
394
|
+
// This is very naive and can probably be improved by vectorization.
|
|
395
|
+
for (size_t len = 0; len < avail; len++) {
|
|
396
|
+
if (p[len] == '\n') {
|
|
397
|
+
return len;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return avail;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
static bool
|
|
276
405
|
decode (const struct config *config, struct buffer *buf)
|
|
277
406
|
{
|
|
278
|
-
size_t
|
|
407
|
+
size_t avail;
|
|
279
408
|
struct base64_state state;
|
|
280
409
|
|
|
281
410
|
// Initialize the decoder's state structure.
|
|
@@ -283,18 +412,61 @@ decode (const struct config *config, struct buffer *buf)
|
|
|
283
412
|
|
|
284
413
|
// Read encoded data into the buffer. Use the smallest buffer size to
|
|
285
414
|
// be on the safe side: the decoded output will fit the raw buffer.
|
|
286
|
-
while ((
|
|
415
|
+
while ((avail = fread(buf->enc, 1, BUFFER_RAW_SIZE, config->fp)) > 0) {
|
|
416
|
+
char *start = buf->enc;
|
|
417
|
+
char *outbuf = buf->raw;
|
|
418
|
+
size_t ototal = 0;
|
|
419
|
+
|
|
420
|
+
// By popular demand, this utility tries to be bug-compatible
|
|
421
|
+
// with GNU `base64'. That includes silently ignoring newlines
|
|
422
|
+
// in the input. Tokenize the input on newline characters.
|
|
423
|
+
while (avail > 0) {
|
|
424
|
+
size_t outlen, len;
|
|
425
|
+
|
|
426
|
+
// When stripping garbage or newlines in the input,
|
|
427
|
+
// find the offset of the next garbage/newline
|
|
428
|
+
// character, which is also the length of the next
|
|
429
|
+
// chunk. Otherwise treat the entire input as a single
|
|
430
|
+
// chunk.
|
|
431
|
+
if (config->ignore_garbage) {
|
|
432
|
+
len = find_garbage(start, avail);
|
|
433
|
+
} else if (config->strip_newlines) {
|
|
434
|
+
len = find_newline(start, avail);
|
|
435
|
+
} else {
|
|
436
|
+
len = avail;
|
|
437
|
+
}
|
|
287
438
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
439
|
+
// Ignore empty chunks.
|
|
440
|
+
if (len == 0) {
|
|
441
|
+
start++;
|
|
442
|
+
avail--;
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Decode the chunk into the raw buffer.
|
|
447
|
+
if (base64_stream_decode(&state, start, len,
|
|
448
|
+
outbuf, &outlen) == 0) {
|
|
449
|
+
fprintf(stderr, "%s: %s: decoding error\n",
|
|
450
|
+
config->name, config->file);
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Update the output buffer pointer and total size.
|
|
455
|
+
outbuf += outlen;
|
|
456
|
+
ototal += outlen;
|
|
457
|
+
|
|
458
|
+
// Bail out if the whole string has been consumed.
|
|
459
|
+
if (len == avail) {
|
|
460
|
+
break;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Move the start pointer past the newline.
|
|
464
|
+
start += len + 1;
|
|
465
|
+
avail -= len + 1;
|
|
294
466
|
}
|
|
295
467
|
|
|
296
468
|
// Append the raw data to the output stream.
|
|
297
|
-
if (write_stdout(config, buf->raw,
|
|
469
|
+
if (write_stdout(config, buf->raw, ototal) == false) {
|
|
298
470
|
return false;
|
|
299
471
|
}
|
|
300
472
|
}
|
|
@@ -317,10 +489,17 @@ usage (FILE *fp, const struct config *config)
|
|
|
317
489
|
"If no FILE is given or is specified as '-', "
|
|
318
490
|
"read from standard input.\n"
|
|
319
491
|
"Options:\n"
|
|
320
|
-
" -d, --decode
|
|
321
|
-
" -h, --help
|
|
322
|
-
" -
|
|
323
|
-
"
|
|
492
|
+
" -d, --decode Decode a base64 stream.\n"
|
|
493
|
+
" -h, --help Print this help text.\n"
|
|
494
|
+
" -i, --ignore-garbage When decoding, ignore any "
|
|
495
|
+
"non-base64 data.\n"
|
|
496
|
+
" -n, --no-strip-newlines When decoding, do not strip "
|
|
497
|
+
"newlines. Speeds up\n"
|
|
498
|
+
" decoding of inputs that do not "
|
|
499
|
+
"contain newlines.\n"
|
|
500
|
+
" -w, --wrap=COLS Wrap encoded lines at this "
|
|
501
|
+
"column. Default 76, 0 to\n"
|
|
502
|
+
" disable.\n";
|
|
324
503
|
|
|
325
504
|
fprintf(fp, usage, config->name);
|
|
326
505
|
}
|
|
@@ -357,9 +536,11 @@ parse_opts (int argc, char **argv, struct config *config)
|
|
|
357
536
|
{
|
|
358
537
|
int c;
|
|
359
538
|
static const struct option opts[] = {
|
|
360
|
-
{ "decode",
|
|
361
|
-
{ "help",
|
|
362
|
-
{ "
|
|
539
|
+
{ "decode", no_argument, NULL, 'd' },
|
|
540
|
+
{ "help", no_argument, NULL, 'h' },
|
|
541
|
+
{ "ignore-garbage", no_argument, NULL, 'i' },
|
|
542
|
+
{ "no-strip-newlines", no_argument, NULL, 'n' },
|
|
543
|
+
{ "wrap", required_argument, NULL, 'w' },
|
|
363
544
|
{ NULL }
|
|
364
545
|
};
|
|
365
546
|
|
|
@@ -367,7 +548,7 @@ parse_opts (int argc, char **argv, struct config *config)
|
|
|
367
548
|
config->name = *argv;
|
|
368
549
|
|
|
369
550
|
// Parse command line options.
|
|
370
|
-
while ((c = getopt_long(argc, argv, ":
|
|
551
|
+
while ((c = getopt_long(argc, argv, ":dhinw:", opts, NULL)) != -1) {
|
|
371
552
|
switch (c) {
|
|
372
553
|
case 'd':
|
|
373
554
|
config->decode = true;
|
|
@@ -377,6 +558,14 @@ parse_opts (int argc, char **argv, struct config *config)
|
|
|
377
558
|
config->print_help = true;
|
|
378
559
|
return true;
|
|
379
560
|
|
|
561
|
+
case 'i':
|
|
562
|
+
config->ignore_garbage = true;
|
|
563
|
+
break;
|
|
564
|
+
|
|
565
|
+
case 'n':
|
|
566
|
+
config->strip_newlines = false;
|
|
567
|
+
break;
|
|
568
|
+
|
|
380
569
|
case 'w':
|
|
381
570
|
if (get_wrap(config, optarg) == false) {
|
|
382
571
|
fprintf(stderr,
|
|
@@ -433,11 +622,13 @@ main (int argc, char **argv)
|
|
|
433
622
|
{
|
|
434
623
|
// Default program config.
|
|
435
624
|
struct config config = {
|
|
436
|
-
.file
|
|
437
|
-
.fp
|
|
438
|
-
.wrap
|
|
439
|
-
.decode
|
|
440
|
-
.print_help
|
|
625
|
+
.file = "stdin",
|
|
626
|
+
.fp = stdin,
|
|
627
|
+
.wrap = 76,
|
|
628
|
+
.decode = false,
|
|
629
|
+
.print_help = false,
|
|
630
|
+
.strip_newlines = true,
|
|
631
|
+
.ignore_garbage = false,
|
|
441
632
|
};
|
|
442
633
|
struct buffer buf;
|
|
443
634
|
|
|
@@ -458,6 +649,15 @@ main (int argc, char **argv)
|
|
|
458
649
|
return 1;
|
|
459
650
|
}
|
|
460
651
|
|
|
652
|
+
#ifdef WIN
|
|
653
|
+
|
|
654
|
+
// On Windows, ensure that stdout is binary-clean, and does not
|
|
655
|
+
// silently convert newlines to CRLFs. This seems to be the portable
|
|
656
|
+
// way to do it; freopen() and SetConsoleMode() occasionally result in
|
|
657
|
+
// permission errors, whereas this always seems to work.
|
|
658
|
+
_setmode(1, _O_BINARY);
|
|
659
|
+
#endif
|
|
660
|
+
|
|
461
661
|
// Encode or decode the input based on the user's choice.
|
|
462
662
|
const bool ret = config.decode
|
|
463
663
|
? decode(&config, &buf)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
2
|
+
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
3
|
+
<assemblyIdentity type="win32" name="base64" version="0.5.2.0" />
|
|
4
|
+
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
|
5
|
+
<security>
|
|
6
|
+
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
|
7
|
+
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
|
8
|
+
</requestedPrivileges>
|
|
9
|
+
</security>
|
|
10
|
+
</trustInfo>
|
|
11
|
+
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
|
12
|
+
<application>
|
|
13
|
+
<!-- Windows 10 and Windows 11 -->
|
|
14
|
+
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
|
15
|
+
</application>
|
|
16
|
+
</compatibility>
|
|
17
|
+
<application>
|
|
18
|
+
<windowsSettings>
|
|
19
|
+
<activeCodePage
|
|
20
|
+
xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
|
|
21
|
+
</windowsSettings>
|
|
22
|
+
</application>
|
|
23
|
+
</assembly>
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
|
|
34
34
|
#endif // HAVE_AVX
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
void
|
|
37
|
+
base64_stream_encode_avx BASE64_ENC_PARAMS
|
|
37
38
|
{
|
|
38
39
|
#if HAVE_AVX
|
|
39
40
|
#include "../generic/enc_head.c"
|
|
@@ -50,17 +51,18 @@ BASE64_ENC_FUNCTION(avx)
|
|
|
50
51
|
|
|
51
52
|
#include "../generic/enc_tail.c"
|
|
52
53
|
#else
|
|
53
|
-
|
|
54
|
+
base64_enc_stub(state, src, srclen, out, outlen);
|
|
54
55
|
#endif
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
int
|
|
59
|
+
base64_stream_decode_avx BASE64_DEC_PARAMS
|
|
58
60
|
{
|
|
59
61
|
#if HAVE_AVX
|
|
60
62
|
#include "../generic/dec_head.c"
|
|
61
63
|
dec_loop_ssse3(&s, &slen, &o, &olen);
|
|
62
64
|
#include "../generic/dec_tail.c"
|
|
63
65
|
#else
|
|
64
|
-
|
|
66
|
+
return base64_dec_stub(state, src, srclen, out, outlen);
|
|
65
67
|
#endif
|
|
66
68
|
}
|
|
@@ -33,24 +33,26 @@
|
|
|
33
33
|
|
|
34
34
|
#endif // HAVE_AVX2
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
void
|
|
37
|
+
base64_stream_encode_avx2 BASE64_ENC_PARAMS
|
|
37
38
|
{
|
|
38
39
|
#if HAVE_AVX2
|
|
39
40
|
#include "../generic/enc_head.c"
|
|
40
41
|
enc_loop_avx2(&s, &slen, &o, &olen);
|
|
41
42
|
#include "../generic/enc_tail.c"
|
|
42
43
|
#else
|
|
43
|
-
|
|
44
|
+
base64_enc_stub(state, src, srclen, out, outlen);
|
|
44
45
|
#endif
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
int
|
|
49
|
+
base64_stream_decode_avx2 BASE64_DEC_PARAMS
|
|
48
50
|
{
|
|
49
51
|
#if HAVE_AVX2
|
|
50
52
|
#include "../generic/dec_head.c"
|
|
51
53
|
dec_loop_avx2(&s, &slen, &o, &olen);
|
|
52
54
|
#include "../generic/dec_tail.c"
|
|
53
55
|
#else
|
|
54
|
-
|
|
56
|
+
return base64_dec_stub(state, src, srclen, out, outlen);
|
|
55
57
|
#endif
|
|
56
58
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
static
|
|
1
|
+
static BASE64_FORCE_INLINE void
|
|
2
2
|
enc_loop_avx2_inner_first (const uint8_t **s, uint8_t **o)
|
|
3
3
|
{
|
|
4
4
|
// First load is done at s - 0 to not get a segfault:
|
|
@@ -17,7 +17,7 @@ enc_loop_avx2_inner_first (const uint8_t **s, uint8_t **o)
|
|
|
17
17
|
*o += 32;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
static
|
|
20
|
+
static BASE64_FORCE_INLINE void
|
|
21
21
|
enc_loop_avx2_inner (const uint8_t **s, uint8_t **o)
|
|
22
22
|
{
|
|
23
23
|
// Load input:
|