Repository: tobiaslocker/base64
Branch: master
Commit: 8d96a2a737ac
Files: 15
Total size: 67.7 KB
Directory structure:
gitextract_49o6eegi/
├── .clang-format
├── .github/
│ └── workflows/
│ ├── bigendiancmake.yml
│ ├── cmake.yml
│ └── cpplint.yml
├── .gitignore
├── CMakeLists.txt
├── CPPLINT.cfg
├── LICENSE
├── README.md
├── include/
│ └── base64.hpp
├── scripts/
│ ├── run-clang-format.sh
│ └── run-s390x-emulation.sh
└── test/
├── base64_tests.cpp
├── modp_b64_tests.cpp
└── roundtrip_test.cpp
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
BasedOnStyle: Google
IndentWidth: 2
UseTab: Never
ColumnLimit: 0
NamespaceIndentation: None
BreakBeforeBraces: Attach
AllowShortFunctionsOnASingleLine: Inline
ReflowComments: true
================================================
FILE: .github/workflows/bigendiancmake.yml
================================================
name: CMake on s390x emulation (Big endian system)
on: [push, pull_request]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo
jobs:
build-linux-s390x:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: uraimo/run-on-arch-action@v2
name: Run commands
id: runcmd
with:
arch: s390x
distro: ubuntu_latest
install: |
apt-get update -q -y
apt-get -y install cmake
apt-get -y install make
apt-get -y install g++
apt-get -y install git
run: |
lscpu | grep Endian
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} .
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
cd ${{github.workspace}}/build
ctest -C ${{env.BUILD_TYPE}} --output-on-failure
================================================
FILE: .github/workflows/cmake.yml
================================================
name: CMake
on: [push, pull_request]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Install optional tools (clang-tidy)
if: matrix.os == 'ubuntu-latest'
run: sudo apt-get install -y clang-tidy
- name: Configure CMake (Windows)
if: runner.os == 'Windows'
# Configure CMake in a 'build' subdirectory.
# `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} .
- name: Configure CMake (Other OS)
if: runner.os != 'Windows'
# Configure CMake in a 'build' subdirectory.
# `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -USE_ASAN=ON -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} .
- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure
================================================
FILE: .github/workflows/cpplint.yml
================================================
# GitHub Action to run cpplint recursively on all pushes and pull requests
# https://github.com/cpplint/GitHub-Action-for-cpplint
name: cpplint
on: [push, pull_request]
jobs:
cpplint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: 3.x
- run: pip install cpplint
- run: cpplint --root=include --recursive .
================================================
FILE: .gitignore
================================================
main.cpp
build
*.user
*.swp
scripts/build.sh
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.16)
project(base64)
option(BASE64_ENABLE_TESTING "Build test files." ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()
# Warnings compiler flags
if(MSVC)
add_compile_options(/W4)
else()
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# Optionally enable clang-tidy
find_program(CLANG_TIDY_EXE NAMES clang-tidy PATHS /opt/homebrew/opt/llvm/bin/)
if(NOT CLANG_TIDY_EXE)
message(STATUS "clang-tidy not found. Skipping corresponding checks.")
else()
set(CMAKE_CXX_CLANG_TIDY
${CLANG_TIDY_EXE};
-header-filter=.*;
-checks=-*,portability-*,bugprone-*,-bugprone-easily-swappable-parameters,-bugprone-sizeof-expression,clang-analyzer-*;
)
message(STATUS "Found clang-tidy: ${CLANG_TIDY_EXE}.")
endif()
# Simplify the use of ASan
option(USE_ASAN "Activate ASan compiler/linker options" OFF)
if(USE_ASAN)
if(MSVC)
add_compile_options(/fsanitize=address)
add_link_options(/fsanitize=address)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
else()
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
add_link_options(-fsanitize=address)
endif()
endif()
add_library(base64 INTERFACE)
target_include_directories(base64 INTERFACE include)
if (BASE64_ENABLE_TESTING)
add_executable(roundtrip_test test/roundtrip_test.cpp)
target_link_libraries(roundtrip_test PRIVATE base64)
enable_testing()
add_test(NAME roundtrip_test COMMAND roundtrip_test)
# Add some more tests
include(FetchContent)
if(${CMAKE_CXX_BYTE_ORDER} MATCHES BIG_ENDIAN)
set(FETCHCONTENT_QUIET FALSE)
endif()
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG b514bdc898e2951020cbdca1304b75f5950d1f59
GIT_PROGRESS TRUE
SYSTEM
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
set_target_properties(gtest PROPERTIES CXX_CLANG_TIDY "")
set_target_properties(gtest_main PROPERTIES CXX_CLANG_TIDY "")
set_target_properties(gmock PROPERTIES CXX_CLANG_TIDY "")
set_target_properties(gmock_main PROPERTIES CXX_CLANG_TIDY "")
add_executable(base64_tests test/base64_tests.cpp)
target_link_libraries(base64_tests PRIVATE base64)
target_link_libraries(base64_tests PRIVATE GTest::gtest GTest::gtest_main)
add_test(NAME base64_tests COMMAND base64_tests)
add_executable(modp_b64_tests test/modp_b64_tests.cpp)
target_link_libraries(modp_b64_tests PRIVATE base64)
target_link_libraries(modp_b64_tests PRIVATE GTest::gtest GTest::gtest_main)
add_test(NAME modp_b64_tests COMMAND modp_b64_tests)
endif()
================================================
FILE: CPPLINT.cfg
================================================
filter=-legal/copyright
filter=-readability/todo
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 Tobias Locker
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# base64
A simple, header-only C++17 library for Base64 encoding and decoding. Uses modern C++ features when available
(e.g., `std::bit_cast` in C++20) while remaining portable and efficient.
## Features
- Header-only, single-file library
- Fast encoding/decoding using lookup tables
- Safe type punning using `std::bit_cast` (avoids undefined behavior with unions)
- Throws `std::runtime_error` for invalid Base64 input (size, padding, or characters)
## Platform Support
- Compilers: GCC, Clang, MSVC
- Architectures: x86, x64, ARM, AArch64 (little-endian)
- Requires C++17 (C++20 features optional)
## Usage
```cpp
#include <iostream>
#include "base64.hpp"
int main() {
auto encoded = base64::to_base64("Hello, World!");
std::cout << encoded << std::endl; // SGVsbG8sIFdvcmxkIQ==
auto decoded = base64::from_base64("SGVsbG8sIFdvcmxkIQ==");
std::cout << decoded << std::endl; // Hello, World!
}
```
## Notes
- Inspired by Nick Galbreath's modp_b64 (used by Chromium) for high performance
- Compatible with C++17; optionally uses C++20 features
- Avoids union-based type punning for safety
- Faster implementations exist using SIMD or multithreading but are not header-only
## References
- Benchmark of C/C++ Base64 libraries: https://github.com/gaspardpetit/base64/
- Chromium modp_b64: https://github.com/chromium/chromium/tree/main/third_party/modp_b64
- SIMD/optimized alternatives:
- https://github.com/aklomp/base64
- https://github.com/simdutf/simdutf
- https://github.com/powturbo/Turbo-Base64
================================================
FILE: include/base64.hpp
================================================
#ifndef BASE64_HPP_
#define BASE64_HPP_
#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#if defined(__cpp_lib_bit_cast)
#include <bit> // For std::bit_cast.
#endif
namespace base64 {
namespace detail {
#if defined(__cpp_lib_bit_cast)
using std::bit_cast;
#else
template <class To, class From>
std::enable_if_t<sizeof(To) == sizeof(From) &&
std::is_trivially_copyable_v<From> &&
std::is_trivially_copyable_v<To>,
To> bit_cast(const From& src) noexcept {
static_assert(std::is_trivially_constructible_v<To>,
"This implementation additionally requires "
"destination type to be trivially constructible");
To dst;
std::memcpy(&dst, &src, sizeof(To));
return dst;
}
#endif
inline constexpr char padding_char{'='};
inline constexpr uint32_t bad_char{0x01FFFFFF};
#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
(defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) || \
(defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN) || \
(defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || \
(defined(__sun) && defined(__SVR4) && defined(_BIG_ENDIAN)) || \
defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__) || \
defined(_M_PPC)
#define __BIG_ENDIAN__
#elif (defined(__BYTE_ORDER__) && \
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || /* gcc */ \
(defined(__BYTE_ORDER) && \
__BYTE_ORDER == __LITTLE_ENDIAN) /* linux header */ \
|| (defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN) || \
(defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) /* mingw header */ || \
(defined(__sun) && defined(__SVR4) && \
defined(_LITTLE_ENDIAN)) || /* solaris */ \
defined(__ARMEL__) || \
defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || \
defined(__MIPSEL) || defined(__MIPSEL__) || defined(_M_IX86) || \
defined(_M_X64) || defined(_M_IA64) || /* msvc for intel processors */ \
defined(_M_ARM) || \
defined(_M_ARM64) /* msvc code on arm executes in little endian mode */
#define __LITTLE_ENDIAN__
#endif
#endif
#if !defined(__LITTLE_ENDIAN__) & !defined(__BIG_ENDIAN__)
#error "UNKNOWN Platform / endianness. Configure endianness explicitly."
#endif
#if defined(__LITTLE_ENDIAN__)
std::array<std::uint32_t, 256> constexpr decode_table_0 = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x000000f8, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x000000fc,
0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4,
0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 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, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 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, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
};
std::array<std::uint32_t, 256> constexpr decode_table_1 = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x0000e003, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000f003,
0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003,
0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 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, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 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, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
};
std::array<std::uint32_t, 256> constexpr decode_table_2 = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x00800f00, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00c00f00,
0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00,
0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 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, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 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, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
};
std::array<std::uint32_t, 256> constexpr decode_table_3 = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x003e0000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x003f0000,
0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000,
0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 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, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 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, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
};
// TODO fix decoding tables to avoid the need for different indices in big
// endian?
inline constexpr size_t decidx0{0};
inline constexpr size_t decidx1{1};
inline constexpr size_t decidx2{2};
#elif defined(__BIG_ENDIAN__)
std::array<std::uint32_t, 256> constexpr decode_table_0 = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x00f80000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00fc0000,
0x00d00000, 0x00d40000, 0x00d80000, 0x00dc0000, 0x00e00000, 0x00e40000,
0x00e80000, 0x00ec0000, 0x00f00000, 0x00f40000, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00040000, 0x00080000, 0x000c0000, 0x00100000, 0x00140000, 0x00180000,
0x001c0000, 0x00200000, 0x00240000, 0x00280000, 0x002c0000, 0x00300000,
0x00340000, 0x00380000, 0x003c0000, 0x00400000, 0x00440000, 0x00480000,
0x004c0000, 0x00500000, 0x00540000, 0x00580000, 0x005c0000, 0x00600000,
0x00640000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x00680000, 0x006c0000, 0x00700000, 0x00740000, 0x00780000,
0x007c0000, 0x00800000, 0x00840000, 0x00880000, 0x008c0000, 0x00900000,
0x00940000, 0x00980000, 0x009c0000, 0x00a00000, 0x00a40000, 0x00a80000,
0x00ac0000, 0x00b00000, 0x00b40000, 0x00b80000, 0x00bc0000, 0x00c00000,
0x00c40000, 0x00c80000, 0x00cc0000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
};
std::array<std::uint32_t, 256> constexpr decode_table_1 = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x0003e000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0003f000,
0x00034000, 0x00035000, 0x00036000, 0x00037000, 0x00038000, 0x00039000,
0x0003a000, 0x0003b000, 0x0003c000, 0x0003d000, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,
0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,
0x0000d000, 0x0000e000, 0x0000f000, 0x00010000, 0x00011000, 0x00012000,
0x00013000, 0x00014000, 0x00015000, 0x00016000, 0x00017000, 0x00018000,
0x00019000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x0001a000, 0x0001b000, 0x0001c000, 0x0001d000, 0x0001e000,
0x0001f000, 0x00020000, 0x00021000, 0x00022000, 0x00023000, 0x00024000,
0x00025000, 0x00026000, 0x00027000, 0x00028000, 0x00029000, 0x0002a000,
0x0002b000, 0x0002c000, 0x0002d000, 0x0002e000, 0x0002f000, 0x00030000,
0x00031000, 0x00032000, 0x00033000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
};
std::array<std::uint32_t, 256> constexpr decode_table_2 = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x00000f80, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000fc0,
0x00000d00, 0x00000d40, 0x00000d80, 0x00000dc0, 0x00000e00, 0x00000e40,
0x00000e80, 0x00000ec0, 0x00000f00, 0x00000f40, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00000040, 0x00000080, 0x000000c0, 0x00000100, 0x00000140, 0x00000180,
0x000001c0, 0x00000200, 0x00000240, 0x00000280, 0x000002c0, 0x00000300,
0x00000340, 0x00000380, 0x000003c0, 0x00000400, 0x00000440, 0x00000480,
0x000004c0, 0x00000500, 0x00000540, 0x00000580, 0x000005c0, 0x00000600,
0x00000640, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x00000680, 0x000006c0, 0x00000700, 0x00000740, 0x00000780,
0x000007c0, 0x00000800, 0x00000840, 0x00000880, 0x000008c0, 0x00000900,
0x00000940, 0x00000980, 0x000009c0, 0x00000a00, 0x00000a40, 0x00000a80,
0x00000ac0, 0x00000b00, 0x00000b40, 0x00000b80, 0x00000bc0, 0x00000c00,
0x00000c40, 0x00000c80, 0x00000cc0, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
};
std::array<std::uint32_t, 256> constexpr decode_table_3 = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x0000003e, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000003f,
0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039,
0x0000003a, 0x0000003b, 0x0000003c, 0x0000003d, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006,
0x00000007, 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
0x0000000d, 0x0000000e, 0x0000000f, 0x00000010, 0x00000011, 0x00000012,
0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, 0x00000018,
0x00000019, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, 0x0000001e,
0x0000001f, 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024,
0x00000025, 0x00000026, 0x00000027, 0x00000028, 0x00000029, 0x0000002a,
0x0000002b, 0x0000002c, 0x0000002d, 0x0000002e, 0x0000002f, 0x00000030,
0x00000031, 0x00000032, 0x00000033, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
};
// TODO fix decoding tables to avoid the need for different indices in big
// endian?
inline constexpr size_t decidx0{1};
inline constexpr size_t decidx1{2};
inline constexpr size_t decidx2{3};
#endif
std::array<char, 256> constexpr encode_table_0 = {
'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D',
'D', 'E', 'E', 'E', 'E', 'F', 'F', 'F', 'F', 'G', 'G', 'G', 'G', 'H', 'H',
'H', 'H', 'I', 'I', 'I', 'I', 'J', 'J', 'J', 'J', 'K', 'K', 'K', 'K', 'L',
'L', 'L', 'L', 'M', 'M', 'M', 'M', 'N', 'N', 'N', 'N', 'O', 'O', 'O', 'O',
'P', 'P', 'P', 'P', 'Q', 'Q', 'Q', 'Q', 'R', 'R', 'R', 'R', 'S', 'S', 'S',
'S', 'T', 'T', 'T', 'T', 'U', 'U', 'U', 'U', 'V', 'V', 'V', 'V', 'W', 'W',
'W', 'W', 'X', 'X', 'X', 'X', 'Y', 'Y', 'Y', 'Y', 'Z', 'Z', 'Z', 'Z', 'a',
'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd',
'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g', 'g', 'g', 'h', 'h', 'h',
'h', 'i', 'i', 'i', 'i', 'j', 'j', 'j', 'j', 'k', 'k', 'k', 'k', 'l', 'l',
'l', 'l', 'm', 'm', 'm', 'm', 'n', 'n', 'n', 'n', 'o', 'o', 'o', 'o', 'p',
'p', 'p', 'p', 'q', 'q', 'q', 'q', 'r', 'r', 'r', 'r', 's', 's', 's', 's',
't', 't', 't', 't', 'u', 'u', 'u', 'u', 'v', 'v', 'v', 'v', 'w', 'w', 'w',
'w', 'x', 'x', 'x', 'x', 'y', 'y', 'y', 'y', 'z', 'z', 'z', 'z', '0', '0',
'0', '0', '1', '1', '1', '1', '2', '2', '2', '2', '3', '3', '3', '3', '4',
'4', '4', '4', '5', '5', '5', '5', '6', '6', '6', '6', '7', '7', '7', '7',
'8', '8', '8', '8', '9', '9', '9', '9', '+', '+', '+', '+', '/', '/', '/',
'/'
};
std::array<char, 256> constexpr encode_table_1 = {
'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', '+', '/', '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', '+', '/', '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', '+', '/', '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', '+',
'/'
};
} // namespace detail
template <class OutputBuffer, class InputIterator>
inline OutputBuffer encode_into(InputIterator begin, InputIterator end) {
typedef std::decay_t<decltype(*begin)> input_value_type;
static_assert(std::is_same_v<input_value_type, char> ||
std::is_same_v<input_value_type, signed char> ||
std::is_same_v<input_value_type, unsigned char> ||
std::is_same_v<input_value_type, std::byte>);
typedef typename OutputBuffer::value_type output_value_type;
static_assert(std::is_same_v<output_value_type, char> ||
std::is_same_v<output_value_type, signed char> ||
std::is_same_v<output_value_type, unsigned char> ||
std::is_same_v<output_value_type, std::byte>);
const size_t binarytextsize = end - begin;
const size_t encodedsize = (binarytextsize / 3 + (binarytextsize % 3 > 0))
<< 2;
OutputBuffer encoded(encodedsize, detail::padding_char);
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&*begin);
char* currEncoding = reinterpret_cast<char*>(&encoded[0]);
for (size_t i = binarytextsize / 3; i; --i) {
const uint8_t t1 = *bytes++;
const uint8_t t2 = *bytes++;
const uint8_t t3 = *bytes++;
*currEncoding++ = detail::encode_table_0[t1];
*currEncoding++ =
detail::encode_table_1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*currEncoding++ =
detail::encode_table_1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
*currEncoding++ = detail::encode_table_1[t3];
}
switch (binarytextsize % 3) {
case 0: {
break;
}
case 1: {
const uint8_t t1 = bytes[0];
*currEncoding++ = detail::encode_table_0[t1];
*currEncoding++ = detail::encode_table_1[(t1 & 0x03) << 4];
break;
}
case 2: {
const uint8_t t1 = bytes[0];
const uint8_t t2 = bytes[1];
*currEncoding++ = detail::encode_table_0[t1];
*currEncoding++ =
detail::encode_table_1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*currEncoding++ = detail::encode_table_1[(t2 & 0x0F) << 2];
break;
}
default: {
throw std::runtime_error{"Invalid base64 encoded data"};
}
}
return encoded;
}
template <class OutputBuffer>
inline OutputBuffer encode_into(std::string_view data) {
return encode_into<OutputBuffer>(std::begin(data), std::end(data));
}
inline std::string to_base64(std::string_view data) {
return encode_into<std::string>(std::begin(data), std::end(data));
}
template <class OutputBuffer>
inline OutputBuffer decode_into(std::string_view base64Text) {
typedef typename OutputBuffer::value_type output_value_type;
static_assert(std::is_same_v<output_value_type, char> ||
std::is_same_v<output_value_type, signed char> ||
std::is_same_v<output_value_type, unsigned char> ||
std::is_same_v<output_value_type, std::byte>);
if (base64Text.empty()) {
return OutputBuffer();
}
if ((base64Text.size() & 3) != 0) {
throw std::runtime_error{
"Invalid base64 encoded data - Size not divisible by 4"};
}
const size_t numPadding =
std::count(base64Text.rbegin(), base64Text.rbegin() + 4, '=');
if (numPadding > 2) {
throw std::runtime_error{
"Invalid base64 encoded data - Found more than 2 padding signs"};
}
const size_t decodedsize = (base64Text.size() * 3 >> 2) - numPadding;
OutputBuffer decoded(decodedsize, '.');
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&base64Text[0]);
char* currDecoding = reinterpret_cast<char*>(&decoded[0]);
for (size_t i = (base64Text.size() >> 2) - (numPadding != 0); i; --i) {
const uint8_t t1 = *bytes++;
const uint8_t t2 = *bytes++;
const uint8_t t3 = *bytes++;
const uint8_t t4 = *bytes++;
const uint32_t d1 = detail::decode_table_0[t1];
const uint32_t d2 = detail::decode_table_1[t2];
const uint32_t d3 = detail::decode_table_2[t3];
const uint32_t d4 = detail::decode_table_3[t4];
const uint32_t temp = d1 | d2 | d3 | d4;
if (temp >= detail::bad_char) {
throw std::runtime_error{
"Invalid base64 encoded data - Invalid character"};
}
// Use bit_cast instead of union and type punning to avoid
// undefined behaviour risk:
// https://en.wikipedia.org/wiki/Type_punning#Use_of_union
const std::array<char, 4> tempBytes =
detail::bit_cast<std::array<char, 4>, uint32_t>(temp);
*currDecoding++ = tempBytes[detail::decidx0];
*currDecoding++ = tempBytes[detail::decidx1];
*currDecoding++ = tempBytes[detail::decidx2];
}
switch (numPadding) {
case 0: {
break;
}
case 1: {
const uint8_t t1 = *bytes++;
const uint8_t t2 = *bytes++;
const uint8_t t3 = *bytes++;
const uint32_t d1 = detail::decode_table_0[t1];
const uint32_t d2 = detail::decode_table_1[t2];
const uint32_t d3 = detail::decode_table_2[t3];
const uint32_t temp = d1 | d2 | d3;
if (temp >= detail::bad_char) {
throw std::runtime_error{
"Invalid base64 encoded data - Invalid character"};
}
// Use bit_cast instead of union and type punning to avoid
// undefined behaviour risk:
// https://en.wikipedia.org/wiki/Type_punning#Use_of_union
const std::array<char, 4> tempBytes =
detail::bit_cast<std::array<char, 4>, uint32_t>(temp);
*currDecoding++ = tempBytes[detail::decidx0];
*currDecoding++ = tempBytes[detail::decidx1];
break;
}
case 2: {
const uint8_t t1 = *bytes++;
const uint8_t t2 = *bytes++;
const uint32_t d1 = detail::decode_table_0[t1];
const uint32_t d2 = detail::decode_table_1[t2];
const uint32_t temp = d1 | d2;
if (temp >= detail::bad_char) {
throw std::runtime_error{
"Invalid base64 encoded data - Invalid character"};
}
const std::array<char, 4> tempBytes =
detail::bit_cast<std::array<char, 4>, uint32_t>(temp);
*currDecoding++ = tempBytes[detail::decidx0];
break;
}
default: {
throw std::runtime_error{
"Invalid base64 encoded data - Invalid padding number"};
}
}
return decoded;
}
template <class OutputBuffer, class InputIterator>
inline OutputBuffer decode_into(InputIterator begin, InputIterator end) {
typedef std::decay_t<decltype(*begin)> input_value_type;
static_assert(std::is_same_v<input_value_type, char> ||
std::is_same_v<input_value_type, signed char> ||
std::is_same_v<input_value_type, unsigned char> ||
std::is_same_v<input_value_type, std::byte>);
std::string_view data(reinterpret_cast<const char*>(&*begin), end - begin);
return decode_into<OutputBuffer>(data);
}
inline std::string from_base64(std::string_view data) {
return decode_into<std::string>(data);
}
} // namespace base64
#endif // BASE64_HPP_
================================================
FILE: scripts/run-clang-format.sh
================================================
#!/usr/bin/env sh
clang-format -style=Google -i include/*.hpp
clang-format -style=Google -i test/*.cpp
================================================
FILE: scripts/run-s390x-emulation.sh
================================================
#!/usr/bin/env sh
#
#docker run --rm --privileged multiarch/qemu-user-static:register --reset
docker run -it multiarch/ubuntu-core:s390x-focal /bin/bash
apt-get update -q -y && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends make cmake g++ git
#software-properties-common
cd home
git clone https://github.com/tvercaut/base64.git
cd base64
git checkout modpb64xover
cmake -B ./build -DCMAKE_BUILD_TYPE=Debug .
cmake --build ./build --config Debug
cd build
ctest -C Debug --output-on-failure
================================================
FILE: test/base64_tests.cpp
================================================
// Test suite ported from https://github.com/matheusgomes28/base64pp
#include <gtest/gtest.h>
#include <array>
#include <cstdint>
#include <string>
#include <vector>
#include "../include/base64.hpp"
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesEmpty) {
std::string const expected{};
std::string const actual{base64::to_base64({})};
ASSERT_EQ(expected, actual);
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesThreeBytesZeros) {
std::array<std::uint8_t, 3> const input{0x00, 0x00, 0x00};
auto const expected{"AAAA"};
auto const actual{base64::encode_into<std::string>(begin(input), end(input))};
ASSERT_EQ(expected, actual);
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesThreeBytesRandom) {
std::array<std::uint8_t, 3> const input{0xFE, 0xE9, 0x72};
auto const expected{"/uly"};
auto const actual{base64::encode_into<std::string>(begin(input), end(input))};
ASSERT_EQ(expected, actual);
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesTwoBytes) {
std::array<std::uint8_t, 2> const input{0x00, 0x00};
auto const expected{"AAA="};
auto const actual{base64::encode_into<std::string>(begin(input), end(input))};
ASSERT_EQ(expected, actual);
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesOneByte) {
std::array<std::uint8_t, 1> const input{0x00};
auto const expected{"AA=="};
auto const actual{base64::encode_into<std::string>(begin(input), end(input))};
ASSERT_EQ(expected, actual);
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesFourBytes) {
std::array<std::uint8_t, 4> const input{0x74, 0x68, 0x65, 0x20};
auto const expected{"dGhlIA=="};
auto const actual{base64::encode_into<std::string>(begin(input), end(input))};
ASSERT_EQ(expected, actual);
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesFiveBytes) {
std::array<std::uint8_t, 5> const input{0x20, 0x62, 0x72, 0x6f, 0x77};
auto const expected{"IGJyb3c="};
auto const actual{base64::encode_into<std::string>(begin(input), end(input))};
ASSERT_EQ(actual, expected);
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesSixBytes) {
std::array<std::uint8_t, 6> const input{0x20, 0x6a, 0x75, 0x6d, 0x70, 0x73};
auto const expected{"IGp1bXBz"};
auto const actual{base64::encode_into<std::string>(begin(input), end(input))};
ASSERT_EQ(actual, expected);
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesBrownFox) {
std::array<std::uint8_t, 43> const input{
0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x62,
0x72, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75,
0x6d, 0x70, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68,
0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67};
auto const expected{
"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="};
auto const actual{base64::encode_into<std::string>(begin(input), end(input))};
ASSERT_EQ(actual, expected);
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodesBrownFastFoxNullInMiddle) {
std::array<std::uint8_t, 45> const input{
0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x21, 0x20, 0x62,
0x72, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d,
0x70, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x00,
0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67};
auto const expected{
"dGhlIHF1aWNrISBicm93biBmb3gganVtcHMgb3ZlciB0aGUAIGxhenkgZG9n"};
auto const actual{base64::encode_into<std::string>(begin(input), end(input))};
ASSERT_EQ(actual, expected);
}
// NOLINTNEXTLINE
TEST(Base64Decode, FailDecodeOneString) {
std::string const input{"1"};
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
}
// NOLINTNEXTLINE
TEST(Base64Decode, FailDecodeOneStringPadded) {
std::string const input{"1==="};
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
}
// NOLINTNEXTLINE
TEST(Base64Decode, FailDecodeOneCharRemaining) {
std::string const input{"something"};
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
}
// NOLINTNEXTLINE
TEST(Base64Decode, FailDecodeNonSize4Bigger) {
std::string const input{"SomethingEntirelyDifferent"};
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
// For the record - expected decoding if relaxed checks
// std::vector<std::uint8_t> const expected{0x4A, 0x89, 0x9E, 0xB6, 0x18,
// 0xA7, 0x80, 0x49, 0xED, 0x8A, 0xB7, 0xA5,
// 0xC8, 0x38, 0x9F, 0x7D, 0xEA, 0xDE, 0x9E};
}
// NOLINTNEXTLINE
TEST(Base64Decode, FailDecodeNonBase64Short) {
std::string const input{"a aa"};
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
}
// NOLINTNEXTLINE
TEST(Base64Decode, FailDecodeNonBase64Longer) {
std::string const input{"aaa`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"};
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesMissingTwoPads0) {
std::string const input{"12"};
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
// For the record - expected decoding if relaxed checks
// std::vector<std::uint8_t> const expected{0xD7};
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesMissingTwoPads1) {
std::string const input = "AA";
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
// For the record - expected decoding if relaxed checks
// std::vector<std::uint8_t> const expected{0x00};
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesMissingOnePad0) {
std::string const input = "AAA";
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
// For the record - expected decoding if relaxed checks
// std::vector<std::uint8_t> const expected{0x00, 0x00};
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesMissingOnePad1) {
std::string const input{"12a"};
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
// For the record - expected decoding if relaxed checks
// std::vector<std::uint8_t> const expected{0xD7, 0x66};
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesMissingIssueExample) {
std::string const input = "eyJuYW1lIjoiSm9obiBEb2UifQ";
ASSERT_THROW(base64::from_base64(input), std::runtime_error);
// For the record - expected decoding if relaxed checks
// std::string const expected_str = R"({"name":"John Doe"})";
// See https://github.com/matheusgomes28/base64pp/issues/84
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesEmptyString) {
std::string expected{};
auto const actual{base64::from_base64("")};
ASSERT_EQ(expected, actual);
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesZeroArray) {
std::string const input{"AAAA"};
std::vector<std::uint8_t> const expected{0x00, 0x00, 0x00};
auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};
ASSERT_EQ(actual, expected);
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesZeroArrayTwice) {
std::string const input{"AAAAAAAA"};
std::vector<std::uint8_t> const expected{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};
ASSERT_EQ(actual, expected);
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesZeroArrayOneByte) {
std::string const input{"AA=="};
std::vector<std::uint8_t> const expected{0x00};
auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};
ASSERT_EQ(actual, expected);
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesZeroArrayTwoBytes) {
std::string const input{"AAA="};
std::vector<std::uint8_t> const expected{0x00, 0x00};
auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};
ASSERT_EQ(actual, expected);
}
// NOLINTNEXTLINE
TEST(Base64Decode, DecodesQuickFox) {
std::string const input{
"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="};
std::vector<std::uint8_t> const expected{
0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x62,
0x72, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75,
0x6d, 0x70, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68,
0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67};
auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};
ASSERT_EQ(actual, expected);
}
// NOLINTNEXTLINE
TEST(Base64RoundTripTests, AllPossibleBytes) {
std::vector<std::uint8_t> all_possible_bytes;
for (std::size_t i = 0; i <= 255; ++i) {
all_possible_bytes.push_back(static_cast<std::uint8_t>(i));
}
auto const encode_string = base64::encode_into<std::string>(
begin(all_possible_bytes), end(all_possible_bytes));
auto const decoded_bytes =
base64::decode_into<std::vector<std::uint8_t>>(encode_string);
ASSERT_EQ(all_possible_bytes, decoded_bytes);
}
// NOLINTNEXTLINE
TEST(Base64RoundTripTests, ExhaustiveTests) {
std::vector<std::string> const base64_strings = {
"YW55IGNhcm5hbCBwbGVhcw==",
"bGVnYWwgcGFzcw==",
"dGVzdCBzdHJpbmc=",
"bGVnYWwgcHJvdmlkZXI=",
"ZW5vdWdoIHRoZSBzYW1lIG9mIHRoZSBwbGFjZQ==",
"YW5vdGhlciB0aGUgc3RyYWlnaHQ=",
"d2FzIG1lIGFkZHJlc3MgcHJvdmlkZXI=",
"YWJvdXQgdGhlIG1hc3RlciBvZiB0aGUgZGFtYWdl",
"ZW50aXJlIHRoYXQgYnJvdWdodCBvZiB0aGUgbW9uZXk=",
"bGVnYWwgc2VjdXJpdHk=",
"YmFzaWMgZ29vZCBvZiB0aGUgcGFkIHN0cmluZw==",
"ZGVsZXRlIHN0cmluZyBvZiB0aGUgc3RyYWlnaHQ=",
"YnJvdWdodCBvZiB0aGUgcGFkIGZvbGRlciBvZiB0aGUgZGFtYWdl",
"aW50ZXJmYWNlIHN0cmluZw==",
"Y29uc29sZS1tZS1jb21wYW55",
"aW5mb3JtYXRpb24tbWVkaWE=",
"c3RhdHVzLXNlY3VyZQ==",
"Y3JlYXRlLWNvbXBhbnktc3RyaW5n",
"b3JkZXItbGVhZGVy",
"Y2F0YWxvZy1wcm9maWxl",
"dGVzdC1jb25zdWx0aW5n",
"YnJvdWdodC1sZWFkZXI=",
"YXNzaWduLW1lY2hhbmlzbQ==",
"bGVnYWwtY29udGFpbmVy",
"ZW1haWwtY29udGFpbmVy",
"aW5zdGFuY2UtY29udGFpbmVy",
"dGVzdC1jb21wYW55LWFuZC1wcm9maWxl",
"YmFzZTY0LWJhc2U=",
"cGFzc3dvcmQ=",
"Zm9vYmFy",
"Y29vbC1iYXNl",
"YmFzZTY0LXNlY3VyZQ==",
"aW50ZXJ2YWw=",
"dGhlLW1hc3Rlci1vZi10aGUtZGFtYWdl",
"c2FtZS1wbGFjZS1vZi10aGUtZGFtYWdl",
"aGFzaC1zb21ldGhpbmc="};
for (auto const& b64_string : base64_strings) {
auto const decoded = base64::from_base64(b64_string);
auto const encoded_round_trip = base64::to_base64(decoded);
ASSERT_EQ(encoded_round_trip, b64_string);
}
}
// NOLINTNEXTLINE
TEST(Base64OverloadTests, EncodesString1) {
std::array<std::pair<std::string, std::string>, 11> const test_cases = {
{{"", ""},
{"Hello, World!", "SGVsbG8sIFdvcmxkIQ=="},
{"abcdefghijklmnopqrstuvwxyz0123456789\\`!\"£$%^&*()_+",
"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5XGAhIsKjJCVeJiooKV8r"},
{"Base64 encoding", "QmFzZTY0IGVuY29kaW5n"},
{"I love coding", "SSBsb3ZlIGNvZGluZw=="},
{"C++23 is awesome", "QysrMjMgaXMgYXdlc29tZQ=="},
{"This is a sample", "VGhpcyBpcyBhIHNhbXBsZQ=="},
{"Base64 is useful", "QmFzZTY0IGlzIHVzZWZ1bA=="},
{"Encode and decode", "RW5jb2RlIGFuZCBkZWNvZGU="},
{"Data encryption", "RGF0YSBlbmNyeXB0aW9u"},
{"Th3 Quickk Br0wn f0x", "VGgzIFF1aWNrayAgQnIwd24gZjB4"}}};
for (auto const& [input, expected] : test_cases) {
auto const actual = base64::to_base64(input);
ASSERT_EQ(actual, expected);
}
}
// NOLINTNEXTLINE
TEST(Base64RoundTripTests, TypeMixTests) {
const std::string strinput{"Hello, World!"};
const std::string stroutput{"SGVsbG8sIFdvcmxkIQ=="};
typedef std::vector<std::uint8_t> u8vec_type;
const u8vec_type uvecinput(strinput.begin(), strinput.end());
const u8vec_type uvecoutput(stroutput.begin(), stroutput.end());
typedef std::vector<std::int8_t> s8vec_type;
const s8vec_type svecinput(strinput.begin(), strinput.end());
const s8vec_type svecoutput(stroutput.begin(), stroutput.end());
// str -> str
{
auto tmp1 =
base64::encode_into<std::string>(strinput.begin(), strinput.end());
ASSERT_EQ(tmp1, stroutput);
auto tmp2 =
base64::decode_into<std::string>(stroutput.begin(), stroutput.end());
ASSERT_EQ(tmp2, strinput);
auto tmp3 = base64::encode_into<std::string>(strinput);
ASSERT_EQ(tmp3, stroutput);
auto tmp4 = base64::decode_into<std::string>(stroutput);
ASSERT_EQ(tmp4, strinput);
auto tmp5 = base64::to_base64(strinput);
ASSERT_EQ(tmp5, stroutput);
auto tmp6 = base64::from_base64(stroutput);
ASSERT_EQ(tmp6, strinput);
}
// str -> u8
{
auto tmp1 =
base64::encode_into<u8vec_type>(strinput.begin(), strinput.end());
ASSERT_EQ(tmp1, uvecoutput);
auto tmp2 =
base64::decode_into<u8vec_type>(stroutput.begin(), stroutput.end());
ASSERT_EQ(tmp2, uvecinput);
auto tmp3 = base64::encode_into<u8vec_type>(strinput);
ASSERT_EQ(tmp3, uvecoutput);
auto tmp4 = base64::decode_into<u8vec_type>(stroutput);
ASSERT_EQ(tmp4, uvecinput);
}
// str -> s8
{
auto tmp1 =
base64::encode_into<s8vec_type>(strinput.begin(), strinput.end());
ASSERT_EQ(tmp1, svecoutput);
auto tmp2 =
base64::decode_into<s8vec_type>(stroutput.begin(), stroutput.end());
ASSERT_EQ(tmp2, svecinput);
auto tmp3 = base64::encode_into<s8vec_type>(strinput);
ASSERT_EQ(tmp3, svecoutput);
auto tmp4 = base64::decode_into<s8vec_type>(stroutput);
ASSERT_EQ(tmp4, svecinput);
}
// u8 -> str
{
auto tmp1 =
base64::encode_into<std::string>(uvecinput.begin(), uvecinput.end());
ASSERT_EQ(tmp1, stroutput);
auto tmp2 =
base64::decode_into<std::string>(uvecoutput.begin(), uvecoutput.end());
ASSERT_EQ(tmp2, strinput);
}
// u8 -> u8
{
auto tmp1 =
base64::encode_into<u8vec_type>(uvecinput.begin(), uvecinput.end());
ASSERT_EQ(tmp1, uvecoutput);
auto tmp2 =
base64::decode_into<u8vec_type>(uvecoutput.begin(), uvecoutput.end());
ASSERT_EQ(tmp2, uvecinput);
}
// u8 -> s8
{
auto tmp1 =
base64::encode_into<s8vec_type>(uvecinput.begin(), uvecinput.end());
ASSERT_EQ(tmp1, svecoutput);
auto tmp2 =
base64::decode_into<s8vec_type>(uvecoutput.begin(), uvecoutput.end());
ASSERT_EQ(tmp2, svecinput);
}
// s8 -> str
{
auto tmp1 =
base64::encode_into<std::string>(svecinput.begin(), svecinput.end());
ASSERT_EQ(tmp1, stroutput);
auto tmp2 =
base64::decode_into<std::string>(svecoutput.begin(), svecoutput.end());
ASSERT_EQ(tmp2, strinput);
}
// s8 -> u8
{
auto tmp1 =
base64::encode_into<u8vec_type>(svecinput.begin(), svecinput.end());
ASSERT_EQ(tmp1, uvecoutput);
auto tmp2 =
base64::decode_into<u8vec_type>(svecoutput.begin(), svecoutput.end());
ASSERT_EQ(tmp2, uvecinput);
}
// s8 -> s8
{
auto tmp1 =
base64::encode_into<s8vec_type>(svecinput.begin(), svecinput.end());
ASSERT_EQ(tmp1, svecoutput);
auto tmp2 =
base64::decode_into<s8vec_type>(svecoutput.begin(), svecoutput.end());
ASSERT_EQ(tmp2, svecinput);
}
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
================================================
FILE: test/modp_b64_tests.cpp
================================================
// Test suite ported
// https://github.com/client9/stringencoders/blob/master/test/modp_b64_test.c
#include <gtest/gtest.h>
#include <array>
#include <cstdint>
#include <string>
#include <vector>
#include "../include/base64.hpp"
// NOLINTNEXTLINE
TEST(Base64Encode, Padding) {
// Test 1-6 bytes input and decode
{
/* 1 in, 4 out */
std::string const input{1};
auto const encoded{base64::to_base64(input)};
ASSERT_EQ(4, encoded.size());
auto const decoded{base64::from_base64(encoded)};
ASSERT_EQ(input, decoded);
}
{
/* 2 in, 4 out */
std::string const input{1, 1};
auto const encoded{base64::to_base64(input)};
ASSERT_EQ(4, encoded.size());
auto const decoded{base64::from_base64(encoded)};
ASSERT_EQ(input, decoded);
}
{
/* 3 in, 4 out */
std::string const input{1, 1, 1};
auto const encoded{base64::to_base64(input)};
ASSERT_EQ(4, encoded.size());
auto const decoded{base64::from_base64(encoded)};
ASSERT_EQ(input, decoded);
}
{
/* 4 in, 8 out */
std::string const input{1, 1, 1, 1};
auto const encoded{base64::to_base64(input)};
ASSERT_EQ(8, encoded.size());
auto const decoded{base64::from_base64(encoded)};
ASSERT_EQ(input, decoded);
}
{
/* 5 in, 8 out */
std::string const input{1, 1, 1, 1, 1};
auto const encoded{base64::to_base64(input)};
ASSERT_EQ(8, encoded.size());
auto const decoded{base64::from_base64(encoded)};
ASSERT_EQ(input, decoded);
}
{
/* 6 in, 8 out */
std::string const input{1, 1, 1, 1, 1, 6};
auto const encoded{base64::to_base64(input)};
ASSERT_EQ(8, encoded.size());
auto const decoded{base64::from_base64(encoded)};
ASSERT_EQ(input, decoded);
}
}
// NOLINTNEXTLINE
TEST(Base64Encode, EncodeDecode) {
// Test all 17M 3 bytes inputs to encoder, decode
// and make sure it's equal.
for (int i = 0; i < 256; ++i) {
for (int j = 0; j < 256; ++j) {
for (int k = 0; k < 256; ++k) {
std::string const input{static_cast<char>(i), static_cast<char>(j),
static_cast<char>(k)};
auto const encoded{base64::to_base64(input)};
ASSERT_EQ(4, encoded.size());
auto const decoded{base64::from_base64(encoded)};
ASSERT_EQ(input, decoded);
}
}
}
}
// NOLINTNEXTLINE
TEST(Base64Encode, DecodeErrors) {
{
// test bad input - all combinations
char goodchar = 'A';
char badchar = '~';
std::array<std::uint8_t, 4> decode;
for (int i = 1; i < 16; ++i) {
decode[0] = static_cast<char>(((i & 0x01) == 0) ? goodchar : badchar);
decode[1] = static_cast<char>(((i & 0x02) == 0) ? goodchar : badchar);
decode[2] = static_cast<char>(((i & 0x04) == 0) ? goodchar : badchar);
decode[3] = static_cast<char>(((i & 0x08) == 0) ? goodchar : badchar);
ASSERT_THROW(
base64::decode_into<std::string>(decode.begin(), decode.end()),
std::runtime_error);
}
}
{
// test just 1-4 padchars
for (int i = 1; i <= 4; ++i) {
std::vector<char> decode(i, '=');
ASSERT_THROW(
base64::decode_into<std::string>(decode.begin(), decode.end()),
std::runtime_error);
}
}
{
// Test good+3 pad chars (should be impossible)
std::string decode("A===");
ASSERT_THROW(base64::decode_into<std::string>(decode.begin(), decode.end()),
std::runtime_error);
}
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
================================================
FILE: test/roundtrip_test.cpp
================================================
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
#include "../include/base64.hpp"
int runtests() {
const std::vector<int> lengths{5, 10, 100, 1024, 10000, 1000003};
int outcome = EXIT_SUCCESS;
std::cout << "char is "
<< (std::is_signed<char>::value ? "signed" : "unsigned")
<< std::endl;
std::cout << "endianness is "
#if defined(__LITTLE_ENDIAN__)
<< "little endian"
#else
<< "big endian"
#endif
<< std::endl;
for (auto& length : lengths) {
std::string original;
for (int i = 0; i < length; i++) {
original += static_cast<char>(std::rand());
}
auto encoded = base64::to_base64(original);
auto s = base64::from_base64(encoded);
if (s == original) {
std::cout << "Test passed with length " << length << std::endl;
} else {
std::cout << "Test FAILED with length " << length << std::endl;
outcome = EXIT_FAILURE;
}
}
return outcome;
}
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
try {
return runtests();
} catch (const std::exception& e) {
// standard exceptions
std::cout << "Caught std::exception in main: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (...) {
// everything else
std::cout << "Caught unknown exception in main" << std::endl;
return EXIT_FAILURE;
}
}
gitextract_49o6eegi/
├── .clang-format
├── .github/
│ └── workflows/
│ ├── bigendiancmake.yml
│ ├── cmake.yml
│ └── cpplint.yml
├── .gitignore
├── CMakeLists.txt
├── CPPLINT.cfg
├── LICENSE
├── README.md
├── include/
│ └── base64.hpp
├── scripts/
│ ├── run-clang-format.sh
│ └── run-s390x-emulation.sh
└── test/
├── base64_tests.cpp
├── modp_b64_tests.cpp
└── roundtrip_test.cpp
SYMBOL INDEX (47 symbols across 4 files)
FILE: include/base64.hpp
type base64 (line 18) | namespace base64 {
type detail (line 20) | namespace detail {
function bit_cast (line 26) | std::enable_if_t<sizeof(To) == sizeof(From) &&
function OutputBuffer (line 505) | inline OutputBuffer encode_into(InputIterator begin, InputIterator end) {
function OutputBuffer (line 564) | inline OutputBuffer encode_into(std::string_view data) {
function to_base64 (line 568) | inline std::string to_base64(std::string_view data) {
function OutputBuffer (line 573) | inline OutputBuffer decode_into(std::string_view base64Text) {
function OutputBuffer (line 688) | inline OutputBuffer decode_into(InputIterator begin, InputIterator end) {
function from_base64 (line 698) | inline std::string from_base64(std::string_view data) {
FILE: test/base64_tests.cpp
function TEST (line 12) | TEST(Base64Encode, EncodesEmpty) {
function TEST (line 19) | TEST(Base64Encode, EncodesThreeBytesZeros) {
function TEST (line 27) | TEST(Base64Encode, EncodesThreeBytesRandom) {
function TEST (line 35) | TEST(Base64Encode, EncodesTwoBytes) {
function TEST (line 43) | TEST(Base64Encode, EncodesOneByte) {
function TEST (line 51) | TEST(Base64Encode, EncodesFourBytes) {
function TEST (line 59) | TEST(Base64Encode, EncodesFiveBytes) {
function TEST (line 67) | TEST(Base64Encode, EncodesSixBytes) {
function TEST (line 75) | TEST(Base64Encode, EncodesBrownFox) {
function TEST (line 89) | TEST(Base64Encode, EncodesBrownFastFoxNullInMiddle) {
function TEST (line 103) | TEST(Base64Decode, FailDecodeOneString) {
function TEST (line 109) | TEST(Base64Decode, FailDecodeOneStringPadded) {
function TEST (line 115) | TEST(Base64Decode, FailDecodeOneCharRemaining) {
function TEST (line 121) | TEST(Base64Decode, FailDecodeNonSize4Bigger) {
function TEST (line 131) | TEST(Base64Decode, FailDecodeNonBase64Short) {
function TEST (line 137) | TEST(Base64Decode, FailDecodeNonBase64Longer) {
function TEST (line 143) | TEST(Base64Decode, DecodesMissingTwoPads0) {
function TEST (line 151) | TEST(Base64Decode, DecodesMissingTwoPads1) {
function TEST (line 159) | TEST(Base64Decode, DecodesMissingOnePad0) {
function TEST (line 167) | TEST(Base64Decode, DecodesMissingOnePad1) {
function TEST (line 175) | TEST(Base64Decode, DecodesMissingIssueExample) {
function TEST (line 184) | TEST(Base64Decode, DecodesEmptyString) {
function TEST (line 192) | TEST(Base64Decode, DecodesZeroArray) {
function TEST (line 201) | TEST(Base64Decode, DecodesZeroArrayTwice) {
function TEST (line 210) | TEST(Base64Decode, DecodesZeroArrayOneByte) {
function TEST (line 219) | TEST(Base64Decode, DecodesZeroArrayTwoBytes) {
function TEST (line 228) | TEST(Base64Decode, DecodesQuickFox) {
function TEST (line 241) | TEST(Base64RoundTripTests, AllPossibleBytes) {
function TEST (line 255) | TEST(Base64RoundTripTests, ExhaustiveTests) {
function TEST (line 303) | TEST(Base64OverloadTests, EncodesString1) {
function TEST (line 325) | TEST(Base64RoundTripTests, TypeMixTests) {
function main (line 444) | int main(int argc, char** argv) {
FILE: test/modp_b64_tests.cpp
function TEST (line 13) | TEST(Base64Encode, Padding) {
function TEST (line 66) | TEST(Base64Encode, EncodeDecode) {
function TEST (line 84) | TEST(Base64Encode, DecodeErrors) {
function main (line 118) | int main(int argc, char** argv) {
FILE: test/roundtrip_test.cpp
function runtests (line 8) | int runtests() {
function main (line 43) | int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
Condensed preview — 15 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (72K chars).
[
{
"path": ".clang-format",
"chars": 180,
"preview": "BasedOnStyle: Google\nIndentWidth: 2\nUseTab: Never\nColumnLimit: 0\nNamespaceIndentation: None\nBreakBeforeBraces: Attach\nAl"
},
{
"path": ".github/workflows/bigendiancmake.yml",
"chars": 1052,
"preview": "name: CMake on s390x emulation (Big endian system)\n\non: [push, pull_request]\n\nenv:\n # Customize the CMake build type he"
},
{
"path": ".github/workflows/cmake.yml",
"chars": 1877,
"preview": "name: CMake\n\non: [push, pull_request]\n\nenv:\n # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc"
},
{
"path": ".github/workflows/cpplint.yml",
"chars": 412,
"preview": "# GitHub Action to run cpplint recursively on all pushes and pull requests\n# https://github.com/cpplint/GitHub-Action-fo"
},
{
"path": ".gitignore",
"chars": 45,
"preview": "main.cpp\nbuild\n*.user\n*.swp\nscripts/build.sh\n"
},
{
"path": "CMakeLists.txt",
"chars": 2949,
"preview": "cmake_minimum_required(VERSION 3.16)\nproject(base64)\n\noption(BASE64_ENABLE_TESTING \"Build test files.\" ON)\n\nset(CMAKE_CX"
},
{
"path": "CPPLINT.cfg",
"chars": 48,
"preview": "filter=-legal/copyright\nfilter=-readability/todo"
},
{
"path": "LICENSE",
"chars": 1070,
"preview": "MIT License\n\nCopyright (c) 2019 Tobias Locker\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
},
{
"path": "README.md",
"chars": 1583,
"preview": "# base64\n\nA simple, header-only C++17 library for Base64 encoding and decoding. Uses modern C++ features when available\n"
},
{
"path": "include/base64.hpp",
"chars": 39606,
"preview": "#ifndef BASE64_HPP_\n#define BASE64_HPP_\n\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <cstdint>\n#in"
},
{
"path": "scripts/run-clang-format.sh",
"chars": 103,
"preview": "#!/usr/bin/env sh\nclang-format -style=Google -i include/*.hpp\nclang-format -style=Google -i test/*.cpp\n"
},
{
"path": "scripts/run-s390x-emulation.sh",
"chars": 517,
"preview": "#!/usr/bin/env sh\n#\n#docker run --rm --privileged multiarch/qemu-user-static:register --reset\ndocker run -it multiarch/u"
},
{
"path": "test/base64_tests.cpp",
"chars": 14940,
"preview": "// Test suite ported from https://github.com/matheusgomes28/base64pp\n#include <gtest/gtest.h>\n\n#include <array>\n#include"
},
{
"path": "test/modp_b64_tests.cpp",
"chars": 3559,
"preview": "// Test suite ported\n// https://github.com/client9/stringencoders/blob/master/test/modp_b64_test.c\n#include <gtest/gtest"
},
{
"path": "test/roundtrip_test.cpp",
"chars": 1405,
"preview": "#include <iostream>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"../include/base64.hpp\"\n\nint ru"
}
]
About this extraction
This page contains the full source code of the tobiaslocker/base64 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 15 files (67.7 KB), approximately 27.7k tokens, and a symbol index with 47 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.