Merge branch 'development' into chru-atomic-constexpr

This commit is contained in:
John Wellbelove 2026-06-08 09:23:38 +01:00 committed by GitHub
commit 331b057d21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
622 changed files with 77186 additions and 4346 deletions

26
.bazelrc Normal file
View File

@ -0,0 +1,26 @@
# Bazel settings for ETL
build --enable_bzlmod
build --cxxopt=-std=c++17
# Cross-compilation: build flags + QEMU (mirrors .devcontainer/run-tests.sh)
# Each config sets CC + tool env vars so Bazel's auto-configured toolchain
# finds the full cross-tool suite, and --run_under for QEMU execution.
build:armhf --repo_env=CC=arm-linux-gnueabihf-gcc --repo_env=AR=arm-linux-gnueabihf-ar --repo_env=LD=arm-linux-gnueabihf-ld --repo_env=NM=arm-linux-gnueabihf-nm --repo_env=STRIP=arm-linux-gnueabihf-strip --repo_env=OBJDUMP=arm-linux-gnueabihf-objdump
build:armhf --cxxopt=-std=c++23 --copt=-DETL_NO_STL --copt=-O0
test:armhf --run_under=/usr/bin/qemu-arm-static
build:i386 --repo_env=CC=i686-linux-gnu-gcc --repo_env=AR=i686-linux-gnu-ar --repo_env=LD=i686-linux-gnu-ld --repo_env=NM=i686-linux-gnu-nm --repo_env=STRIP=i686-linux-gnu-strip --repo_env=OBJDUMP=i686-linux-gnu-objdump
build:i386 --cxxopt=-std=c++23 --copt=-DETL_NO_STL --copt=-O0
test:i386 --run_under=/usr/bin/qemu-i386-static
build:powerpc --repo_env=CC=powerpc-linux-gnu-gcc --repo_env=AR=powerpc-linux-gnu-ar --repo_env=LD=powerpc-linux-gnu-ld --repo_env=NM=powerpc-linux-gnu-nm --repo_env=STRIP=powerpc-linux-gnu-strip --repo_env=OBJDUMP=powerpc-linux-gnu-objdump
build:powerpc --cxxopt=-std=c++23 --copt=-DETL_NO_STL --copt=-O0
test:powerpc --run_under=/usr/bin/qemu-ppc
build:riscv64 --repo_env=CC=riscv64-linux-gnu-gcc --repo_env=AR=riscv64-linux-gnu-ar --repo_env=LD=riscv64-linux-gnu-ld --repo_env=NM=riscv64-linux-gnu-nm --repo_env=STRIP=riscv64-linux-gnu-strip --repo_env=OBJDUMP=riscv64-linux-gnu-objdump
build:riscv64 --cxxopt=-std=c++23 --copt=-DETL_NO_STL --copt=-O0
test:riscv64 --run_under=/usr/bin/qemu-riscv64-static
build:s390x --repo_env=CC=s390x-linux-gnu-gcc --repo_env=AR=s390x-linux-gnu-ar --repo_env=LD=s390x-linux-gnu-ld --repo_env=NM=s390x-linux-gnu-nm --repo_env=STRIP=s390x-linux-gnu-strip --repo_env=OBJDUMP=s390x-linux-gnu-objdump
build:s390x --cxxopt=-std=c++23 --copt=-DETL_NO_STL --copt=-O0
test:s390x --run_under=/usr/bin/qemu-s390x-static

1
.bazelversion Normal file
View File

@ -0,0 +1 @@
8.5.1

182
.clang-tidy Normal file
View File

@ -0,0 +1,182 @@
---
# TODO: Enable these checks in smaller steps
# cppcoreguidelines-*,
# portability-* if needed
# readability-*, -readability-magic-numbers,
# misc-*, -misc-no-recursion,
# modernize-*, -modernize-use-trailing-return-type,
# performance-*,
Checks: >-
cert-*, -cert-dcl37-c, -cert-dcl51-cpp,
clang-analyzer-*,
bugprone-*,
-bugprone-easily-swappable-parameters,
cppcoreguidelines-pro-type-vararg,
cppcoreguidelines-pro-type-reinterpret-cast,
llvm-*,-llvm-header-guard,-llvm-include-order,
google-readability-casting
ExtraArgs: ['-Wno-unknown-warning-option']
HeaderFileExtensions: ['h', 'hpp']
HeaderFilterRegex: '.*include/etl/.*'
ImplementationFileExtensions: ['cpp']
UseColor: true
# TODO: Enable these when readability check is enabled
# CheckOptions :
# - key: readability-identifier-naming.AbstractClassCase
# value: snake_case
# - key: readability-identifier-naming.AbstractClassPrefix
# value: I
# - key: readability-identifier-naming.AbstractClassSuffix
# value: ''
# - key: readability-identifier-naming.ClassCase
# value: snake_case
# - key: readability-identifier-naming.ClassPrefix
# value: ''
# - key: readability-identifier-naming.ClassSuffix
# value: ''
# - key: readability-identifier-naming.GlobalConstantCase
# value: UPPER_CASE
# - key: readability-identifier-naming.GlobalConstantPrefix
# value: ''
# - key: readability-identifier-naming.GlobalConstantSuffix
# value: ''
# - key: readability-identifier-naming.ConstantCase
# value: snake_case
# - key: readability-identifier-naming.ConstantPrefix
# value: ''
# - key: readability-identifier-naming.ConstantSuffix
# value: ''
# - key: readability-identifier-naming.ConstantMemberCase
# value: snake_case
# - key: readability-identifier-naming.ConstantMemberPrefix
# value: k
# - key: readability-identifier-naming.ConstantMemberSuffix
# value: ''
# - key: readability-identifier-naming.StaticConstantCase
# value: snake_case
# - key: readability-identifier-naming.StaticConstantPrefix
# value: k
# - key: readability-identifier-naming.StaticConstantSuffix
# value: ''
# - key: readability-identifier-naming.EnumCase
# value: snake_case
# - key: readability-identifier-naming.EnumPrefix
# value: ''
# - key: readability-identifier-naming.EnumSuffix
# value: ''
# - key: readability-identifier-naming.EnumConstantCase
# value: snake_case
# - key: readability-identifier-naming.EnumConstantPrefix
# value: ''
# - key: readability-identifier-naming.EnumConstantSuffix
# value: ''
# - key: readability-identifier-naming.GlobalVariableCase
# value: snake_case
# - key: readability-identifier-naming.GlobalVariablePrefix
# value: g
# - key: readability-identifier-naming.GlobalVariableSuffix
# value: ''
# - key: readability-identifier-naming.LocalVariableCase
# value: snake_case
# - key: readability-identifier-naming.LocalVariablePrefix
# value: ''
# - key: readability-identifier-naming.LocalVariableSuffix
# value: ''
# - key: readability-identifier-naming.StructCase
# value: aNy_CasE
# - key: readability-identifier-naming.StructPrefix
# value: ''
# - key: readability-identifier-naming.StructSuffix
# value: ''
# - key: readability-identifier-naming.FunctionCase
# value: snake_case
# - key: readability-identifier-naming.FunctionPrefix
# value: ''
# - key: readability-identifier-naming.FunctionSuffix
# value: ''
# - key: readability-identifier-naming.MethodCase
# value: snake_case
# - key: readability-identifier-naming.MethodPrefix
# value: ''
# - key: readability-identifier-naming.MethodSuffix
# value: ''
# - key: readability-identifier-naming.ParameterCase
# value: snake_case
# - key: readability-identifier-naming.PrivateMethodCase
# value: snake_case
# - key: readability-identifier-naming.PrivateMethodPrefix
# value: ''
# - key: readability-identifier-naming.PrivateMethodSuffix
# value: ''
# - key: readability-identifier-naming.PublicMethodCase
# value: snake_case
# - key: readability-identifier-naming.PublicMethodPrefix
# value: ''
# - key: readability-identifier-naming.PublicMethodSuffix
# value: ''
# - key: readability-identifier-naming.MemberCase
# value: snake_case
# - key: readability-identifier-naming.MemberPrefix
# value: _
# - key: readability-identifier-naming.MemberSuffix
# value: ''
# - key: readability-identifier-naming.PrivateMemberCase
# value: snake_case
# - key: readability-identifier-naming.PrivateMemberPrefix
# value: _
# - key: readability-identifier-naming.PrivateMemberSuffix
# value: ''
# - key: readability-identifier-naming.PublicMemberCase
# value: snake_case
# - key: readability-identifier-naming.PublicMemberPrefix
# value: ''
# - key: readability-identifier-naming.PublicMemberSuffix
# value: ''
# - key: readability-identifier-naming.NamespaceCase
# value: lower_case
# - key: readability-identifier-naming.NamespacePrefix
# value: ''
# - key: readability-identifier-naming.NamespaceSuffix
# value: ''
# - key: readability-identifier-naming.InlineNamespaceCase
# value: lower_case
# - key: readability-identifier-naming.InlineNamespacePrefix
# value: ''
# - key: readability-identifier-naming.InlineNamespaceSuffix
# value: ''
# - key: readability-identifier-length.IgnoredParameterNames
# value: ^(n|id|a|b|x|y)$
# - key: readability-identifier-length.IgnoredLoopCounterNames
# value: ^[ijkxy_]$
# - key: readability-identifier-naming.GlobalFunctionCase
# value: snake_case
# - key: readability-identifier-naming.GlobalFunctionPrefix
# value: ''
# - key: readability-identifier-naming.GlobalFunctionSuffix
# value: ''
# - key: readability-identifier-naming.TemplateParameterCase
# value: CamelCase
# - key: readability-identifier-naming.TemplateParameterPrefix
# value: ''
# - key: readability-identifier-naming.TemplateParameterSuffix
# value: ''
# - key: readability-identifier-naming.TemplateTemplateParameterCase
# value: CamelCase
# - key: readability-identifier-naming.TemplateTemplateParameterPrefix
# value: 'TPL'
# - key: readability-identifier-naming.TemplateTemplateParameterSuffix
# value: ''
# - key: readability-identifier-naming.TypeTemplateParameterCase
# value: CamelCase
# - key: readability-identifier-naming.TypeTemplateParameterPrefix
# value: 'T'
# - key: readability-identifier-naming.TypeTemplateParameterSuffix
# value: ''
# - key: readability-identifier-naming.ValueTemplateParameterCase
# value: UPPER_CASE
# - key: readability-identifier-naming.ValueTemplateParameterPrefix
# value: ''
# - key: readability-identifier-naming.ValueTemplateParameterSuffix
# value: ''
...

View File

@ -36,15 +36,32 @@ RUN set -eux \
&& apt-get -y install --no-install-recommends \
python3-full \
python3-pip \
python3-cogapp \
git \
wget \
cmake \
&& rm -rf /var/lib/apt/lists/* \
&& if pip help install | grep -q '\-\-break-system-packages'; then \
pip install --no-cache-dir --break-system-packages cogapp; \
else \
pip install --no-cache-dir cogapp; \
fi
clang-format \
clang-format-18 \
lcov \
&& rm -rf /var/lib/apt/lists/*
RUN set -eux; \
VERSION="2.4.1"; \
case "$(uname -m)" in \
x86_64) ARCH="amd64"; SHA256="bdaa2c0fbee03e5c2f99e605d9419386ce5d558440baac2017398faada839e04" ;; \
aarch64) ARCH="arm64"; SHA256="0a09e1f04a0f8a86fd4e709552613f5d82adf6bc72f0a4b5e217670894e79fbf" ;; \
*) echo "Unsupported architecture: $(uname -m)"; exit 1 ;; \
esac; \
wget -O treefmt.tar.gz "https://github.com/numtide/treefmt/releases/download/v${VERSION}/treefmt_${VERSION}_linux_${ARCH}.tar.gz" \
&& echo "${SHA256} treefmt.tar.gz" | sha256sum -c \
&& tar xzf treefmt.tar.gz treefmt \
&& install -m 755 treefmt /usr/bin/treefmt \
&& rm treefmt.tar.gz treefmt
# Install Bazelisk as 'bazel'
RUN ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') && \
wget -qO /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-${ARCH} && \
chmod +x /usr/local/bin/bazel
RUN set -eux \
&& echo "Pip version: " \

View File

@ -0,0 +1,61 @@
# armhf Test Environment for ETL
# Uses QEMU user-mode emulation to run armhf binaries on x64 host
FROM debian:trixie
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and armhf cross-compilation tools
RUN dpkg --add-architecture armhf && \
apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
binfmt-support \
gcc-arm-linux-gnueabihf \
g++-arm-linux-gnueabihf \
cmake \
make \
ninja-build \
git \
wget \
ca-certificates \
file \
libc6:armhf \
libstdc++6:armhf \
libatomic1:armhf \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
# Install Bazelisk as 'bazel'
RUN ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') && \
wget -qO /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-${ARCH} && \
chmod +x /usr/local/bin/bazel
# Verify QEMU and cross-compilation setup
RUN echo "=== Host Architecture ===" && \
uname -m && \
echo "" && \
echo "=== armhf Cross Compiler ===" && \
arm-linux-gnueabihf-gcc --version && \
echo "" && \
echo "=== QEMU arm ===" && \
qemu-arm-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -0,0 +1,29 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "armhf (Debian)",
"build": {
"dockerfile": "./Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
"settings": {
"cmake.sourceDirectory": "${workspaceFolder}/test",
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/armhf/toolchain-armhf.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=OFF",
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-armhf",
"cmake.generator": "Ninja"
}
}
},
"remoteUser": "root"
}

View File

@ -0,0 +1,21 @@
# CMake toolchain file for armhf cross-compilation
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# Specify the cross compiler
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_AR arm-linux-gnueabihf-ar)
set(CMAKE_RANLIB arm-linux-gnueabihf-ranlib)
set(CMAKE_STRIP arm-linux-gnueabihf-strip)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Set QEMU for running tests
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-arm-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries")

View File

@ -1,291 +0,0 @@
#!/usr/bin/env bash
# For more detailed debugging, uncomment the next line
# set -x
# Explicitly set CMAKE_VERSION from first argument, default to "none"
CMAKE_VERSION=${1:-"none"}
# --- Configuration ---
DOWNLOAD_ATTEMPTS=3
DOWNLOAD_RETRY_DELAY=5 # seconds
# --- Global Variables ---
TMP_DIR="" # Initialize TMP_DIR, will be set by mktemp
# Filenames used within TMP_DIR
CMAKE_INSTALLER_SCRIPT_LOCAL_NAME="cmake-installer.sh"
CMAKE_CHECKSUM_FILE_LOCAL_NAME="cmake-checksums.txt"
# This will be the actual name of the CMake binary, derived from version and arch
# It's important for matching against the checksum file.
DERIVED_CMAKE_BINARY_FILENAME=""
# --- Cleanup Function ---
# This trap will execute on EXIT, ERR, SIGINT, SIGTERM
# It's crucial for debugging to see the state of TMP_DIR if things go wrong.
cleanup() {
# $? is the exit code of the last command before the trap was triggered
# or the argument to exit if the script called exit explicitly.
LAST_EXIT_CODE=$?
echo # Newline for readability
# Only proceed with detailed cleanup if TMP_DIR was actually created
if [[ -n "${TMP_DIR}" && -d "${TMP_DIR}" ]]; then
echo "--- Cleanup: Temporary Directory Inspector (${TMP_DIR}) ---"
echo "Listing contents of TMP_DIR:"
ls -la "${TMP_DIR}"
# Check and display checksum file content
if [[ -f "${TMP_DIR}/${CMAKE_CHECKSUM_FILE_LOCAL_NAME}" ]]; then
echo "--- Content of downloaded checksum file (${CMAKE_CHECKSUM_FILE_LOCAL_NAME}) ---"
cat "${TMP_DIR}/${CMAKE_CHECKSUM_FILE_LOCAL_NAME}"
echo "--- End of checksum file ---"
else
echo "Checksum file (${CMAKE_CHECKSUM_FILE_LOCAL_NAME}) not found in TMP_DIR."
fi
# Check and display head of (potentially) installer script
# Useful to see if it's an HTML error page
if [[ -f "${TMP_DIR}/${CMAKE_INSTALLER_SCRIPT_LOCAL_NAME}" ]]; then
echo "--- First 10 lines of downloaded installer script (${CMAKE_INSTALLER_SCRIPT_LOCAL_NAME}) ---"
head -n 10 "${TMP_DIR}/${CMAKE_INSTALLER_SCRIPT_LOCAL_NAME}"
echo "--- End of installer script head ---"
elif [[ -f "${TMP_DIR}/${DERIVED_CMAKE_BINARY_FILENAME}" ]]; then
# If it was renamed
echo "--- First 10 lines of downloaded installer script (${DERIVED_CMAKE_BINARY_FILENAME}) ---"
head -n 10 "${TMP_DIR}/${DERIVED_CMAKE_BINARY_FILENAME}"
echo "--- End of installer script head ---"
else
echo "Installer script not found in TMP_DIR (checked for ${CMAKE_INSTALLER_SCRIPT_LOCAL_NAME} and ${DERIVED_CMAKE_BINARY_FILENAME})."
fi
echo "Attempting to remove temporary directory: ${TMP_DIR}"
rm -Rf "${TMP_DIR}"
echo "Temporary directory removed."
echo "--- End of Cleanup ---"
else
echo "--- Cleanup: TMP_DIR was not set or not a directory, no temp files to inspect or clean. ---"
fi
# Ensure the script exits with the LAST_EXIT_CODE observed by the trap
# unless it was 0 and the script is exiting due to an explicit non-zero exit.
# The 'exit' command within the trap will override the script's natural exit code.
# So, if the script was going to exit 0, but cleanup had an issue, this could change it.
# However, for debugging an exit code 8, we want to preserve the code that *caused* the trap.
echo "Script finished with exit code: ${LAST_EXIT_CODE}."
exit "${LAST_EXIT_CODE}"
}
trap cleanup EXIT ERR SIGINT SIGTERM
# Immediately turn on `set -e` after trap setup
set -e
# --- Helper Functions ---
# Function to download a file with retries and basic validation
download_file() {
local url="$1"
local output_filename="$2"
local attempts_left=$DOWNLOAD_ATTEMPTS
local wget_exit_code=0
while [ $attempts_left -gt 0 ]; do
echo "Downloading: ${url}"
echo "Saving to: ${TMP_DIR}/${output_filename}"
echo "Attempt $((DOWNLOAD_ATTEMPTS - attempts_left + 1)) of ${DOWNLOAD_ATTEMPTS}..."
# Use wget with:
# -O: specify output file
# --timeout: connection/read timeout
# --tries: number of retries (wget's own retry, distinct from this loop)
# --quiet: suppress normal output, but errors still go to stderr
# --show-progress: if not quiet, shows a progress bar (optional)
# Using -q for less verbose logs, but on failure, we need to know.
wget -O "${TMP_DIR}/${output_filename}" --timeout=30 --tries=1 "${url}"
wget_exit_code=$?
if [ ${wget_exit_code} -eq 0 ]; then
echo "Download command successful for ${output_filename}."
if [ -s "${TMP_DIR}/${output_filename}" ]; then # -s: file exists and has a size greater than 0
# Basic check for common HTML error page indicators
# This is a heuristic and might not catch all error pages.
if head -n 5 "${TMP_DIR}/${output_filename}" | grep -Eiq '<html|<head|<!doctype html|404 Not Found|Error'; then
echo "WARNING: Downloaded file '${output_filename}' might be an HTML error page."
echo "First 5 lines of ${output_filename}:"
head -n 5 "${TMP_DIR}/${output_filename}"
# Consider this a failure for critical files
return 1 # Treat as failure
fi
echo "File ${output_filename} downloaded and is not empty."
return 0 # Success
else
echo "ERROR: Downloaded file ${output_filename} is empty."
# No need to rm here, loop will retry or fail
fi
else
echo "ERROR: wget failed to download ${url} with exit code ${wget_exit_code}."
fi
attempts_left=$((attempts_left - 1))
if [ $attempts_left -gt 0 ]; then
echo "Retrying in ${DOWNLOAD_RETRY_DELAY} seconds..."
sleep $DOWNLOAD_RETRY_DELAY
else
echo "ERROR: Failed to download ${url} after ${DOWNLOAD_ATTEMPTS} attempts."
return 1 # Explicit failure
fi
done
return 1 # Should be unreachable if loop logic is correct, but as a fallback
}
# --- Main Script Logic ---
if [ "${CMAKE_VERSION}" = "none" ]; then
echo "No CMake version specified by argument, skipping CMake reinstallation."
exit 0
fi
echo "CMake version to install: ${CMAKE_VERSION}"
# 1. Ensure wget is available
echo "Checking for wget..."
if ! command -v wget > /dev/null; then
echo "wget not found. Attempting to install wget via apt-get..."
if command -v apt-get > /dev/null; then
apt-get update -y
apt-get install -y --no-install-recommends wget
echo "wget installed."
else
echo "ERROR: apt-get not found. Cannot install wget. Please install wget manually."
exit 1
fi
else
echo "wget is available."
fi
# 2. (Optional) Remove existing CMake installed via apt
echo "Attempting to remove any existing CMake installed via apt..."
if command -v apt-get > /dev/null; then
if dpkg -s cmake &> /dev/null; then # Check if cmake package is actually installed
apt-get -y purge --auto-remove cmake
echo "cmake package purged."
else
echo "cmake package not found via dpkg, skipping purge."
fi
else
echo "apt-get not found, skipping removal of CMake via apt."
fi
# 3. Create installation and temporary directories
echo "Creating CMake installation directory /opt/cmake..."
mkdir -p /opt/cmake
TMP_DIR=$(mktemp -d -t cmake-install-XXXXXXXXXX)
echo "Temporary directory created: ${TMP_DIR}"
# Crucial: subsequent operations needing temp files should happen in or relative to TMP_DIR
# We will cd into TMP_DIR later, or use full paths like ${TMP_DIR}/filename
# 4. Determine system architecture
echo "Determining system architecture..."
architecture=$(dpkg --print-architecture)
case "${architecture}" in
arm64) ARCH="aarch64" ;;
amd64) ARCH="x86_64" ;;
*)
echo "ERROR: Unsupported architecture '${architecture}' reported by dpkg."
exit 1
;;
esac
echo "Detected architecture: ${architecture} (mapped to CMake arch: ${ARCH})"
# 5. Define CMake download URLs and the filename expected by checksum
DERIVED_CMAKE_BINARY_FILENAME="cmake-${CMAKE_VERSION}-linux-${ARCH}.sh"
CMAKE_BINARY_URL="https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${DERIVED_CMAKE_BINARY_FILENAME}"
CMAKE_CHECKSUM_FILE_URL="https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-SHA-256.txt"
# 6. Download CMake binary and checksum file
echo "--- Downloading Files ---"
if ! download_file "${CMAKE_BINARY_URL}" "${CMAKE_INSTALLER_SCRIPT_LOCAL_NAME}"; then
echo "ERROR: Failed to download CMake binary installer. See messages above."
exit 1
fi
if ! download_file "${CMAKE_CHECKSUM_FILE_URL}" "${CMAKE_CHECKSUM_FILE_LOCAL_NAME}"; then
echo "ERROR: Failed to download CMake checksum file. See messages above."
exit 1
fi
echo "Downloads complete."
echo "--- End of Downloading Files ---"
echo # Newline for readability
# Before checksum, rename the downloaded installer to its derived name,
# as the checksum file refers to this specific name.
echo "Renaming downloaded installer from '${CMAKE_INSTALLER_SCRIPT_LOCAL_NAME}' to '${DERIVED_CMAKE_BINARY_FILENAME}' for checksum verification."
mv "${TMP_DIR}/${CMAKE_INSTALLER_SCRIPT_LOCAL_NAME}" "${TMP_DIR}/${DERIVED_CMAKE_BINARY_FILENAME}"
if [ ! -f "${TMP_DIR}/${DERIVED_CMAKE_BINARY_FILENAME}" ]; then
echo "ERROR: Failed to rename installer script for checksum. File '${TMP_DIR}/${DERIVED_CMAKE_BINARY_FILENAME}' does not exist after move."
exit 1
fi
# 7. Verify checksum
echo "--- Verifying Checksum ---"
echo "Checksum file is: ${TMP_DIR}/${CMAKE_CHECKSUM_FILE_LOCAL_NAME}"
echo "Binary file to check is: ${TMP_DIR}/${DERIVED_CMAKE_BINARY_FILENAME}"
# Ensure the checksum file actually contains an entry for our binary
# This is important because the SHA-256.txt file contains checksums for *all* release assets
echo "Checking if checksum file contains entry for '${DERIVED_CMAKE_BINARY_FILENAME}'..."
if ! grep -q "${DERIVED_CMAKE_BINARY_FILENAME}" "${TMP_DIR}/${CMAKE_CHECKSUM_FILE_LOCAL_NAME}"; then
echo "ERROR: The downloaded checksum file '${CMAKE_CHECKSUM_FILE_LOCAL_NAME}' does NOT contain an entry for '${DERIVED_CMAKE_BINARY_FILENAME}'."
echo "This strongly suggests that the CMAKE_VERSION ('${CMAKE_VERSION}') or ARCH ('${ARCH}') is incorrect, or the specified version does not provide a .sh installer for this architecture."
echo "Please verify the version and available files at https://github.com/Kitware/CMake/releases/tag/v${CMAKE_VERSION}"
exit 1
fi
echo "Checksum file contains an entry for '${DERIVED_CMAKE_BINARY_FILENAME}'."
# Perform the checksum. We need to be in the directory where the files are.
echo "Changing directory to ${TMP_DIR} for checksum verification."
cd "${TMP_DIR}" # <<<<<<< IMPORTANT: sha256sum -c needs to find files
echo "Verifying checksum of '${DERIVED_CMAKE_BINARY_FILENAME}' using '${CMAKE_CHECKSUM_FILE_LOCAL_NAME}'..."
# The --ignore-missing flag is good, as the .txt file has many checksums.
# The --strict flag would cause it to error if there are improperly formatted lines.
# We rely on the grep check above to ensure our specific file is mentioned.
if sha256sum -c --ignore-missing "${CMAKE_CHECKSUM_FILE_LOCAL_NAME}"; then
echo "Checksum verification successful for '${DERIVED_CMAKE_BINARY_FILENAME}'."
else
SHA_EXIT_CODE=$?
echo "ERROR: Checksum verification FAILED for '${DERIVED_CMAKE_BINARY_FILENAME}' with exit code ${SHA_EXIT_CODE}."
# Cleanup trap will show file contents.
exit 1 # Critical failure
fi
echo "--- End of Verifying Checksum ---"
echo # Newline for readability
# 8. Install CMake
echo "--- Installing CMake ---"
echo "Making the CMake installer script '${DERIVED_CMAKE_BINARY_FILENAME}' executable..."
chmod +x "${DERIVED_CMAKE_BINARY_FILENAME}" # Still in TMP_DIR
echo "Executing CMake installer script: ./${DERIVED_CMAKE_BINARY_FILENAME} --prefix=/opt/cmake --skip-license"
# Execute the script. If this script exits with 8, this is our culprit.
if ./"${DERIVED_CMAKE_BINARY_FILENAME}" --prefix=/opt/cmake --skip-license; then
echo "CMake installer script executed successfully."
else
INSTALLER_EXIT_CODE=$?
echo "ERROR: CMake installer script FAILED with exit code ${INSTALLER_EXIT_CODE}."
# This is the most likely place for an exit code 8 if downloads and checksums were okay.
# The trap will handle cleanup. The script will exit with INSTALLER_EXIT_CODE due to the trap.
exit ${INSTALLER_EXIT_CODE} # Explicitly exit with the installer's code
fi
echo "--- End of Installing CMake ---"
echo # Newline for readability
# 9. Create symlinks
echo "Creating symbolic links for cmake and ctest in /usr/local/bin/..."
ln -sf /opt/cmake/bin/cmake /usr/local/bin/cmake
ln -sf /opt/cmake/bin/ctest /usr/local/bin/ctest
echo "Symbolic links created."
echo # Newline for readability
echo "SUCCESS: CMake ${CMAKE_VERSION} installation and setup complete."
# The script will exit with 0 here. The trap will run, see $? is 0, and then exit 0.
exit 0

View File

@ -0,0 +1,61 @@
# i386 Test Environment for ETL
# Uses QEMU user-mode emulation to run i386 binaries on x64 host
FROM debian:trixie
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and i386 cross-compilation tools
RUN dpkg --add-architecture i386 && \
apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
binfmt-support \
gcc-i686-linux-gnu \
g++-i686-linux-gnu \
cmake \
make \
ninja-build \
git \
wget \
ca-certificates \
file \
libc6:i386 \
libstdc++6:i386 \
libatomic1:i386 \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
# Install Bazelisk as 'bazel'
RUN ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') && \
wget -qO /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-${ARCH} && \
chmod +x /usr/local/bin/bazel
# Verify QEMU and cross-compilation setup
RUN echo "=== Host Architecture ===" && \
uname -m && \
echo "" && \
echo "=== i386 Cross Compiler ===" && \
i686-linux-gnu-gcc --version && \
echo "" && \
echo "=== QEMU i386 ===" && \
qemu-i386-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -0,0 +1,29 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "i386 (Debian)",
"build": {
"dockerfile": "./Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
"settings": {
"cmake.sourceDirectory": "${workspaceFolder}/test",
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/i386/toolchain-i386.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=OFF",
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-i386",
"cmake.generator": "Ninja"
}
}
},
"remoteUser": "root"
}

View File

@ -0,0 +1,21 @@
# CMake toolchain file for i386 cross-compilation
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR i386)
# Specify the cross compiler
set(CMAKE_C_COMPILER i686-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER i686-linux-gnu-g++)
set(CMAKE_AR i686-linux-gnu-ar)
set(CMAKE_RANLIB i686-linux-gnu-ranlib)
set(CMAKE_STRIP i686-linux-gnu-strip)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Set QEMU for running tests
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-i386-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries")

View File

@ -0,0 +1,85 @@
# powerpc Test Environment for ETL
# Uses QEMU user-mode emulation to run powerpc binaries on x64 host
FROM debian:sid-20260406
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and powerpc cross-compilation tools
RUN dpkg --add-architecture powerpc && \
apt-get update && apt-get install -y --no-install-recommends \
binfmt-support \
gpg \
ca-certificates \
cmake \
make \
ninja-build \
git \
wget \
file \
debian-ports-archive-keyring \
&& rm -rf /var/lib/apt/lists/*
RUN cat <<EOF > /etc/apt/sources.list.d/debian.sources
Types: deb
URIs: http://snapshot.debian.org/archive/debian/20260406T000000Z
Suites: sid
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.pgp
EOF
RUN cat <<EOF > /etc/apt/sources.list.d/powerpc.sources
Types: deb
URIs: http://snapshot.debian.org/archive/debian-ports/20260406T000000Z
Suites: sid
Components: main
Architectures: powerpc
Signed-By: /usr/share/keyrings/debian-ports-archive-keyring.gpg
EOF
RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf.d/99no-check-valid
RUN apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
gcc-powerpc-linux-gnu \
g++-powerpc-linux-gnu \
libc6:powerpc \
libstdc++6:powerpc \
libatomic1:powerpc \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
# Install Bazelisk as 'bazel'
RUN ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') && \
wget -qO /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-${ARCH} && \
chmod +x /usr/local/bin/bazel
# Verify QEMU and cross-compilation setup
RUN echo "=== Host Architecture ===" && \
uname -m && \
echo "" && \
echo "=== powerpc Cross Compiler ===" && \
powerpc-linux-gnu-gcc --version && \
echo "" && \
echo "=== QEMU powerpc ===" && \
qemu-ppc-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -0,0 +1,29 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "powerpc (Debian)",
"build": {
"dockerfile": "./Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
"settings": {
"cmake.sourceDirectory": "${workspaceFolder}/test",
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/powerpc/toolchain-powerpc.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=ON",
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-powerpc",
"cmake.generator": "Ninja"
}
}
},
"remoteUser": "root"
}

View File

@ -0,0 +1,21 @@
# CMake toolchain file for powerpc cross-compilation
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR powerpc)
# Specify the cross compiler
set(CMAKE_C_COMPILER powerpc-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER powerpc-linux-gnu-g++)
set(CMAKE_AR powerpc-linux-gnu-ar)
set(CMAKE_RANLIB powerpc-linux-gnu-ranlib)
set(CMAKE_STRIP powerpc-linux-gnu-strip)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Set QEMU for running tests
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-ppc CACHE FILEPATH "Path to the emulator for cross-compiled binaries")

View File

@ -0,0 +1,61 @@
# riscv64 Test Environment for ETL
# Uses QEMU user-mode emulation to run riscv64 binaries on x64 host
FROM debian:trixie
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and riscv64 cross-compilation tools
RUN dpkg --add-architecture riscv64 && \
apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
binfmt-support \
gcc-riscv64-linux-gnu \
g++-riscv64-linux-gnu \
cmake \
make \
ninja-build \
git \
wget \
ca-certificates \
file \
libc6:riscv64 \
libstdc++6:riscv64 \
libatomic1:riscv64 \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
# Install Bazelisk as 'bazel'
RUN ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') && \
wget -qO /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-${ARCH} && \
chmod +x /usr/local/bin/bazel
# Verify QEMU and cross-compilation setup
RUN echo "=== Host Architecture ===" && \
uname -m && \
echo "" && \
echo "=== riscv64 Cross Compiler ===" && \
riscv64-linux-gnu-gcc --version && \
echo "" && \
echo "=== QEMU riscv64 ===" && \
qemu-riscv64-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -0,0 +1,29 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "riscv64 (Debian)",
"build": {
"dockerfile": "./Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
"settings": {
"cmake.sourceDirectory": "${workspaceFolder}/test",
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/riscv64/toolchain-riscv64.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=OFF",
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-riscv64",
"cmake.generator": "Ninja"
}
}
},
"remoteUser": "root"
}

View File

@ -0,0 +1,20 @@
# CMake toolchain file for riscv64 cross-compilation
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR riscv64)
# Specify the cross compiler
set(CMAKE_C_COMPILER riscv64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER riscv64-linux-gnu-g++)
set(CMAKE_AR riscv64-linux-gnu-ar)
set(CMAKE_RANLIB riscv64-linux-gnu-ranlib)
set(CMAKE_STRIP riscv64-linux-gnu-strip)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Set QEMU for running tests
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-riscv64-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries")

56
.devcontainer/run-tests.sh Executable file
View File

@ -0,0 +1,56 @@
#!/bin/bash
#
# Run tests inside the separately created docker container for different hardware architecture
#
# Strategy:
# * Create docker image
# * Enter image
# * Cross build tests
# * Run tests via QEMU
#
set -e
usage()
{
echo "Usage: run-tests.sh <architecture>"
echo "Architecture: armhf|i386|powerpc|riscv64|s390x"
echo "(run from project root)"
}
ARCHLIST="armhf i386 powerpc riscv64 s390x"
if [[ " $ARCHLIST " =~ " $1 " ]] ; then
ARCH=$1
else
echo "Unsupported architecture: $1"
usage
exit 1
fi
if [ "$2" = "" ] ; then
echo "Creating docker image..."
docker build -t $ARCH .devcontainer/$ARCH
echo "Entering container..."
docker run -it --rm -v "$PWD":/workspaces/etl -w /workspaces/etl $ARCH /bin/bash .devcontainer/run-tests.sh $ARCH inside_container
elif [ "$2" = "inside_container" ] ; then
echo "Cross building tests..."
mkdir -p build-$ARCH
cd build-$ARCH
cmake -DCMAKE_TOOLCHAIN_FILE=../.devcontainer/$ARCH/toolchain-$ARCH.cmake \
-DBUILD_TESTS=ON -DNO_STL=ON -DETL_CXX_STANDARD=23 \
-DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=-O0 -DETL_ENABLE_SANITIZER=OFF -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF \
../test
export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
cmake --build .
echo "Running tests via CTest (using QEMU emulator from toolchain)..."
ctest -V --output-on-failure
echo "Tests successful."
else
echo "Invalid second argument: $2"
usage
exit 1
fi

View File

@ -7,7 +7,7 @@ ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and s390x cross-compilation tools
RUN dpkg --add-architecture s390x && \
apt-get update && apt-get install -y --no-install-recommends\
apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
binfmt-support \
@ -18,14 +18,29 @@ RUN dpkg --add-architecture s390x && \
ninja-build \
git \
wget \
ca-certificates \
file \
libc6:s390x \
libstdc++6:s390x \
libatomic1:s390x \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
# Install Bazelisk as 'bazel'
RUN ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') && \
wget -qO /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-${ARCH} && \
chmod +x /usr/local/bin/bazel
# Verify QEMU and cross-compilation setup
RUN echo "=== Host Architecture ===" && \
uname -m && \
@ -36,5 +51,11 @@ RUN echo "=== Host Architecture ===" && \
echo "=== QEMU s390x ===" && \
qemu-s390x-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -18,7 +18,7 @@
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/s390x/toolchain-s390x.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=OFF",
"-DETL_CXX_STANDARD=17"
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-s390x",
"cmake.generator": "Ninja"

View File

@ -0,0 +1,20 @@
FROM ubuntu:26.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
git \
ninja-build \
python3 \
python3-pip \
clang \
docker.io \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -m -s /bin/bash vscode
WORKDIR /etl
CMD ["/bin/bash"]

View File

@ -0,0 +1,22 @@
name: bazel-gcc-c++23-no-stl
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-bazel-gcc-cpp23-no-stl:
name: Bazel GCC C++23 Linux - No STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build
run: bazel build //test:etl_tests --cxxopt=-std=c++23 --copt=-DETL_NO_STL
- name: Run tests
run: bazel test //test:etl_tests --cxxopt=-std=c++23 --copt=-DETL_NO_STL --test_output=all

View File

@ -25,7 +25,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -47,7 +47,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

View File

@ -25,7 +25,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -47,7 +47,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

View File

@ -25,7 +25,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -47,7 +47,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

View File

@ -32,7 +32,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
clang-17 --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -61,7 +61,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
clang-17 --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -90,7 +90,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
clang-17 --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -112,7 +112,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -134,7 +134,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -156,7 +156,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -178,7 +178,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

View File

@ -13,26 +13,19 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
os: [ubuntu-24.04]
steps:
- uses: actions/checkout@v4
# Temporary fix. See https://github.com/actions/runner-images/issues/8659
- name: Install newer Clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x ./llvm.sh
sudo ./llvm.sh 17
- name: Build
run: |
export CC=clang-17
export CXX=clang++-17
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
clang-17 --version
make -j $(getconf _NPROCESSORS_ONLN)
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
clang --version
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -42,26 +35,19 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
os: [ubuntu-24.04]
steps:
- uses: actions/checkout@v4
# Temporary fix. See https://github.com/actions/runner-images/issues/8659
- name: Install newer Clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x ./llvm.sh
sudo ./llvm.sh 17
- name: Build
run: |
export CC=clang-17
export CXX=clang++-17
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
clang-17 --version
make -j $(getconf _NPROCESSORS_ONLN)
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
clang --version
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -71,26 +57,19 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
os: [ubuntu-24.04]
steps:
- uses: actions/checkout@v4
# Temporary fix. See https://github.com/actions/runner-images/issues/8659
- name: Install newer Clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x ./llvm.sh
sudo ./llvm.sh 17
- name: Build
run: |
export CC=clang-17
export CXX=clang++-17
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
clang-17 --version
make -j $(getconf _NPROCESSORS_ONLN)
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
clang --version
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -110,9 +89,9 @@ jobs:
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -132,9 +111,9 @@ jobs:
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -154,9 +133,9 @@ jobs:
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -176,9 +155,9 @@ jobs:
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

185
.github/workflows/clang-c++26.yml vendored Normal file
View File

@ -0,0 +1,185 @@
name: clang-c++26
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-clang-cpp26-linux-stl:
name: Clang C++26 Linux - STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=clang && \
export CXX=clang++ && \
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ && \
clang --version && \
make -j \$(getconf _NPROCESSORS_ONLN) && \
./test/etl_tests -v"
build-clang-cpp26-linux-no-stl:
name: Clang C++26 Linux - No STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=clang && \
export CXX=clang++ && \
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ && \
clang --version && \
make -j \$(getconf _NPROCESSORS_ONLN) && \
./test/etl_tests -v"
build-clang-cpp26-linux-stl-force-cpp03:
name: Clang C++26 Linux - STL - Force C++03
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=clang && \
export CXX=clang++ && \
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ && \
clang --version && \
make -j \$(getconf _NPROCESSORS_ONLN) && \
./test/etl_tests -v"
build-clang-cpp26-linux-no-stl-force-cpp03:
name: Clang C++26 Linux - No STL - Force C++03
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=clang && \
export CXX=clang++ && \
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ && \
clang --version && \
make -j \$(getconf _NPROCESSORS_ONLN) && \
./test/etl_tests -v"
build-clang-cpp26-osx-stl:
name: Clang C++26 OSX - STL
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-26]
steps:
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./
clang --version
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
build-clang-cpp26-osx-no-stl:
name: Clang C++26 OSX - No STL
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-26]
steps:
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./
clang --version
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
build-clang-cpp26-osx-stl-force-cpp03:
name: Clang C++26 OSX - STL - Force C++03
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-26]
steps:
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./
clang --version
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
build-clang-cpp26-osx-no-stl-force-cpp03:
name: Clang C++26 OSX - No STL - Force C++03
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-26]
steps:
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./
clang --version
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

View File

@ -23,10 +23,10 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=03 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp03-linux-No-STL:
name: Syntax Check - Clang C++03 Linux No STL
name: Syntax Check - Clang C++03 Linux No STL
runs-on: ${{ matrix.os }}
strategy:
matrix:
@ -41,7 +41,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=03 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp11-linux-STL:
name: Syntax Check - Clang C++11 Linux STL
@ -59,10 +59,10 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp11-linux-No-STL:
name: Syntax Check - Clang C++11 Linux No STL
name: Syntax Check - Clang C++11 Linux No STL
runs-on: ${{ matrix.os }}
strategy:
matrix:
@ -77,7 +77,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp11-linux-STL-Force-CPP03:
name: Syntax Check - Clang C++11 Linux STL Force C++03
@ -95,7 +95,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=11 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp11-linux-No-STL-Force-CPP03:
name: Syntax Check - Clang C++11 Linux No STL Force C++03
@ -113,7 +113,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=11 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp14-linux-STL:
name: Syntax Check - Clang C++14 Linux STL
@ -131,10 +131,10 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp14-linux-No-STL:
name: Syntax Check - Clang C++14 Linux No STL
name: Syntax Check - Clang C++14 Linux No STL
runs-on: ${{ matrix.os }}
strategy:
matrix:
@ -149,7 +149,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp14-linux-STL-Force-CPP03:
name: Syntax Check - Clang C++14 Linux STL Force C++03
@ -167,7 +167,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=14 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp14-linux-No-STL-Force-CPP03:
name: Syntax Check - Clang C++14 Linux No STL Force C++03
@ -185,7 +185,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=14 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp17-linux-STL:
name: Syntax Check - Clang C++17 Linux STL
@ -203,10 +203,10 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp17-linux-No-STL:
name: Syntax Check - Clang C++17 Linux No STL
name: Syntax Check - Clang C++17 Linux No STL
runs-on: ${{ matrix.os }}
strategy:
matrix:
@ -221,7 +221,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp17-linux-STL-Force-CPP03:
name: Syntax Check - Clang C++17 Linux STL Force C++03
@ -239,7 +239,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp17-linux-No-STL-Force-CPP03:
name: Syntax Check - Clang C++17 Linux No STL Force C++03
@ -257,7 +257,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp20-linux-STL:
name: Syntax Check - Clang C++20 Linux STL
@ -275,10 +275,10 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp20-linux-No-STL:
name: Syntax Check - Clang C++20 Linux No STL
name: Syntax Check - Clang C++20 Linux No STL
runs-on: ${{ matrix.os }}
strategy:
matrix:
@ -293,7 +293,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp20-linux-STL-Force-CPP03:
name: Syntax Check - Clang C++20 Linux STL Force C++03
@ -311,7 +311,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp20-linux-No-STL-Force-CPP03:
name: Syntax Check - Clang C++20 Linux No STL Force C++03
@ -329,7 +329,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp23-linux-STL:
name: Syntax Check - Clang C++23 Linux STL
@ -347,10 +347,10 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp23-linux-No-STL:
name: Syntax Check - Clang C++23 Linux No STL
name: Syntax Check - Clang C++23 Linux No STL
runs-on: ${{ matrix.os }}
strategy:
matrix:
@ -365,7 +365,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp23-linux-STL-Force-CPP03:
name: Syntax Check - Clang C++23 Linux STL Force C++03
@ -383,7 +383,7 @@ jobs:
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp23-linux-No-STL-Force-CPP03:
name: Syntax Check - Clang C++23 Linux No STL Force C++03
@ -401,4 +401,84 @@ jobs:
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp26-linux-STL:
name: Syntax Check - Clang C++26 Linux STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=clang && \
export CXX=clang++ && \
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./test/syntax_check && \
clang++ --version && \
make -j \$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp26-linux-No-STL:
name: Syntax Check - Clang C++26 Linux No STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=clang && \
export CXX=clang++ && \
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./test/syntax_check && \
clang++ --version && \
make -j \$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp26-linux-STL-Force-CPP03:
name: Syntax Check - Clang C++26 Linux STL Force C++03
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=clang && \
export CXX=clang++ && \
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./test/syntax_check && \
clang++ --version && \
make -j \$(getconf _NPROCESSORS_ONLN)"
build-clang-cpp26-linux-No-STL-Force-CPP03:
name: Syntax Check - Clang C++26 Linux No STL Force C++03
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=clang && \
export CXX=clang++ && \
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./test/syntax_check && \
clang++ --version && \
make -j \$(getconf _NPROCESSORS_ONLN)"

29
.github/workflows/clang-tidy.yaml vendored Normal file
View File

@ -0,0 +1,29 @@
name: clang-tidy
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
clang-tidy:
name: clang-tidy
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends clang clang-tidy
clang --version
clang-tidy --version
run-clang-tidy --version || true
- name: Run clang-tidy
run: |
test/run-clang-tidy.sh

View File

@ -65,8 +65,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
# GitHub Repository settings
# -> Settings -> Pages
# -> Source: gh actions
uses: actions/deploy-pages@v5

View File

@ -0,0 +1,39 @@
name: Deploy documentation to www.etlcpp.com
on:
push:
branches:
- master
workflow_dispatch:
jobs:
build_deploy:
name: build and deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: '0.147.1'
extended: true
- name: Build
working-directory: hugo
run: hugo --minify --cleanDestinationDir --baseURL "https://www.etlcpp.com/"
# Deploys the site via the deploy script in the ci directory
- name: Deploy
run: source $GITHUB_WORKSPACE/scripts/deploy_documentation.sh
env:
ACTIONS_DEPLOY_KEY: ${{ secrets.DOCS_BDEPLOY_KEY }}
SSH_USERNAME: ${{ secrets.DOCS_SSH_USER }}
SERVER_ADDRESS: ${{ secrets.DOCS_SSH_SERVER }}
SERVER_DESTINATION: ${{ secrets.DOCS_DEST_DIR }}
SSH_PORT: ${{ secrets.DOCS_SSH_PORT }}

View File

@ -26,7 +26,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -49,7 +49,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

View File

@ -25,7 +25,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -47,7 +47,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

View File

@ -25,7 +25,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -47,7 +47,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

View File

@ -25,7 +25,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -47,7 +47,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -69,7 +69,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -91,7 +91,7 @@ jobs:
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

29
.github/workflows/gcc-c++23-armhf.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-armhf
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-armhf:
name: GCC C++23 Linux - No STL - armhf
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-armhf -f .devcontainer/armhf/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-armhf bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/armhf/toolchain-armhf.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

29
.github/workflows/gcc-c++23-i386.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-i386
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-i386:
name: GCC C++23 Linux - No STL - i386
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-i386 -f .devcontainer/i386/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-i386 bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/i386/toolchain-i386.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

29
.github/workflows/gcc-c++23-powerpc.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-powerpc
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-powerpc:
name: GCC C++23 Linux - No STL - powerpc
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-powerpc -f .devcontainer/powerpc/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-powerpc bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/powerpc/toolchain-powerpc.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

29
.github/workflows/gcc-c++23-riscv64.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-riscv64
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-riscv64:
name: GCC C++23 Linux - No STL - riscv64
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-riscv64 -f .devcontainer/riscv64/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-riscv64 bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/riscv64/toolchain-riscv64.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

29
.github/workflows/gcc-c++23-s390x.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-s390x
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-s390x:
name: GCC C++23 Linux - No STL - s390x
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-s390x -f .devcontainer/s390x/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-s390x bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/s390x/toolchain-s390x.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

View File

@ -13,7 +13,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
os: [ubuntu-24.04]
steps:
- uses: actions/checkout@v4
@ -23,9 +23,9 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
export CC=gcc
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -35,7 +35,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
os: [ubuntu-24.04]
steps:
- uses: actions/checkout@v4
@ -45,9 +45,9 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
export CC=gcc
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -57,7 +57,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
os: [ubuntu-24.04]
steps:
- uses: actions/checkout@v4
@ -67,9 +67,9 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
export CC=gcc
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v
@ -79,7 +79,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
os: [ubuntu-24.04]
steps:
- uses: actions/checkout@v4
@ -89,9 +89,9 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
export CC=gcc
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
- name: Run tests
run: ./test/etl_tests -v

97
.github/workflows/gcc-c++26.yml vendored Normal file
View File

@ -0,0 +1,97 @@
name: gcc-c++26
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp26-linux-stl:
name: GCC C++26 Linux - STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
export CC=gcc && \
export CXX=g++ && \
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ && \
gcc --version && \
make -j \$(getconf _NPROCESSORS_ONLN) && \
./test/etl_tests -v"
build-gcc-cpp26-linux-no-stl:
name: GCC C++26 Linux - No STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
export CC=gcc && \
export CXX=g++ && \
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ && \
gcc --version && \
make -j \$(getconf _NPROCESSORS_ONLN) && \
./test/etl_tests -v"
build-gcc-cpp26-linux-stl-force-cpp03:
name: GCC C++26 Linux - STL - Force C++03
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
export CC=gcc && \
export CXX=g++ && \
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ && \
gcc --version && \
make -j \$(getconf _NPROCESSORS_ONLN) && \
./test/etl_tests -v"
build-gcc-cpp26-linux-no-stl-force-cpp03:
name: GCC C++26 Linux - No STL - Force C++03
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
export CC=gcc && \
export CXX=g++ && \
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ && \
gcc --version && \
make -j \$(getconf _NPROCESSORS_ONLN) && \
./test/etl_tests -v"

View File

@ -23,10 +23,10 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=03 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp03-linux-No-STL:
name: Syntax Check - GCC C++03 Linux No STL
name: Syntax Check - GCC C++03 Linux No STL
runs-on: ${{ matrix.os }}
strategy:
matrix:
@ -41,7 +41,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=03 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp11-linux-STL:
name: Syntax Check - GCC C++11 Linux STL
@ -59,7 +59,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp11-linux-No-STL:
name: Syntax Check - GCC C++11 Linux No STL
@ -77,7 +77,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp11-linux-STL-Force-CPP03:
name: Syntax Check - GCC C++11 Linux STL Force C++03
@ -95,7 +95,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=11 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp11-linux-No-STL-Force-CPP03:
name: Syntax Check - GCC C++11 Linux No STL Force C++03
@ -113,7 +113,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=11 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp14-linux-STL:
name: Syntax Check - GCC C++14 Linux STL
@ -131,7 +131,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp14-linux-No-STL:
name: Syntax Check - GCC C++14 Linux No STL
@ -149,7 +149,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp14-linux-STL-Force-CPP03:
name: Syntax Check - GCC C++14 Linux STL Force C++03
@ -167,7 +167,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=14 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp14-linux-No-STL-Force-CPP03:
name: Syntax Check - GCC C++14 Linux No STL Force C++03
@ -185,7 +185,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=14 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp17-linux-STL:
name: Syntax Check - GCC C++17 Linux STL
@ -203,7 +203,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp17-linux-No-STL:
name: Syntax Check - GCC C++17 Linux No STL
@ -221,7 +221,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp17-linux-STL-Force-CPP03:
name: Syntax Check - GCC C++17 Linux STL Force C++03
@ -239,7 +239,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp17-linux-No-STL-Force-CPP03:
name: Syntax Check - GCC C++17 Linux No STL Force C++03
@ -257,7 +257,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp20-linux-STL:
name: Syntax Check - GCC C++20 Linux STL
@ -275,7 +275,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp20-linux-No-STL:
name: Syntax Check - GCC C++20 Linux No STL
@ -293,7 +293,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp20-linux-STL-Force-CPP03:
name: Syntax Check - GCC C++20 Linux STL Force C++03
@ -311,7 +311,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp20-linux-No-STL-Force-CPP03:
name: Syntax Check - GCC C++20 Linux No STL Force C++03
@ -329,7 +329,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp23-linux-STL:
name: Syntax Check - GCC C++23 Linux STL
@ -347,7 +347,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp23-linux-No-STL:
name: Syntax Check - GCC C++23 Linux No STL
@ -365,7 +365,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp23-linux-STL-Force-CPP03:
name: Syntax Check - GCC C++23 Linux STL Force C++03
@ -383,7 +383,7 @@ jobs:
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp23-linux-No-STL-Force-CPP03:
name: Syntax Check - GCC C++23 Linux No STL Force C++03
@ -401,4 +401,84 @@ jobs:
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
make -j "$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp26-linux-STL:
name: Syntax Check - GCC C++26 Linux STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=gcc && \
export CXX=g++ && \
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./test/syntax_check && \
gcc --version && \
make -j \$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp26-linux-No-STL:
name: Syntax Check - GCC C++26 Linux No STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=gcc && \
export CXX=g++ && \
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./test/syntax_check && \
gcc --version && \
make -j \$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp26-linux-STL-Force-CPP03:
name: Syntax Check - GCC C++26 Linux STL Force C++03
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=gcc && \
export CXX=g++ && \
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./test/syntax_check && \
gcc --version && \
make -j \$(getconf _NPROCESSORS_ONLN)"
build-gcc-cpp26-linux-No-STL-Force-CPP03:
name: Syntax Check - GCC C++26 Linux No STL Force C++03
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-ubuntu-2604 -f .devcontainer/ubuntu-26.04/Dockerfile .
- name: Build
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
cd /workspaces/etl && \
export CC=gcc && \
export CXX=g++ && \
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./test/syntax_check && \
gcc --version && \
make -j \$(getconf _NPROCESSORS_ONLN)"

View File

@ -14,12 +14,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Generate
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y python3-cogapp
cd include/etl/generators && bash generate.bat
- name: Check Generated Headers For Changes
- name: Run generator_test.py
run: |
git diff --exit-code
cd scripts && python3 generator_test.py

View File

@ -0,0 +1,31 @@
name: meson-gcc-c++23-no-stl
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-meson-gcc-cpp23-no-stl:
name: Meson GCC C++23 Linux - No STL
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Install Meson
run: sudo apt-get install -y meson
- name: Configure
run: |
export CC=gcc
export CXX=g++
meson setup builddir -Duse_stl=false -Dcpp_std=c++23
- name: Build
run: meson compile -C builddir
- name: Run tests
run: meson test -C builddir -v

2
.gitignore vendored
View File

@ -419,3 +419,5 @@ hugo/resources
hugo/.hugo_build.lock
docs/*.html
test/build-coverage
include/etl/iterator.h~RFfd5eda.TMP
test/vs2022/Build

0
.gitmodules vendored Normal file
View File

9
BUILD.bazel Normal file
View File

@ -0,0 +1,9 @@
load("@rules_cc//cc:defs.bzl", "cc_library")
package(default_visibility = ["//visibility:public"])
cc_library(
name = "etl",
hdrs = glob(["include/**/*.h"]),
includes = ["include"],
)

144
DOCUMENTATION.md Normal file
View File

@ -0,0 +1,144 @@
# Viewing the documentation locally
The documentation for this project is built using [Hugo](https://gohugo.io/), a static site generator.
This guide will walk you through installing Hugo and running the documentation site on your machine.
---
## Prerequisites
- You must have already cloned this repository, including its submodules (the Hugo themes are stored as submodules).
- If you cloned without submodules, run this first:
```bash
git submodule update --init --recursive
```
---
## Step 1: Install Hugo Extended
This project requires the **extended** version of Hugo, which includes support for additional features such as SCSS/Sass processing.
Make sure you install the extended version, not the standard one.
### Windows
1. The easiest way to install Hugo on Windows is via [Chocolatey](https://chocolatey.org/). If you have it installed, open a command prompt as Administrator and run:
```bash
choco install hugo-extended -y
```
2. If you don't have Chocolatey, you can download Hugo Extended directly from the [Hugo releases page](https://github.com/gohugoio/hugo/releases).
Download the file named `hugo_extended_x.x.x_windows-amd64.zip`, extract it, and add the folder to your system PATH.
3. Verify the installation by opening a new command prompt and running:
```bash
hugo version
```
You should see the word **extended** in the output, for example: `hugo v0.x.x+extended`.
### macOS
1. The easiest way to install Hugo Extended on macOS is via [Homebrew](https://brew.sh/). Homebrew installs the extended version by default. If you have it installed, open a terminal and run:
```bash
brew install hugo
```
2. If you don't have Homebrew, you can install it first by following the instructions at [brew.sh](https://brew.sh/), then run the command above.
3. Verify the installation by running:
```bash
hugo version
```
You should see the word **extended** in the output, for example: `hugo v0.x.x+extended`.
### Linux
1. Package managers often provide an older or non-extended version of Hugo, so the recommended approach is to download the latest extended release directly from the [Hugo releases page](https://github.com/gohugoio/hugo/releases).
Download the file named `hugo_extended_x.x.x_linux-amd64.tar.gz`, then run:
```bash
tar -xzf hugo_extended_x.x.x_linux-amd64.tar.gz
sudo mv hugo /usr/local/bin/
```
2. Verify the installation by running:
```bash
hugo version
```
You should see the word **extended** in the output, for example: `hugo v0.x.x+extended`.
---
## Step 2: Run the documentation site
1. Open a terminal (or command prompt on Windows) and navigate to the `hugo` directory inside the project:
```bash
cd hugo
```
2. Start the Hugo development server:
```bash
hugo server
```
3. Hugo will start a local web server. You will see output similar to:
```
Web Server is available at http://localhost:1313/
```
4. Open your browser and go to **http://localhost:1313/** to view the documentation.
---
## Stopping the server
To stop the Hugo server, go back to your terminal and press **Ctrl+C**.
---
## Editing the Documentation
The documentation source files are located in the `/docs` directory at the root of the repository —
**not** inside the `hugo` directory. Hugo is configured to mount this directory automatically via
`hugo.toml`, so any changes you make to files in `/docs` will be picked up by the Hugo development
server straight away.
Here is a quick overview of where things live:
```
hugo/
├── layouts/ # HTML templates (you probably won't need to touch these)
├── themes/ # The Hugo theme (managed as a git submodule)
└── hugo.toml # Hugo configuration file (includes the /docs content mount)
docs/
└── section-name/ # Each subdirectory becomes a section in the documentation
├── _index.md # The landing page for that section
└── my-page.md # Individual pages within the section
```
### Adding or Editing a Page
All documentation pages are written in **Markdown** (`.md` files). To edit an existing page, open
the relevant `.md` file in the `/docs` directory and make your changes.
The documentation is written in [Goldmark](https://github.com/teekennedy/goldmark-markdown) markdown.
Hugo uses [Goldmark](https://github.com/teekennedy/goldmark-markdown) as its default Markdown processor for versions 0.60.0 and newer.
It is built into Hugo, providing high-performance and fully [CommonMark](https://commonmark.org/)-compliant rendering, along with support for [GitHub](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) Markdown.
### Starting a New Page
A template file is provided at `docs/page-template.md` to use as a starting point. Copy it to the
appropriate section directory, rename it, and edit the front matter, in particular, change the
`title` and remove the `draft: true` line, otherwise Hugo will not include your page in the
documentation.
### Previewing Your Changes
If you have the Hugo development server running (see [Step 2](#step-2--run-the-documentation-site)),
your changes will appear in the browser automatically as soon as you save the file. There is no need
to restart the server.
### Images and Other Assets
If you need to include images in your documentation, place them in the `hugo/static/` directory and
reference them in your Markdown like so:
```markdown
![Alt text](/my-image.png)
```
The site will automatically refresh in your browser whenever you save changes to the documentation files.

7
MODULE.bazel Normal file
View File

@ -0,0 +1,7 @@
module(
name = "etl",
version = "0.0.0",
)
bazel_dep(name = "platforms", version = "0.0.11")
bazel_dep(name = "rules_cc", version = "0.1.1")

205
MODULE.bazel.lock generated Normal file
View File

@ -0,0 +1,205 @@
{
"lockFileVersion": 24,
"registryFileHashes": {
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da",
"https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
"https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
"https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
"https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
"https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc",
"https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
"https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
"https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
"https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
"https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
"https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4",
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
"https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
"https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29",
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
"https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
"https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
"https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
"https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
"https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
"https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
"https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981",
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022",
"https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
"https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4",
"https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
"https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
"https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
"https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
"https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
"https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
"https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
"https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
"https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c",
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
"https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
"https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
"https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6",
"https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
"https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
"https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
"https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
"https://bcr.bazel.build/modules/rules_java/8.14.0/MODULE.bazel": "717717ed40cc69994596a45aec6ea78135ea434b8402fb91b009b9151dd65615",
"https://bcr.bazel.build/modules/rules_java/8.14.0/source.json": "8a88c4ca9e8759da53cddc88123880565c520503321e2566b4e33d0287a3d4bc",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
"https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
"https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
"https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
"https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
"https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
"https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
"https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
"https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
"https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
"https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
"https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
"https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
"https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
"https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
"https://bcr.bazel.build/modules/rules_python/0.40.0/source.json": "939d4bd2e3110f27bfb360292986bb79fd8dcefb874358ccd6cdaa7bda029320",
"https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
"https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95",
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
"https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
"https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
"https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
"https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
"https://bcr.bazel.build/modules/stardoc/0.7.1/source.json": "b6500ffcd7b48cd72c29bb67bcac781e12701cc0d6d55d266a652583cfcdab01",
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
"https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
},
"selectedYankedVersions": {},
"moduleExtensions": {
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
"general": {
"bzlTransitiveDigest": "rL/34P1aFDq2GqVC2zCFgQ8nTuOC6ziogocpvG50Qz8=",
"usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"com_github_jetbrains_kotlin_git": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
"attributes": {
"urls": [
"https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
],
"sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
}
},
"com_github_jetbrains_kotlin": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
"attributes": {
"git_repository_name": "com_github_jetbrains_kotlin_git",
"compiler_version": "1.9.23"
}
},
"com_github_google_ksp": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
"attributes": {
"urls": [
"https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
],
"sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
"strip_version": "1.9.23-1.0.20"
}
},
"com_github_pinterest_ktlint": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
"attributes": {
"sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
"urls": [
"https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
],
"executable": true
}
},
"rules_android": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
"strip_prefix": "rules_android-0.1.1",
"urls": [
"https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
]
}
}
},
"recordedRepoMappingEntries": [
[
"rules_kotlin+",
"bazel_tools",
"bazel_tools"
]
]
}
}
},
"facts": {}
}

View File

@ -2,7 +2,7 @@
![GitHub release (latest by date)](https://img.shields.io/github/v/release/jwellbelove/etl)
[![Release date](https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3)](https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3)
[![Standard](https://img.shields.io/badge/c%2B%2B-98/03/11/14/17/20/23-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization)
[![Standard](https://img.shields.io/badge/c%2B%2B-98/03/11/14/17/20/23/26-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
![GitHub contributors](https://img.shields.io/github/contributors-anon/ETLCPP/etl)
![GitHub forks](https://img.shields.io/github/forks/ETLCPP/etl?style=flat)
@ -15,6 +15,7 @@
![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++17.yml/badge.svg?branch=master)
![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++20.yml/badge.svg?branch=master)
![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++23.yml/badge.svg?branch=master)
![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++26.yml/badge.svg?branch=master)
![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-syntax-checks.yml/badge.svg?branch=master)
![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++11.yml/badge.svg?branch=master)
@ -22,6 +23,7 @@
![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++17.yml/badge.svg?branch=master)
![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++20.yml/badge.svg?branch=master)
![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++23.yml/badge.svg?branch=master)
![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++26.yml/badge.svg?branch=master)
![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-syntax-checks.yml/badge.svg?branch=master)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3c14cd918ccf40008d0bcd7b083d5946)](https://www.codacy.com/manual/jwellbelove/etl?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=ETLCPP/etl&amp;utm_campaign=Badge_Grade)
@ -49,7 +51,7 @@ Its design goals include:
- Offering APIs that closely resemble those of the STL, enabling familiar and consistent usage.
- Maintaining compatibility with C++98 while implementing many features introduced in later standards
(C++11/14/17/20/23) where possible.
(C++11/14/17/20/23/26) where possible.
- Ensuring deterministic behavior, which is critical in real-time and resource-constrained environments.

View File

@ -18,6 +18,22 @@
#define ARDUINO_BOARD "Teensy 3.5"
#elif defined(__MK66FX1M0__)
#define ARDUINO_BOARD "Teensy 3.6"
#elif defined(ARDUINO_TEENSY40)
#define ARDUINO_BOARD "Teensy 4.0"
#elif defined(ARDUINO_TEENSY41)
#define ARDUINO_BOARD "Teensy 4.1"
#elif defined(ARDUINO_TEENSY_MICROMOD)
#define ARDUINO_BOARD "Teensy MicroMod"
#else
#define ARDUINO_BOARD "Unknown"
#endif
#elif defined(CORE_ARDUINO_PICO)
#if defined(PICO_RP2040)
#define ARDUINO_BOARD "RP2040"
#elif defined(PICO_RP2350)
#define ARDUINO_BOARD "RP2350"
#else
#define ARDUINO_BOARD "Unknown"
#endif

6
docs/IO/_index.md Normal file
View File

@ -0,0 +1,6 @@
---
title: "IO"
weight: 100
---
Classes that address access to hardware.

View File

@ -0,0 +1,152 @@
---
title: "bip_buffer_spsc_atomic"
---
{{< callout >}}
Header: `bip_buffer_spsc_atomic.h`
Since: tbc
{{< /callout >}}
A fixed capacity bipartite buffer.
A bipartite buffer is a memory buffer design that uses two contiguous halves of the same underlying memory block to create a seamless, wraparound-free view of a circular/ring buffer's contents.
**The Problem It Solves**
Ring buffers are efficient for streaming data, but when data wraps around the end of the buffer back to the beginning, reading a contiguous chunk across that boundary normally requires two separate reads or a temporary copy.
**How It Works**
A bipartite buffer allocates a backing array that is twice the needed capacity. The two halves (the "bipartite" part) are mapped to the same physical memory, so:
The first region covers indices 0 to N-1
The second region covers indices N to 2N-1, but maps to the same memory as the first
This means any contiguous slice of up to N bytes can always be read as a single, linear pointer — no wraparound, no copying, no splitting.
```cpp
etl::bip_buffer_spsc_atomic<typename T,
size_t SIZE,
size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
```
Inherits from `etl::ibip_buffer_spsc_atomic<T>`.
`etl::ibip_buffer_spsc_atomic` may be used as a size independent pointer or reference type for any `etl::bip_buffer_spsc_atomic instance`.
## Member types
`value_type`
`size_type`
`reference`
`const_reference`
`rvalue_reference`
## Static Constants
`MAX_SIZE` The maximum size of the circular_buffer.
## Constructor
```cpp
etl::bip_buffer_spsc_atomic<typename T,
size_t SIZE,
size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>();
```
## Capacity
```cpp
bool empty() const
```
**Description**
Returns `true` if the size of the circular buffer is zero, otherwise `false`.
---
```cpp
bool full() const
```
**Description**
Returns `true` if the size of the circular buffer is `SIZE`, otherwise `false`.
---
```cpp
size_t size() const
```
**Description**
Returns the size of the circular buffer.
---
```cpp
size_t max_size() const
```
**Description**
Returns the maximum possible size of the circular buffer.
---
```cpp
size_t capacity() const
```
**Description**
Returns the maximum possible size of the circular buffer.
---
```cpp
size_t available() const
```
**Description**
Returns the remaining available capacity in the circular buffer.
## Modifiers
```cpp
etl::span<T> read_reserve(size_type max_reserve_size = numeric_limits<size_type>::max())
```
**Description**
Reserves a memory area for reading (up to the `max_reserve_size`).
```cpp
void read_commit(const etl::span<T> &reserve)
```
**Description**
Commits the previously reserved read memory area
the reserve can be trimmed at the end before committing.
Throws `bip_buffer_reserve_invalid`.
---
```cpp
etl::span<T> write_reserve(size_type max_reserve_size)
```
**Description**
Reserves a memory area for writing up to the `max_reserve_size`.
---
```cpp
etl::span<T> write_reserve_optimal(size_type min_reserve_size = 1U)
```
**Description**
Reserves an optimal memory area for writing. The buffer will only wrap
around if the available forward space is less than `min_reserve_size`.
---
```cpp
void write_commit(const etl::span<T> &reserve)
```
**Description**
Commits the previously reserved write memory area
the reserve can be trimmed at the end before committing.
Throws `bip_buffer_reserve_invalid`
---
```cpp
void clear()
```
**Description**
Clears the buffer, destructing any elements that haven't been read.

View File

@ -0,0 +1,277 @@
---
title: "buffer_descriptors"
---
{{< callout >}}
Header: `buffer_descriptors.h`
Since: All versions
{{< /callout >}}
A set of descriptors to a collection of buffers.
```cpp
template <typename TBuffer, // The type to store in the buffer.
TSize BUFFER_SIZE, // The size of each buffer.
size_t N_BUFFERS, // The total number of buffers.
typename TFlag = bool> // The 'in use' flag type.
class buffer_descriptors
```
The type used for the 'in use' flag depends on how the buffer descriptors class is used.
For interrupts and multi-threaded code, either the flag type must force a fence (by using an atomic type) or the calls to allocate and release must ensure that they are not re-ordered by the compiler or processor.
## Member types
| Type | |
| ------------- | -------------------------------------------------------------------- |
| value_type | The type that is stored in the buffers |
| size_type | An unsigned integral type |
| flag_type | |
| pointer | |
| descriptor | A nested class that encapsulates the details of an individual buffer |
| notification | A nested class that is sent to the user defined callback function |
| callback_type | `etl::delegate<void(notification)>` |
## Static Constants
| Value | |
| ----------- | --------------------------------------------------------- |
| N_BUFFERS | The number of buffers that the buffer descriptor controls |
| BUFFER_SIZE | The number of elements in each buffer |
## Constructors
```cpp
buffer_descriptors(pointer pbuffers)
```
**Description**
Construct with a pointer to the start of the buffers to control.
This storage should be contiguous and large enough to hold `N_BUFFERS`.
---
```cpp
buffer_descriptors(pointer pbuffers, const callback_type& callback)
```
**Description**
Construct with a pointer to the start of the buffers to control and the callback.
## Member functions
```cpp
void set_callback(const callback_type& callback)
```
**Description**
Set the callback for notification.
---
```cpp
bool is_valid() const
```
**Description**
Returns true if class contains valid buffers.
---
```cpp
void notify(notification n)
```
**Description**
Calls the user defined callback with the descriptor and buffer size.
Used when the buffer has been filled and is ready for processing via the callback.
---
```cpp
descriptor allocate()
```
**Description**
Returns a new descriptor.
If all descriptors are in use then the descriptor will be invalid.
---
```cpp
descriptor allocate(value_type fill)
```
**Description**
Returns a new descriptor and fills the buffer with fill.
If all descriptors are in use then the descriptor will be invalid.
---
```cpp
void clear()
```
**Description**
Clears by releasing all allocated descriptors.
```cpp
descriptor
```
**Description**
A nested class that encapsulates the details of an individual buffer.
---
```cpp
const size_type MAX_SIZE
```
**Description**
The maximum size of the buffer.
---
```cpp
descriptor()
```
**Description**
Default constructor.
---
```cpp
ETL_CONSTEXPR pointer data() const
```
**Description**
Returns a pointer to the start of the buffer.
---
```cpp
ETL_CONSTEXPR size_type max_size() const
```
**Description**
Returns the maximum size of the buffer.
---
```cpp
bool is_valid() const
```
**Description**
Returns true if the descriptor points to a valid buffer.
---
```cpp
bool is_allocated() const
```
**Description**
Returns true if the descriptor has been allocated.
---
```cpp
bool is_released() const
```
**Description**
Returns true if the descriptor has been released.
---
```cpp
void release()
```
**Description**
Releases the descriptor.
---
```cpp
notification
```
**Description**
A nested class that is sent to the user defined callback function.
---
```cpp
notification()
```
**Description**
Default contructor.
Initialises to a default constructed descriptor and a count of zero.
---
```cpp
notification(descriptor desc, size_t count)
```
**Description**
Construct with the supplied parameters.
---
```cpp
descriptor get_descriptor() const
```
**Description**
Gets the descriptor.
---
```cpp
size_t get_count() const
```
**Description**
Gets the count.
## Example
*Very simplified.*
Assumes that there is a DMA driver class called DMA.
In the real world the descriptor would be queued in the callback and handled in a foreground thread.
The handler in the thread would release the descriptor.
```cpp
constexpr size_t BUFFER_SIZE = 256U;
constexpr size_t N_BUFFERS = 8U;
// Define the buffer descriptors type.
using BD = etl::buffer_descriptors<char, BUFFER_SIZE, N_BUFFERS, std::atomic_char>;
// The buffers to use with it.
char buffers[N_BUFFERS][BUFFER_SIZE];
// The function to call when a buffer is ready.
void Callback(BD::notification notification)
{
// Process the buffer in the descriptor here.
ProcessData(notification.get_descriptor().data(), notification.get_count());
// Finished with the descriptor now, so release it back.
notification.get_descriptor().release();
}
// Create the buffer_descriptors.
BD bd(&buffers[0][0], BD::callback_type::create<Callback>());
// The current dma descriptor.
BD::descriptor dma_descriptor;
// An object that controls the DMA.
DMA dma;
// Call to start the DMA.
void DMAStart()
{
// Get a new descriptor.
dma_descriptor = bd.allocate();
if (dma_descriptor.is_valid())
{
// Link the buffer to the DMA channel.
dma.Start(dma_descriptor.data());
}
else
{
// No valid descriptors available.
LogError("No Descriptor Available");
}
}
// Called when the DMA has completed (usually an interrupt).
void DMAComplete()
{
// DMA is complete. Notify the callback.
bd.notify(BD::notification(dma_descriptor, dma.GetTransferredSize()));
}
```

246
docs/IO/debounce.md Normal file
View File

@ -0,0 +1,246 @@
---
title: "debounce"
---
{{< callout type="info">}}
Header: `debounce.h`
Since: `TBC`
{{< /callout >}}
A class to debounce signals.
It can detect signal hold, and generate auto repeat.
```cpp
etl::debounce<uint16_t Valid_Count = 0,
uint16_t Hold_Count = 0,
uint16_t Repeat_Count = 0>
```
There are four variants of the class which are selected at compile time according to the supplied template parameters.
All of the template parameters are optional.
If the first parameter is supplied then the debouncer acts as a simple signal debounce.
The signal will become valid after `VALID_COUNT` identical samples have been added.
If the second parameter is supplied then the debouncer will detect the signal being held true for `HOLD_COUNT` samples after becoming valid.
If the third parameter is supplied then the debouncer will indicate that a change has occurred for the signal being held true for each `REPEAT_COUNT` that occurs after entering the hold state.
If no template parameters are supplied then the template variant using internal variables is used.
This has similar parameters supplied to the constructor or the `set` member function.
The diagram below shows the effect of the various parameters.
![Debounce sequence](debounce.png)
## Functions
```cpp
debounce(bool initial_state = false)
```
**Description**
Default constructor.
`etl::debounce<Valid_Count, Hold_Count, Repeat_Count>`
The initial state defaults to:
Initial state = `false`
Valid count = `Valid_Count`
Hold count = `Hold_Count`
Repeat count = `Repeat_Count`
---
`etl::debounce<Valid_Count, Hold_Count>`
The initial state defaults to:
Initial state = `false`
Valid count = `Valid_Count`
Hold count = `Hold_Count`
Repeat count = `0` (Disabled)
---
`etl::debounce<Valid_Count>`
The initial state defaults to:
Initial state = `false`
Valid count = `Valid_Count`
Hold count = `0` (Disabled)
Repeat count = `0` (Disabled)
---
`etl::debounce<>`
The initial state defaults to:
Initial state = `false`
Valid count = `1`
Hold count = `0` (Disabled)
Repeat count = `0` (Disabled)
---
```cpp
debounce(bool initial_state,
uint16_t valid_count = 1,
uint16_t hold_count = 0,
uint16_t repeat_count = 0)
```
**Description**
The constructor available when no template parameters are supplied.
Valid count = `1`
Hold count = `0` (Disabled)
Repeat count = `0` (Disabled)
---
```cpp
bool add(bool sample)
```
**Description**
Adds a new signal sample. Returns true if the state of the debouncer becomes valid, held or repeating.
```cpp
bool has_changed() const
```
**Description**
Returns `true` if the state of the debouncer became valid, held or repeating after the last sample
---
```cpp
bool is_set() const
```
**Description**
Returns `true` if the debouncer is set, `false` if cleared.
---
```cpp
bool is_held() const
```
**Description**
Returns `true` if the debouncer signal is being held.
---
```cpp
bool is_repeating() const
```
**Description**
Returns `true` if the debouncer signal is repeating.
---
```cpp
void set(uint16_t valid_count, uint16_t hold_count = 0, uint16_t repeat_count = 0)
```
**Description**
Sets the debouncer parameters.
Only available when no template parameters are supplied.
## Examples
```cpp
etl::debounce<20> debouncer;
```
**Description**
Simple debounce.
Valid after 20 identical samples.
---
```cpp
etl::debounce<20, 1000> debouncer;
```
**Description**
Key debounce.
Valid after 20 identical samples.
Hold detection after 1000 'set' samples.
---
```cpp
etl::debounce<20, 1000, 100> debouncer;
```
**Description**
Key debounce with hold and auto repeat.
Valid after 20 identical samples.
Hold detection after 1000 'set' samples.
Repeat every 100 samples after hold.
---
```cpp
etl::debounce<> debouncer;
debouncer.set(20, 1000, 100);
```
**Description**
Key debounce with hold and auto repeat.
Runtime parameters.
---
The example below targets the Arduino hardware.
```cpp
//***********************************************************************************
// A debounce demo that reads a key and toggles the LED.
// Set the pin to the correct one for your key.
//***********************************************************************************
#include <debounce.h>
// The sample time in ms.
const int Sample_Time = 1;
// The number of samples that must agree before a key state change is recognised.
// 50 = 50ms for 1ms sample time.
const int Debounce_Count = 50;
// The number of samples that must agree before a key held state is recognised.
// 1000 = 1s for 1ms sample time.
const int Hold_Count = 1000;
// The number of samples that must agree before a key repeat state is recognised.
// 200 = 200ms for 1ms sample time.
const int Repeat_Count = 200;
// The pin that the key is attached to.
const int Key = XX;
void setup()
{
// Initialize LED pin as an output.
pinMode(LED_BUILTIN , OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// Initialize KEY pin as an input.
pinMode(KEY, INPUT);
}
void loop()
{
static int led_state = LOW;
static etl::debounce<Debounce_Count, Hold_Count, Repeat_Count> key_state;
// Assumes 'HIGH' is 'pressed' and 'LOW' is 'released'.
if (key_state.add(digitalRead(KEY) == HIGH))
{
if (key_state.is_set())
{
// Toggle the LED state on every validated press or repeat.
led_state = (led_state == LOW ? HIGH : LOW);
digitalWrite(LED_BUILTIN, led_state);
}
}
delay(1); // Wait 1ms
}
```

BIN
docs/IO/debounce.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

411
docs/IO/io_port.md Normal file
View File

@ -0,0 +1,411 @@
---
title: "io_port"
---
{{< callout type="info">}}
Header: `io_port.h`
From: `20.39.0`
{{< /callout >}}
A set of templates for building interface classes to memory mapped hardware ports.
They avoid the need to directly map carefully packed (and possibly non-portable) structures onto memory addresses.
>A read from a write-only, or write to a read-only port will result in a compile time error.
**Defines classes for the following IO types**
Read / Write.
Read only.
Write only.
Write only with shadow register.
With a shadow register the value written is stored locally and may be read back.
The port may either have an address fixed at compile time or set at runtime. The compile time versions require no extra overhead compared to a plain memory mapped structure.
Ports may be sent as parameters to algorithms that expect iterators, except the runtime address version of `io_port_wos`, which must use the built-in iterator if the shadow value is to be correctly updated for writes.
All classes define the following typedefs.
| Type name | Maps to |
| ----------------- | ------------------- |
| `value_type` | `T` |
| `pointer` | `volatile T*` |
| `const_pointer` | `volatile const T*` |
| `reference` | `volatile T&` |
| `const_reference` | `volatile const T&` |
## Read/write port
```cpp
io_port_rw<typename T, uintptr_t Address>
```
**Description**
Compile time port address.
---
**Types**
iterator
const_iterator
---
```cpp
operator T() const
```
**Description**
Read the value.
Conversion operator to T.
---
```cpp
iterator iter()
```
**Description**
Get an iterator to this port.
---
```cpp
const_iterator iter() const
const_iterator citer() const
```
**Description**
Get a const_iterator to this port.
---
```cpp
T read() const
```
**Description**
Read the value.
---
```cpp
void write(T value)
```
**Description**
Write the value.
---
```cpp
io_port_rw& operator =(T value)
```
**Description**
Write the value.
---
```cpp
pointer get_address()
const_pointer get_address() const
```
**Description**
Gets the address of the port.
---
```cpp
io_port_rw& operator |=(value_type value)
```
**Description**
Or-Equals operator.
---
```cpp
io_port_rw& operator &=(value_type value)
```
**Description**
And-Equals operator.
---
```cpp
io_port_rw& operator ^=(value_type value)
```
**Description**
Exclusive-Or-Equals operator.
---
```cpp
io_port_rw& operator <<=(int shift)
```
**Description**
Left-Shift-Equals operator.
---
```cpp
io_port_rw& operator >>=(int shift)
```
**Description**
Right-Shift-Equals operator.
---
```cpp
value_type operator ~() const
```
**Description**
Not operator.
## Read only port
```cpp
io_port_ro<typename T, uintptr_t Address>
```
---
**Types**
```cpp
const_iterator
```
---
```cpp
operator T() const
```
**Description**
Read the value. Conversion operator to T.
---
```cpp
const_iterator iter() const
const_iterator citer() const
```
**Description**
Get a const_iterator to this port.
---
```cpp
T read() const
```
**Description**
Read the value.
---
```cpp
const_pointer get_address() const
```
**Description**
Gets the address of the port.
## Write only port
```cpp
io_port_wo<typename T, uintptr_t Address>
```
---
**Types**
iterator
---
```cpp
iterator iter()
```
**Description**
Get an iterator to this port.
---
```cpp
void write(T value)
```
**Description**
Write the value.
---
```cpp
io_port_wo& operator =(T value)
```
**Description**
Write the value.
---
```cpp
pointer get_address()
```
**Description**
Gets the address of the port.
## Write only port, with shadow register
```cpp
io_port_wos<typename T, uintptr_t Address>
```
---
**Types**
```cpp
iterator
const_iterator
```
---
```cpp
operator T() const
```
**Description**
Read the value. Conversion operator to `T`.
---
```cpp
iterator iter()
```
**Description**
Get an iterator to this port.
---
```cpp
const_iterator iter() const
const_iterator citer() const
```
**Description**
Get a `const_iterator` to this port.
---
```cpp
T read() const
```
**Description**
Read the value.
---
```cpp
void write(T value)
```
**Description**
Write the value.
---
```cpp
io_port_rw& operator =(T value)
```
**Description**
Write the value.
---
```cpp
pointer get_address()
const_pointer get_address() const
```
**Description**
Gets the address of the port.
---
```cpp
io_port_rw& operator |=(value_type value)
```
**Description**
Or-Equals operator.
---
```cpp
io_port_rw& operator &=(value_type value)
```
**Description**
And-Equals operator.
---
```cpp
io_port_rw& operator ^=(value_type value)
```
**Description**
Exclusive-Or-Equals operator.
---
```cpp
io_port_rw& operator <<=(int shift)
```
**Description**
Left-Shift-Equals operator.
---
```cpp
io_port_rw& operator >>=(int shift)
```
**Description**
Right-Shift-Equals operator.
---
```cpp
value_type operator ~() const
```
**description**
Not operator.
## Example serial port
The example uses a port at a compile time address.
| Variable | Description |
| --------- | ---------------------------------------------------------- |
| `rxdata` | An 8 bit read only port |
| `txdata` | An 8 bit write only port |
| `control` | A 16 bit write only port, with shadow register |
| `status` | A 16 bit read only port. It shares an address with control |
| `option` | An 8 bit read/write port |
```cpp
template <uintptr_t Address>
struct serial_port
{
etl::io_port_ro<char, Address> rxdata; // Read only rx data register.
etl::io_port_wo<char, Address + 1> txdata; // Write only tx register.
etl::io_port_wos<uint16_t, Address + 2> control; // Write only, with shadow, control register.
etl::io_port_ro<uint16_t, Address + 2> status; // Read only status register.
etl::io_port_ro<char, Address> option; // Read/Write register.
};
serial_port<0x800> port; // A serial port at address 0x800
// Read Rx data
char data = port.rxdata;
// Write Tx data
port.txdata = 'A';
// Compile error! txdata is write only.
data = port.txdata;
// Write to the control register and read back what we wrote.
port.control = 0x1234;
uint16_t control = port.control;
// Flip bit 3 of the control register.
port.control ^= 0x0080;
// Read from the status register.
uint16_t status = port.status;
// Copy data from a buffer to the Tx data port.
std::copy(txBuffer.begin(), txBuffer.end(), serial_port.txdata.iter());
// Copy data from the Rx data port to a buffer.
std::copy_n(serial_port.rxdata, serial_port.status, std::back_inserter(rxBuffer));
```

75
docs/Is the ETL free.md Normal file
View File

@ -0,0 +1,75 @@
---
title: "Is the ETL free?"
# Force it to the top of the list
weight: 1
# Disable the Table of Contents entirely for this page
toc: false
---
The ETL is free for you or your company to use, including in commercial applications.
*However, it is not free for me to create or maintain.*
## Why Open Source Needs Support
Development, support, documentation, testing, and hosting all require time and resources.
*Currently, this work is carried entirely by me, usually without compensation.*
As the ETL has grown in functionality and popularity, so has the workload. In some weeks, maintaining the project takes over 30 hours. Without financial support, this is difficult to sustain alongside paid work and personal obligations.
## Why Sponsor the Embedded Template Library (ETL)?
The Embedded Template Library (ETL) is a modern, high-performance C++ library designed specifically for embedded systems. It provides STL-like functionality for environments where efficiency, reliability, and low overhead are essential.
The ETL is used by hobbyists, engineers, and international companies developing commercial embedded products. Yet it is maintained by a single developer in their spare time.
If the ETL has helped your project or become part of your development toolset, please consider supporting its continued growth.
## Why Sponsorship Matters
- **Sustainability**
Ongoing support helps keep the library maintained and up to date.
- **Reliability**
Sponsorship allows for regular testing, bug fixes, and improvements.
- **Responsibility**
Supporting the tools you depend on strengthens the software ecosystem.
- **Recognition**
Sponsors can be publicly acknowledged if desired.
Whether you use the ETL in personal projects or commercial products, your support helps keep it available and improving.
The ETL began as a way to share years of embedded development experience. Since 2014, it has grown into a feature-rich and widely used library.
*But it is still powered by one developer, without corporate funding.*
If you or your company benefit from the ETL, please consider becoming a sponsor. Even small contributions help cover hosting, tools, and time spent supporting the library and its users.
[Why CFOs should care about Open Source software](https://opensourcepledge.com/blog/CFOs-care-about-OSS/)
## How to sponsor
There are two ways that you can help me with the maintenance and further development of the library.
**Through the GitHub donations link.**
[Github sponsors](https://github.com/sponsors/ETLCPP)
---
**By direct bank transfer**
Donations are accepted in many world currencies.
AED, AUD, BGN, CAD, CHF, CLP, COP, CZK, DKK, EGP, EUR, GBP, HKD, HUF, ILS, INR, ISK, JPY, KRW,
KZT, MAD, MXN, NOK, NZD, PHP, PLN, QAR, RON, RSD, SAR, SEK, SGD, THB, TRY, USD, ZAR
I can supply invoices for companies that require one for accounting and tax purposes.
**UK**
Beneficiary John Wellbelove
Account 12655643
Sort code 04-00-75
**Swift (International)**
Beneficiary John Wellbelove
IBAN GB17 REVO 0099 7000 7513 26
BIC REVOGB21
Many thanks for any support you can give to keep this project actively supported,
*John Wellbelove*

23
docs/Messaging/_index.md Normal file
View File

@ -0,0 +1,23 @@
---
title: "Messaging"
weight: 100
---
## Headers
- `message.h`
Defines the core message model. etl::imessage is the base interface (virtual or non-virtual, depending on `ETL_HAS_VIRTUAL_MESSAGES`). `etl::message<ID>` provides typed messages with static IDs. Type traits (`is_message`, `is_message_type`, etc.) and ID comparison utilities support compile-time validation.
- `message_router.h`
Defines `etl::imessage_router`, the central routing interface with receive, accepts, and router identity. Provides message_router<TDerived, ...> that statically dispatches by message ID (contiguous IDs optimized). Includes null_message_router and message_producer helpers, plus send_message utilities.
- `message_bus.h`
Implements `etl::imessage_bus`, a router that manages a sorted list of subscribed routers and forwards messages based on destination ID (broadcast or addressed). Supports subscription limits and forwards to successors.
- `message_broker.h`
Implements etl::message_broker, a router with explicit subscription objects mapping routers to message ID lists (span). It routes only to subscribers that match both message ID and destination ID, then forwards to any successor.
- `message_packet.h`
A type-erased, in-place container for a fixed set of message types. Validates message ID acceptance, supports copy/move, and exposes `get()` as `etl::imessage&`. Uses aligned storage sized to the largest message type.
- `shared_message.h`
Reference-counted wrapper around pooled messages (`ireference_counted_message_pool`). Supports copy/move semantics with automatic release when the last reference drops.
## Basic architecture
![message-framework](images/message-framework.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -0,0 +1,217 @@
---
title: "message_broker"
weight: 6
---
{{< callout type="info">}}
Header: `message_broker.h`
{{< /callout >}}
Message Broker
A variant of the observer pattern in that message routers and derived types are be able to subscribe to selected sets of messages. The message_broker is similar to the message_bus, but it provides more control over the routing of messages. While the message_bus simply broadcasts every message to all subscribers, the message_broker allows you to specify which subscribers should receive each message.
Derived from `imessage_router`.
## Types
```cpp
message_id_span_t etl::span<const etl::message_id_t>
```
## subscription
A nested class of `etl::message_broker`.
The base for broker subscription information.
Derive from this to define your subscription class.
See Example.
---
```cpp
subscription(etl::imessage_router& router)
```
Constructor.
---
```cpp
virtual message_id_span_t message_id_list() const = 0;
```
Override this to return a span of message ids.
## message_broker
```cpp
message_broker()
```
The broker is constructed with an id of `etl::imessage_router::MESSAGE_BROKER`.
---
```cpp
message_broker(etl::imessage_router& successor)
```
The broker is constructed with an id of `etl::imessage_router::MESSAGE_BROKER`.
Sets the successor.
---
```cpp
message_broker(etl::message_router_id_t id)
```
The broker is constructed with the specified id.
---
```cpp
message_broker(etl::message_router_id_t id, etl::imessage_router& successor)
```
The broker is constructed with the specified id.
Sets the successor.
---
```cpp
void subscribe(etl::imessage_router& router)
```
Subscribes an `etl::imessage_router` derived class to the broker.
A subscription object must have a lifetime of at least the same as the broker.
A subscription cannot be shared with another broker.
---
```cpp
void unsubscribe(etl::imessage_router& router)
```
Unsubscribes the specified `etl::imessage_router` derived class from the bus.
Does not unsubscribe from nested buses.
---
```cpp
void receive(const etl::imessage& message)
void receive(etl::shared_message message)
```
Receives a message and distributes it to all subscribers that have registered to receive the message type.
Forwards the message to any successor.
Override this in a derived class if you wish to capture messages sent to the broker.
Call the base receive function from here to allow normal operation to continue.
---
```cpp
bool accepts(etl::message_id_t id) const
```
Always returns `true`.
---
```cpp
void clear()
```
Clears the broker of all subscribers.
---
```cpp
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
```
Always returns `false`.
---
```cpp
bool is_producer() const ETL_OVERRIDE
```
Always returns `true`.
---
```cpp
bool is_consumer() const ETL_OVERRIDE
```
Always returns `true`.
---
```cpp
bool empty() const
```
Returns `true` is the are are no subscribers.
## Example
```cpp
// Some router ids.
enum
{
ROUTER_ID_1,
ROUTER_ID_2,
};
// Custom subscription type.
class Subscription : public etl::message_broker::subscription
{
public:
Subscription(etl::imessage_router& router, std::initializer_list<etl::message_id_t> id_list_)
: etl::message_broker::subscription(router)
, id_list(id_list_)
{
}
etl::message_broker::message_id_span_t message_id_list() const override
{
return etl::message_broker::message_id_span_t(id_list.begin(), id_list.end());
}
std::vector<etl::message_id_t> id_list;
};
// Instances of messages.
Message1 message1;
Message2 message2;
Message3 message3;
Message4 message4;
// Custom broker.
class Broker : public etl::message_broker
{
public:
using etl::message_broker::receive;
// Hook incoming messages and translate Message4 to Message3.
void receive(const etl::imessage& msg) override
{
if (msg.get_message_id() == Message4::ID)
{
etl::message_broker::receive(Message3());
}
else
{
etl::message_broker::receive(msg);
}
}
};
// Instances of message routers.
Router1 router1;
Router2 router2;
// The subscriptions.
Subscription subscription1{ router1, { Message1::ID, Message2::ID } };
Subscription subscription2{ router2, { Message2::ID, Message3::ID } };
// Instance of message broker.
etl::message_broker broker;
// Subscribe router1 and router1 to the broker.
broker.subscribe(subscription1);
broker.subscribe(subscription2);
broker.receive(message1); // Received by router1
broker.receive(message2); // Received by router1 and router2
broker.receive(message3); // Received by router2
broker.receive(message4); // Received by router2 as a Message3
```

View File

@ -0,0 +1,207 @@
---
title: "message_bus"
weight: 5
---
{{< callout type="info">}}
Header: `message_broker.h`
From: `20.33.0`
{{< /callout >}}
Message Bus
This page documents version `20.0.0` and above.
A variant of the observer pattern in that message routers and derived types are be able to subscribe to messages on a bus. The messages can be either broadcast, to be automatically picked up by any router that has a handler, or addressed to a particular router or router id. Message buses may be nested by setting a successor.
## imessage_bus
Derived from imessage_router.
The base for all message buses.
Inherits publicly from `etl::imessage_router`.
Message buses are therefore also a type of router.
Objects of type `etl::imessage_bus` cannot be directly constructed.
## Member functions
```cpp
bool subscribe(etl::imessage_router& router)
```
Subscribes an `etl::imessage_router` derived class to the bus.
Returns `true` on success.
---
```cpp
void unsubscribe(etl::imessage_router& router)
```
Unsubscribes the specified `etl::imessage_router` derived class from the bus.
Does not unsubscribe from nested buses.
---
```cpp
void unsubscribe(etl::message_router_id_t id)
```
Unsubscribes routers with the specified id from the bus.
Does not unsubscribe from nested buses.
`etl::imessage::MESSAGE_BUS` will unsubscribe all message buses.
`etl::imessage::ALL_MESSAGE_ROUTERS` will unsubscribe all routers and buses. Equivalent to calling `clear()`.
---
```cpp
void receive(const etl::imessage& message)
void receive(etl::shared_message message)
```
Receives a message and distributes it to all subscribers.
Forwards the message to any successor.
The routers are called first, in order of ascending router id.
Routers with the duplicate ids will be called in subscribe order.
Any nested message buses are called in subscribe order.
---
```cpp
void receive(etl::message_router_id_t destination_router_id,
const etl::imessage& message);
void receive(etl::message_router_id_t destination_router_id,
etl::shared_message message)
```
Receives a message and distributes it to all subscribers that have the specified router id.
Forwards the message to any successor.
Routers with the duplicate ids will be called in subscribe order.
Any nested message buses are called in subscribe order.
Override this in a derived class if you wish to capture messages sent to the bus.
Call the base receive function from here to allow normal operation to continue.
---
```cpp
bool accepts(etl::message_id_t id) const
```
Always returns `true`.
---
```cpp
size_t size() const
```
Returns the number of subscribers.
---
```cpp
void clear()
```
Clears the bus of all subscribers.
Message buses inherit all of the public functions of `etl::imessage_router`.
## Errors
```cpp
message_bus_exception
```
Base error class for `etl::message_bus`. Inherits from `etl::exception`.
---
```cpp
message_bus_too_many_subscribers
```
Emitted when the number of subscribers exceeds the capacity. Inherits from `etl::message_bus_exception`.
## message_bus
Derived from `imessage_bus`.
```cpp
template <const uint_least8_t MAX_ROUTERS>
class message_bus
```
`MAX_ROUTERS` The maximum number of routers that can be subscribed.
## Member functions
```cpp
message_bus()
```
Constructs a message bus.
Message buses always have a router id of `etl::imessage::MESSAGE_BUS`.
```cpp
message_bus(etl::imessage_router& successor)
```
Constructs a message bus and sets the successor.
Message buses always have a router id of `etl::imessage::MESSAGE_BUS`.
## Example
```cpp
// Some router ids.
enum
{
ROUTER_ID_1,
ROUTER_ID_2,
ROUTER_ID_3
};
// Instances of messages.
MessageA messageA;
// Instances of message routers.
RouterA routerA(ROUTER_ID_1);
RouterB routerB(ROUTER_ID_1);
RouterC routerC(ROUTER_ID_2);
RouterD routerD(ROUTER_ID_3);
RouterE routerE(ROUTER_ID_1);
// Instances of message buses.
etl::message_bus<4> bus1;
etl::message_bus<2> bus2;
etl::message_bus<1> bus3;
// Subscribe bus2 & bus3 to bus1.
bus1.subscribe(bus3);
bus1.subscribe(bus2);
// Subscribe routerB & routerA to bus1.
bus1.subscribe(routerB);
bus1.subscribe(routerA);
// Subscribe routerD & routerC to bus2.
bus2.subscribe(routerD);
bus2.subscribe(routerC);
// Subscribe routerE to bus3.
bus3.subscibe(routerE);
// Assume all routers accept the same messages.
// Broadcast messageA to everyone.
bus1.receive(messageA);
// The call order will be...
// routerB
// routerA
// routerE
// routerC
// routerD
// Address messageA to routers with id ROUTER_ID_1.
bus1.receive(ROUTER_ID_1, messageA);
// The call order will be...
// routerB
// routerA
// routerE
// Address messageA to routers with id ROUTER_ID_3.
bus1.receive(ROUTER_ID_3, messageA);
// The call order will be...
// routerD
```

View File

@ -0,0 +1,155 @@
---
title: "message_packet"
---
{{< callout type="info">}}
Header: `message_packet.h`
{{< /callout >}}
A container for more than one type of message.
The messages must have been derived from `etl::imessage`.
The messages types that the packet may contain are listed as template parameters.
e.g. `etl::message_packet<Message1, Message2, Message3>`
From `20.40.0` message types are not required to have a virtual destructor.
---
```cpp
message_packet()
```
Default constructs a message packet.
`is_valid()` returns `false`.
---
```cpp
explicit message_packet(const etl::imessage&)
```
Constructs a message packet from an `etl::imessage` reference.
Asserts an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list.
---
```cpp
explicit message_packet(etl::imessage&&) C++11
```
Move constructs a message packet from an `etl::imessage` rvalue reference.
Emits an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list.
---
```cpp
template <typename TMessage>
explicit message_packet(const TMessage&)
```
Constructs a message packet from a `TMessage` reference.
Emits a compile time static assert if the parameter is not one listed in the template parameter list.
From: `20.22.0`
---
```cpp
template <typename TMessage>
explicit message_packet(TMessage&&)
```
Move constructs a message packet from a `TMessage` rvalue reference.
Emits a compile time static assert if the parameter is not one listed in the template parameter list.
From: `20.22.0`
---
```cpp
message_packet(const message_packet&)
```
Constructs a message packet from an `message_packet` reference.
Emits an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list.
---
```cpp
message_packet(message_packet&&)
```
Move constructs a message packet from an `message_packet` rvalue reference.
Emits an `etl::unhandled_message_exception` if the parameter is not one listed in the template parameter list.
---
```cpp
message_packet& operator =(const message_packet&)
```
Assigns a message packet from an `message_packet` reference.
Emits an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list.
---
```cpp
message_packet& operator =(message_packet&&)
```
Move assigns a message packet from an `message_packet` rvalue reference.
Emits an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list.
---
```cpp
etl::imessage& get()
const etl::imessage& get() const
```
Returns a reference to an `etl::imessage`.
---
```cpp
bool is_valid() const
```
Returns `true` if the packet contains a valid message, otherwise `false`.
---
## Constants
`SIZE` The size of the largest message.
`ALIGNMENT` The largest message alignment.
---
## Example
```cpp
enum
{
MESSAGE1,
MESSAGE2,
MESSAGE3
};
struct Message1 : public etl::message<MESSAGE1>
{
};
struct Message2 : public etl::message<MESSAGE2>
{
};
struct Message3 : public etl::message<MESSAGE3>
{
};
using Packet = etl::message_packet<Message1, Message2>
Message1 message1;
Message2 message2;
Message3 message3;
Packet packet1(message1);
Packet packet2(message2);
Packet packet3(message3); // Runtime time error! Packet does not support Message3 type.
etl::imessage& m1 = message1;
Packet packet4(m1); // Construct from an etl::imessage reference.
etl::imessage& m3 = message3;
Packet packet4(m3); // Asserts etl::unhandled_message_exception! Packet does not support Message3 type.
etl::imessage& m = packet2.get(); // Get a reference to an etl::imessage from the packet.
```

View File

@ -0,0 +1,180 @@
---
title: "message_router_registry"
weight: 4
---
{{< callout type="info">}}
Header: `message_router_registry`
From: `20.6.0`
{{< /callout >}}
A class that will act as a registry for all message router types.
When iterating through the registry, routers with identical IDs are ordered by insertion.
**Defines the following classes**
```cpp
etl::imessage_router_registry
etl::message_router_registry
```
## imessage_router_registry
The base class for all router registries.
### Iterators
```cpp
iterator
const_iterator
```
### Member functions
```cpp
iterator begin()
const_iterator begin() const
const_iterator cbegin() const
```
Get the beginning of the registry.
---
```cpp
iterator end()
const_iterator end() const
const_iterator cend() const
```
Get the end of the registry.
---
```cpp
iterator lower_bound(etl::message_router_id_t id)
const_iterator lower_bound(etl::message_router_id_t id) const
```
Get the lower bound in the registry of the router with the specified ID.
---
```cpp
iterator upper_bound(etl::message_router_id_t id)
const_iterator upper_bound(etl::message_router_id_t id) const
```
Get the upper bound in the registry of the router with the specified ID.
---
```cpp
etl::imessage_router* find(etl::message_router_id_t id)
const etl::imessage_router* find(etl::message_router_id_t id) const
```
Returns a pointer to the first router with the specified ID, or `ETL_NULLPTR` if it cannot be found.
---
```cpp
void add(etl::imessage_router& router)
void add(etl::imessage_router* p_router)
```
Registers a router.
If the registry is full then an ETL assert is emitted (`etl::message_router_registry_full`).
Duplicate routers will be ignored.
---
```cpp
template <typename TIterator>
void add(TIterator first, const TIterator& last)
```
Registers a collection of routers.
If the registry becomes full then an ETL assert is emitted (`etl::message_router_registry_full`).
Duplicate routers will be ignored.
---
```cpp
void remove(etl::message_router_id_t id)
```
Unregisters a router.
---
```cpp
bool contains(const etl::message_router_id_t id) const
bool contains(const etl::imessage_router* const p_router) const
bool contains(const etl::imessage_router& router) const
```
Returns `true` if the registry contains a router that has the specified ID or object.
---
```cpp
bool empty() const
```
Returns `true` if the registry is empty, otherwise `false`.
---
```cpp
bool full() const
```
Returns `true` if the registry is full, otherwise `false`.
---
```cpp
size_t size() const
```
Returns the size of the registry.
---
```cpp
size_t available() const
```
Returns the available size of the registry.
---
```cpp
size_t max_size() const
```
Returns the maximum size of the registry.
---
## message_router_registry
```cpp
message_router_registry()
```
Default constructor.
---
```cpp
template <typename TIterator>
message_router_registry(TIterator first, const TIterator& last)
```
Constructs from an iterator range.
---
```cpp
message_router_registry(std::initializer_list<etl::imessage_router*> init)
```
Initializer_list constructor.
Enabled for C++11 or above.
---
```cpp
message_router_registry(const message_router_registry& rhs)
```
Copy constructor.
---
```cpp
message_router_registry& operator =(const message_router_registry& rhs)
```
Assignment operator.

112
docs/Messaging/message.md Normal file
View File

@ -0,0 +1,112 @@
---
title: "message"
weight: 1
---
{{< callout type="info">}}
Header: `message.h`
{{< /callout >}}
Message types used for many of the framework classes.
---
```cpp
etl::message_id_t
```
The type used for message ids.
By default can hold a value between 0 and 255.
If `ETL_MESSAGE_ID_TYPE` is defined then this type will be used instead.
---
```cpp
etl::message_router_id_t
```
The type used for message router ids.
Can hold a value between 0 and 255.
---
The message classes are the common communication method across all of the message capable frameworks.
They are identified by a unique id number that specialises the base class.
## imessage
The base class for messages.
It is this class that is passed around, usually by const reference.
The class is abstract.
---
```cpp
etl::message_id_t get_message_id() const ETL_NOEXCEPT = 0;
```
Returns the id of the message.
---
## message
```cpp
message<size_t ID, typename TParent = etl::imessage>
```
Requires an integral id as the template parameter.
Inherits from `TParent`, which defaults to `etl::imessage`.
`TParent` allows additional base interfaces or functionality to be included.
static asserts if `TParent` is not a base of `etl::imessage`.
---
```cpp
ID
```
The id of the message as an enum.
Can be accessed by `etl::message` instances.
---
```cpp
TParent
```
The class that it inherits from. It must ultimately derive from `etl::imessage`.
The default is `etl::imessage`.
---
## Example
```cpp
enum
{
START,
STOP,
SET_SPEED
};
struct MyInterface : public etl::imessage
{
virtual void DoStuff() = 0;
};
// Start implements MyIterface
struct Start : public etl::message<START, MyInterface>
{
void DoStuff() override
{
// Do stuff here.
}
};
struct Stop : public etl::message<STOP>
{
bool isEmergencyStop;
};
struct SetSpeed : public etl::message<SET_SPEED>
{
uint32_t speed;
};
void Receive(const etl::imessage& msg);
```

View File

@ -0,0 +1,139 @@
---
title: "reference_counted_message_pool"
---
{{< callout type="info">}}
Header: `reference_counted_message_pool.h`
Header: `ireference_counted_message_pool.h`
{{< /callout >}}
Allocates `etl::ireference_counted_message` types that are used by `etl::shared_message`.
Uses a supplied `memory_block allocator` derived from `etl::imemory_block_allocator`.
## ireference_counted_message_pool.h
Defines the following class.
`etl::ireference_counted_message_pool`
## reference_counted_message_pool.h
Defines the following classes.
`etl::reference_counted_message_pool_exception`
`etl::reference_counted_message_pool_allocation_failure`
`etl::reference_counted_message_pool_release_failure`
## ireference_counted_message_pool
```cpp
etl::ireference_counted_message_pool
```
The interface for reference counted message pools.
```cpp
virtual ~ireference_counted_message_pool() {}
```
```cpp
virtual void release(const etl::ipool_message& msg) = 0;
```
Virtual `lock()` and `unlock()` functions are defined. The default action is to do nothing.
A derived class may override these functions to provide a thread or interrupt safe pool.
`virtual void lock()`
`virtual void unlock()`
## reference_counted_message_pool
```cpp
etl::reference_counted_message_pool<TCounter>
```
The concrete reference counted message pool.
```cpp
reference_counted_message_pool(imemory_block_allocator& memory_block_allocator)
```
Constructs the pool and assigns the memory block allocator to it.
---
```cpp
template <typename TMessage>
etl::reference_counted_message<TMessage, TCounter>* allocate()
```
Returns a pointer to a pool message that holds a `TMessage`.
The message is default constructed.
ETL_ASSERT if one cannot be allocated and returns `ETL_NULLPTR`.
---
```cpp
template <typename TMessage>
etl::reference_counted_message<TMessage, TCounter>* allocate(const TMessage& message)
```
Returns a pointer to a pool message that holds a `TMessage`.
ETL_ASSERT if one cannot be allocated and returns `ETL_NULLPTR`.
---
```cpp
void release(const etl::ireference_counted_message& rcmessage)
```
Returns the reference counted to a pool message that holds a `TMessage`.
`ETL_ASSERT` if it cannot be released. Reasons can include the message not belonging to the pool.
## pool_message_parameters
**C++03**
The C++03 version defines the largest size and alignment of up to 8 types at a time.
```cpp
template <typename TMessage1, typename TMessage2 = TMessage1,
typename TMessage3 = TMessage1, typename TMessage4 = TMessage1,
typename TMessage5 = TMessage1, typename TMessage6 = TMessage1,
typename TMessage7 = TMessage1, typename TMessage8 = TMessage1>
struct pool_message_parameters
```
---
```cpp
static const size_t max_size;
```
The maximum size.
---
```cpp
static const size_t max_alignment;
```
The maximum alignment.
**C++11 or above**
The C++11 version defines the largest size and alignment of a set of message types.
```cpp
template <typename TMessage1, typename... TMessages>
struct pool_message_parameters
```
---
```cpp
static constexpr size_t max_size
```
The maximum size.
---
```cpp
static constexpr size_t max_alignment;
```
The maximum alignment.
---
**For C++11, with atomic support.**
```cpp
template <typename TObject>
using atomic_counted_message_pool = etl::reference_counted_message_pool<etl::atomic_int32_t>;
```
Defines an alias to a reference counted message pool that uses an atomic.

View File

@ -0,0 +1,197 @@
---
title: "reference_counted_message"
---
{{< callout type="info">}}
Header: `reference_counted_message.h`
{{< /callout >}}
Reference counted message types that are used by `etl::shared_message`.
**Defines the following classes**
```cpp
etl::ireference_counted_message
```
The interface of all reference counted message types.
---
```cpp
etl::reference_counted_message<typename TMessage, typename TCounter>
```
Derived from `etl::ireference_counted_message`.
```cpp
etl::persistent_message<typename TMessage>
```
Derived from `etl::ireference_counted_message`.
## ireference_counted_message
```cpp
etl::ireference_counted_message
```
The interface of all reference counted message types.
---
```cpp
virtual ~ireference_counted_message()
```
---
```cpp
ETL_NODISCARD virtual etl::imessage& get_message() = 0;
```
Get a reference to the message.
---
```cpp
ETL_NODISCARD virtual const etl::imessage& get_message() const = 0;
```
Get a const reference to the message.
---
```cpp
ETL_NODISCARD virtual etl::ireference_counter& get_reference_counter() = 0;
```
Get a reference to the reference counter.
---
```cpp
ETL_NODISCARD virtual const etl::ireference_counter& get_reference_counter() const = 0;
```
Get a const reference to the reference counter.
---
```cpp
virtual void release() = 0;
```
Release back to the owner.
## reference_counted_message
```cpp
etl::reference_counted_message<typename TMessage, typename TCounter>
```
The implementation of reference counted messages owned by a pool.
Will static assert if TMessage is no derived from etl::imessage.
---
```cpp
reference_counted_message(const TMessage& message, etl::ireference_counted_message_pool& owner)
```
Constructs from a message and the pool from which the reference counted message is allocated.
The message is copied.
---
```cpp
reference_counted_message(etl::ireference_counted_message_pool& owner)
```
Constructs from a message and the pool from which the reference counted message is allocated.
The message is default constructed.
---
```cpp
ETL_NODISCARD TMessage& get_message() ETL_OVERRIDE
```
Get a reference to the message.
---
```cpp
ETL_NODISCARD const TMessage& get_message() const ETL_OVERRIDE
```
Get a const reference to the message.
---
```cpp
ETL_NODISCARD etl::ireference_counter& get_reference_counter() ETL_OVERRIDE
```
Get a reference to the reference counter.
---
```cpp
ETL_NODISCARD const etl::ireference_counter& get_reference_counter() const ETL_OVERRIDE
```
Get a const reference to the reference counter.
---
```cpp
void release() ETL_OVERRIDE
```
Release back to the owner pool.
## persistent_message
```cpp
etl::persistent_message<typename TMessage>
```
The implementation of reference counted messages not owned by a pool.
It's counter type is `void`.
Will static assert if `TMessage` is not derived from `etl::imessage`.
---
```cpp
persistent_message(const TMessage& message)
```
Constructs from a message.
The message is copied.
---
```cpp
ETL_NODISCARD TMessage& get_message() ETL_OVERRIDE
```
Get a reference to the message.
---
```cpp
ETL_NODISCARD const TMessage& get_message() const ETL_OVERRIDE
```
Get a const reference to the message.
---
```cpp
ETL_NODISCARD etl::ireference_counter& get_reference_counter() ETL_OVERRIDE
```
Get a reference to the reference counter.
---
```cpp
ETL_NODISCARD const etl::ireference_counter& get_reference_counter() const ETL_OVERRIDE
```
Get a const reference to the reference counter.
---
```cpp
void release() ETL_OVERRIDE
```
Does nothing for a persistent message.
## For C++11, with atomic support.
```cpp
template <typename TMessage>
using atomic_counted_message = etl::reference_counted_message<TMessage, etl::atomic_int32_t>;
```
Defines an alias to a reference counted message that uses an atomic.

View File

@ -0,0 +1,79 @@
---
title: "shared_message"
weight: 2
---
{{< callout type="info">}}
Header: `shared_message.h`
{{< /callout >}}
Shared Messages
The type used to encapsulate reference counted messages.
Shared messages are usually passed by value.
See the Shared Message Tutorial
---
```cpp
template <typename TPool, typename TMessage>
shared_message(TPool& owner, const TMessage& message)
```
Static asserts if `TPool` is not derived from `etl::ireference_counted_message_pool`
Static asserts if `TMessage` not derived from `etl::imessage`.
Requires that `TPool` implements the following member function to allocate from the pool.
```cpp
template <typename TMessage>
etl::ireference_counted_message* allocate(const TMessage& message)
```
---
```cpp
explicit shared_message(etl::ireference_coutnted_message& message)
```
Construct from a reference counted message.
---
```cpp
shared_message(const etl::shared_message& other)
```
Copy constructor.
---
```cpp
shared_message& operator =(const etl::shared_message& other)
```
Assignment operator.
---
```cpp
~shared_message()
```
Destructor.
---
```cpp
ETL_NODISCARD etl::imessage& get_message()
```
Gets a reference to the contained message.
---
```cpp
ETL_NODISCARD const etl::imessage& get_message() const
```
Gets a const reference to the contained message.
---
```cpp
ETL_NODISCARD uint32_t get_reference_count() const
```
Gets the current reference count for this shared message.

View File

@ -1,6 +0,0 @@
plugins:
- jekyll-relative-links
relative_links:
enabled: true
include:
- manchester.md

131
docs/_index.md Normal file
View File

@ -0,0 +1,131 @@
---
title: "Embedded Template Library"
weight: 998
type: hextra-home
---
<div class="not-prose badges">
<div>
<img src="https://img.shields.io/github/v/release/jwellbelove/etl" alt="release">
<img src="https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3" alt="date">
<img src="https://img.shields.io/badge/c%2B%2B-98/03/11/14/17/20/23-blue.svg" alt="standard">
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="license">
<img src="https://img.shields.io/github/contributors-anon/ETLCPP/etl" alt="contributors">
<img src="https://img.shields.io/github/forks/ETLCPP/etl?style=flat" alt="forks">
<img src="https://img.shields.io/github/stars/ETLCPP/etl?style=flat" alt="stars">
</div>
<div>
<img src="https://github.com/ETLCPP/etl/actions/workflows/msvc.yml/badge.svg?branch=master" alt="CI MSVC">
</div>
<div>
<img src="https://github.com/ETLCPP/etl/actions/workflows/gcc-c++11.yml/badge.svg?branch=master" alt="CI GCC 11">
<img src="https://github.com/ETLCPP/etl/actions/workflows/gcc-c++14.yml/badge.svg?branch=master" alt="CI GCC 14">
<img src="https://github.com/ETLCPP/etl/actions/workflows/gcc-c++17.yml/badge.svg?branch=master" alt="CI GCC 17">
<img src="https://github.com/ETLCPP/etl/actions/workflows/gcc-c++20.yml/badge.svg?branch=master" alt="CI GCC 20">
<img src="https://github.com/ETLCPP/etl/actions/workflows/gcc-c++23.yml/badge.svg?branch=master" alt="CI GCC 23">
<img src="https://github.com/ETLCPP/etl/actions/workflows/gcc-syntax-checks.yml/badge.svg?branch=master" alt="CI GCC syntax">
</div>
<div>
<img src="https://github.com/ETLCPP/etl/actions/workflows/clang-c++11.yml/badge.svg?branch=master" alt="CI Clang 11">
<img src="https://github.com/ETLCPP/etl/actions/workflows/clang-c++14.yml/badge.svg?branch=master" alt="CI Clang 14">
<img src="https://github.com/ETLCPP/etl/actions/workflows/clang-c++17.yml/badge.svg?branch=master" alt="CI Clang 17">
<img src="https://github.com/ETLCPP/etl/actions/workflows/clang-c++20.yml/badge.svg?branch=master" alt="CI Clang 20">
<img src="https://github.com/ETLCPP/etl/actions/workflows/clang-c++23.yml/badge.svg?branch=master" alt="CI Clang 23">
<img src="https://github.com/ETLCPP/etl/actions/workflows/clang-syntax-checks.yml/badge.svg?branch=master" alt="CI Clang syntax">
</div>
<div>
<a href="https://github.com/ETLCPP/etl/actions/workflows/coverage.yml"><img src="https://github.com/ETLCPP/etl/actions/workflows/coverage.yml/badge.svg" alt="coverage"></a>
<a href="https://www.codacy.com/manual/jwellbelove/etl"><img src="https://api.codacy.com/project/badge/Grade/3c14cd918ccf40008d0bcd7b083d5946" alt="Codacy"></a>
</div>
<div>
<a href="https://www.etlcpp.com/sponsor.html"><img src="https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86" alt="Sponsor"></a>
</div>
</div>
## Version
This documents version **{{< version >}}**.
## Motivation
C++ is a powerful language for embedded systems development, with templates offering a great deal of flexibility and type safety. While the C++ Standard Library provides a wealth of well-tested functionality, its often not well suited to environments with strict deterministic behavior and limited resources.
In many embedded applications, dynamic memory allocation is discouraged or outright prohibited, making standard STL containers and many other components impractical or unusable.
Whats needed is a template library specifically designed for embedded systems — one that allows developers to define fixed or maximum sizes for containers and other objects at compile time. Additionally, since many older (but still in use) embedded toolchains lack full support for standards beyond C++03, it's valuable to have access to a library that backports select features from later versions of the C++ Standard Library.
## About the ETL
The Embedded Template Library (ETL) is not intended as a full replacement for the C++ Standard Template Library (STL), but rather as a complementary solution tailored specifically for embedded systems.
**Its design goals include**
- Providing a set of containers with fixed or maximum sizes defined at compile-time.
- Offering APIs that closely resemble those of the STL, enabling familiar and consistent usage.
- Maintaining compatibility with C++98 while implementing many features introduced in later standards
(C++11/14/17/20/23/26) wherever possible.
- Ensuring deterministic behavior, which is critical in real-time and resource-constrained environments.
- Introducing additional components and utilities useful in embedded contexts but absent from the STL.
- The ETL avoids dynamic memory allocation entirely; the heap is never used. All non-intrusive containers have a fixed capacity, allowing memory requirements to be fully determined at compile-time. This makes the ETL ideal for lower-resource embedded applications where predictability, performance, and memory control are essential.
The library is compatible with any compiler that supports C++03 or later.
Help on integrating the ETL with your project may be found here.
## Key Features of the ETL
- Actively Maintained: Developed and maintained on GitHub since 2014.
- Open Source: MIT licensed.
- No STL Dependency: Designed to operate independently of the C++ Standard Template Library.
- No Dynamic Memory Allocation: All storage is allocated either at compile-time or on the stack; heap usage is entirely avoided.
- RTTI and Virtual Functions: No runtime type information (RTTI) is required. Virtual functions are used sparingly and only when strictly necessary.
- Header-Only Library: All functionality is provided via header files; No separate compilation needed.
- Fixed-Capacity Containers: Offers STL-like containers with fixed or maximum capacity, plus additional non-standard container types.
- Cache Efficiency: Containers use contiguous memory layouts for optimal cache performance.
- Compact Codebase: Shared base classes (based on type) help reduce overall container code size.
- Compile-Time Features:
Templated compile-time constants
Template-based design pattern base classes (e.g., Visitor, Observer)
Type-safe smart enumerations
Type-safe typedefs and constants
- Embedded System Frameworks:
Message routing
Finite state machines
Task scheduling
- C++11 Backports:
Implements many C++11 features (type traits, algorithms, containers) for use in C++03 environments.
- Utilities:
CRC calculations (8, 16, 32 & 64-bit)
Checksums and hash functions
- Variants (type-safe unions)
- Extensive template support utilities
- Robust Error Handling: Configurable error checking using asserts, exceptions, error handlers, or no checks; users choice.
- Thoroughly Tested:
Over 10,000 unit tests
Tested with Visual Studio 2022, GCC 12, and Clang 14
Continuous integration via GitHub Actions.
- Readable and Well-Documented: Clean, maintainable source code with clear documentation.
- Support: Free email support available. A Slack group is available. Paid support on request.
- Archived: A snapshot of the ETL is preserved in the Arctic Code Vault for long-term digital preservation.
## Support the ETL
Maintaining the ETL can take a lot of man-hours of work, but unfortunately it doesn't pay the bills. When I have to take on paying work, the ETL gets a lot less attention. So if you have found the library is an important component in your work and you would like to help out, then please consider by supporting the project.
---
[**Is the ETL free?**]({{< relref "is the ETL free.md" >}})
---
Any help porting the library to work under different platforms and compilers would be gratefully received.
I am especially interested in people who are using Keil, IAR, Green Hills, TI Code Composer etc, bare metal
or RTOS, and DSPs.
Many thanks.
John.

56
docs/about.md Normal file
View File

@ -0,0 +1,56 @@
---
title: "About"
weight: 3002
---
## About me
I have been involved in technology and computer systems for all of my working life and have amassed considerable knowledge of designing and implementing systems that are both performant and correct.
My role normally encompasses the entire project life-cycle, from specification to maintenance phase.
Most systems I have worked on have required high speed and deterministic performance, often within a highly constrained platform. I am experienced in designing and adapting algorithms to solutions that are both space and time efficient, avoiding the normal overheads of standard solutions.
Acting as a mentor for colleagues has often been a significant, though unofficial, part of my role.
## Why write this library?
I wrote this library, and all the others I have written over the
years, because I'm lazy.
Yes, lazy!
One of the things I really hate when writing software is having to do the same, or something almost the same, over and over again. The first thing I think when presented with a problem that requires a specific set of functionality is "Is this a specific case of a more generic problem?". Surprisingly, I can say "yes" more often than you would expect. Even if not all of the problem can be seen as generic, there are almost certainly parts that are. In every job I've had I've left an extensive code library behind me.
Reinventing the wheel every time is a bad idea, for many reasons.
- **Compile-Time Features:**
Templated compile-time constants
Template-based design pattern base classes (e.g., Visitor, Observer)
Type-safe smart enumerations
Type-safe typedefs and constants
- **Code Bloat**
Multiple instances of slight variations of a theme results in an increase in code size due to no commonality of functionality.
Testing, more testing or no testing.
Are all the variants tested to the same degree?
Are some tested at all?
- **Variable functionality**
Not all the variants are going to have the same level of functionality, or the same API.
Ad-hoc solutions are invariably only going to solve the little bit of the problem that was needed at the time.
This goes against the YAGNI principle, but...
*I think that YAGNI can often be just another way of saying ISEP.*
*I believe in GIRFT.*
*I have over three decades of empirical proof.*
- **No collective knowledge base**
Without commonality every new variant has to be learnt. The underlying principles may be understood (i.e. Linked list), but each implementation has to be understood separately, along with its particular caveats and foibles.
Documentation is likely to be patchy, if it exists at all.
- **Octopus code**
The application is liable to have a close coupling with the solution. For example, I've often seen code using linked lists directly accessing the node pointers. Ad-hoc solutions are liable to have lazy (the bad kind) implementations.
>YAGNI - You Aren't Going To Need It
>ISEP - It's Somebody Else's Problem
>GIRFT - Get It Right First Time
## Why not use 'C'?
**Greenspun's Tenth Rule** has an unofficial C corollary:
*"Any sufficiently advanced C program contains an ad hoc, informally specified, bug-ridden, slow implementation of half of C++."*
I spent 12 years programming in pure C.
I discovered that I had been reverse engineering C++ all that time.

6
docs/binary/_index.md Normal file
View File

@ -0,0 +1,6 @@
---
title: "Binary utilities"
weight: 100
---
Classes and functions that define and manipulate binary data.

574
docs/binary/binary.md Normal file
View File

@ -0,0 +1,574 @@
---
title: binary
---
{{< callout type="info">}}
Header: `binary.h`
Since: `TBC`
{{< /callout >}}
Utility functions for manipulating binary numbers.
## Rotate
Rotate the bits in the value left or right.
```cpp
template <typename T>
ETL_CONSTEXPR14 T rotate_left(T value)
```
**Return**
`value` rotated left by one bit.
```cpp
template <typename T>
ETL_CONSTEXPR14 T rotate_left(T value, size_t distance)
```
**Return**
`value` rotated left by `distance`.
```cpp
template <typename T>
ETL_CONSTEXPR14 T rotate_right(T value)
```
**Return**
`value` rotated right by one bit.
```cpp
template <typename T>
ETL_CONSTEXPR14 T rotate_right(T value, size_t distance)
```
**Return**
`value` rotated right by `distance`.
```cpp
template <typename T>
ETL_CONSTEXPR14 T rotate(T value, typename etl::make_signed<size_t>::type distance)
```
**Parameters**
`distance` Positive is left, negative is right.
**Return**
`value` rotated left or right by `distance`.
## reverse_bits
Reverse the order of the bits in a value.
```cpp
template <typename T>
ETL_CONSTEXPR14 T reverse_bits(T value)
```
The structures below define a member constant value that is Value reversed in bits.
```cpp
template <int8_t Value>
struct reverse_bits_const<int8_t, Value>
```
```cpp
template <uint8_t Value>
struct reverse_bits_const<uint8_t, Value>
```
```cpp
template <int16_t Value>
struct reverse_bits_const<int16_t, Value>
```
```cpp
template <uint16_t Value>
struct reverse_bits_const<uint16_t, Value>
```
```cpp
template <int32_t Value>
struct reverse_bits_const<int32_t, Value>
```
```cpp
template <uint32_t Value>
struct reverse_bits_const<uint32_t, Value>
```
```cpp
template <int64_t Value>
struct reverse_bits_const<int64_t, Value>
```
```cpp
template <uint64_t Value>
struct reverse_bits_const<uint64_t, Value>
```
Defines `value` The reversed bits.
## reverse_bytes
Reverse the order of the bytes in a value.
```cpp
template <typename T>
ETL_CONSTEXPR14 T reverse_bytes(T value)
```
## gray_to_binary
```cpp
template <typename T>
ETL_CONSTEXPR14 T gray_to_binary(T value)
```
Converts a gray code value to binary.
## binary_to_gray
```cpp
template <typename T>
ETL_CONSTEXPR T binary_to_gray(T value)
```
Converts a binary value to the gray code equivalent.
## count_bits
```cpp
template <typename T>
ETL_CONSTEXPR14 uint_least8_t count_bits(T value)
```
**Return**
The number of set bits in `value`.
## parity
```cpp
template <typename T>
ETL_CONSTEXPR14 uint_least8_t parity(T value)
```
**Return**
`1` if the parity of the value is odd, `0` if it is even.
## max_value_for_nbits
```cpp
template <size_t NBits>
struct max_value_for_nbits
```
**Return**
Maximum unsigned value a particular number of bits can represent.
`value_type` The type for the value.
`value` The maximum value.
## fold_bits
```cpp
template <typename TReturn, size_t NBits, typename TValue>
ETL_CONSTEXPR14 TReturn fold_bits(TValue value)
```
**Description**
Fold a binary number down to a set number of bits using XOR.
**Example**
`0xE8C9AACCBC3D9A8F` folded down to 20 bits = `0x998E8`
```cpp
uint32_t result = etl::fold_bits<uint32_t, 20>(0xE8C9AACCBC3D9A8F);
```
## sign_extend
Sign extends a binary number.
```cpp
template <typename TReturn, size_t NBits, typename TValue>
ETL_CONSTEXPR14 TReturn sign_extend(TValue value)
```
**Description**
Converts an N bit binary number, where bit N-1 is the sign bit, to a signed integral type.
---
```cpp
template <typename TReturn, size_t NBits, size_t Shift, typename TValue>
ETL_CONSTEXPR14 TReturn sign_extend(TValue value)
```
**Description**
Converts an N bit binary number, where bit N-1 is the sign bit, and `Shift` is the right shift amount, to a signed integral type.
---
```cpp
template <typename TReturn, typename TValue>
ETL_CONSTEXPR14 TReturn sign_extend(TValue value, size_t nbits)
```
**Description**
Converts an N bit binary number, where bit N-1 is the sign bit, to a signed integral type.
---
```cpp
template <typename TReturn, typename TValue>
ETL_CONSTEXPR14 TReturn sign_extend(TValue value, size_t nbits, size_t shift)
```
**Description**
Converts an N bit binary number, where bit N-1 is the sign bit, and shift is the right shift amount, to a signed integral type.
## count_leading_zeros
```cpp
template <typename T>
ETL_CONSTEXPR14 uint_least8_t count_leading_zeros(T value)
```
**Description**
Counts the number of leading zeros in a binary number
## count_trailing_zeros
```cpp
template <typename T>
ETL_CONSTEXPR14 uint_least8_t count_trailing_zeros(T value)
```
**Description**
Counts the number of trailing zeros in a binary number
## count_leading_ones
```cpp
template <typename T>
ETL_CONSTEXPR14 uint_least8_t count_leading_ones(T value)
```
**Description**
Counts the number of leading ones in a binary number
## count_trailing_ones
```cpp
template <typename T>
ETL_CONSTEXPR14 uint_least8_t count_trailing_ones(T value)
```
**Description**
Counts the number of trailing ones in a binary number
## first_set_bit_position
```cpp
template <typename T>
ETL_CONSTEXPR14 uint_least8_t first_set_bit_position(T value)
```
**Description**
Finds the index of the first set bit from lsb.
## first_clear_bit_position
```cpp
template <typename T>
ETL_CONSTEXPR14 uint_least8_t first_clear_bit_position(T value)
```
**Description**
Finds the index of the first clear bit from lsb.
## first_bit_position
```cpp
template <typename T>
ETL_CONSTEXPR14 uint_least8_t first_bit_position(bool state, T value)
```
**Description**
Finds the index of the first bit in the specified state, from lsb.
## binary_fill
```cpp
template <typename TResult, typename TValue>
ETL_CONSTEXPR TResult binary_fill(TValue value)
```
Fills a value of the specified width with a repeating binary pattern.
*Run time*
Generate `0x12121212`
```cpp
etl::binary_fill<uint32_t>(uint8_t(0x12));
```
---
```cpp
template <typename TResult, typename TValue, TValue Value>
ETL_CONSTEXPR TResult binary_fill()
```
*Partial compile time*
Generate `0x12121212`
```cpp
etl::binary_fill<uint32_t, uint8_t, 0x12>();
```
## has_zero_byte
```cpp
template <typename TValue>
ETL_CONSTEXPR14 bool has_zero_byte(TValue value)
```
*Run time*
Checks to see if a value contains a byte of value zero.
**Example**
`etl::has_zero_byte(uint32_t(0x01234567)) == false`
`etl::has_zero_byte(uint32_t(0x01230067)) == true`
---
```cpp
template <typename TValue, TValue Value>
ETL_CONSTEXPR14 bool has_zero_byte()
```
Checks to see if `Value` contains a byte of value zero.
*Compile time value*
## has_byte_n
Checks to see if a value contains a byte of a particular value.
```cpp
template <typename TValue>
ETL_CONSTEXPR14 bool has_byte_n(TValue value, uint8_t n)
```
*Run time*
```cpp
etl::has_byte_n(uint32_t(0x01234567), 0x12) == false
etl::has_byte_n(uint32_t(0x01234567), 0x45) == true
```
---
```cpp
template <typename TValue, TValue Value>
ETL_CONSTEXPR14 bool has_byte_n(TValue value)
```
*Partial compile time*
```cpp
etl::has_byte_n<0x12>(uint32_t(0x01234567)) == false
etl::has_byte_n<0x45>(uint32_t(0x01234567)) == true
```
## binary_merge
Merges two binary values according to a mask.
Bits set in the mask select bits in the first value, clear bits select those in the second.
```cpp
template <typename T>
ETL_CONSTEXPR T binary_merge(T first, T second, T mask)
```
```cpp
uint8_t first = 0x12;
uint8_t second = 0x34;
const uint8_t mask = 0xF0;
etl::binary_merge(first, second, mask) Equals 0x14
```
---
```cpp
template <typename T, T Mask>
ETL_CONSTEXPR T binary_merge(T first, T second)
```
```cpp
uint8_t first = 0x12;
uint8_t second = 0x34;
const uint8_t mask = 0xF0;
etl::binary_merge<uint8_t, mask>(first, second) Equals 0x14
```
## binary_interleave
Interleaves two values such that bits abcd and efgh will result in eafbgchd.
```cpp
ETL_CONSTEXPR14 uint16_t binary_interleave(uint8_t first, uint8_t second);
ETL_CONSTEXPR14 uint32_t binary_interleave(uint16_t first, uint16_t second);
ETL_CONSTEXPR14 uint64_t binary_interleave(uint32_t first, uint32_t second);
```
## Odd / Even
Determines the odd or evenness of a value.
```cpp
template <typename T>
ETL_CONSTEXPR bool is_odd(T value)
```
```cpp
template <typename T>
ETL_CONSTEXPR bool is_even(T value)
```
## Constants
```cpp
enum binary_constant
```
An enumeration of 256 constants from `b00000000` to `b11111111` (`0` to `255`)
---
```cpp
enum bit_constant
```
An enumeration of 32 constants from `b0` to `b31` (`1` to `4294967296`)
---
```cpp
template <size_t Position>
struct bit
```
`value_type` The type of the value.
`value` The value of the bit at `Position`.
## Creating bit masks
These classes and constexpr functions help create lsb and msb masks.
```cpp
template <typename T, size_t NBits>
class lsb_mask;
```
Defines the member constant value as a binary value of NBits `1` shift to the LSB.
e.g. `lsb_mask<int8_t, 3>::value == 0b00000111`
From: `20.34.0`
---
```cpp
template <typename T>
ETL_CONSTEXPR T make_lsb_mask(size_t nbits)
```
Returns a binary value of nbits `1` shift to the LSB.
e.g. `make_lsb_mask<int8_t>(3) == 0b00000111`
From: `20.34.0`
---
```cpp
template <typename T, size_t NBits>
ETL_CONSTEXPR T make_lsb_mask()
```
**Description**
Returns a binary value of nbits `1` shift to the LSB.
e.g. `make_lsb_mask<int8_t, 3>() == 0b00000111`
From: `20.38.7`
---
```cpp
template <typename T, size_t NBits>
class msb_mask;
```
**Return**
A binary value of nbits `1` shift to the MSB.
e.g. `msb_mask<int8_t, 3>::value == 0b11100000`
From: `20.34.0`
---
```cpp
template <typename T>
ETL_CONSTEXPR T make_msb_mask(size_t nbits)
```
**Description**
Defines the member constant value as a binary value of NBits `1` shift to the MSB.
e.g. `make_msb_mask<int8_t>(3) == 0b11100000`
20.34.0
---
```cpp
template <typename T, size_t NBits>
ETL_CONSTEXPR T make_msb_mask()
```
**Description**
Defines the member constant value as a binary value of NBits `1` shift to the MSB.
e.g. `make_msb_mask<int8_t, 3>() == 0b11100000`
From: `20.38.7`
## Bit manipulation functors
These functors are most useful where lambdas are not available.
## binary_not
```cpp
template <typename T>
struct binary_not : public etl::unary_function<T, T>;
```
From: `20.38.11`
---
```cpp
ETL_CONSTEXPR
binary_not()
```
**Description**
Default constructor.
---
```cpp
ETL_CONSTEXPR
ETL_NODISCARD
T operator()(T value) const ETL_NOEXCEPT
```
**Return**
~value.
## binary_and
```cpp
template <typename T>
struct binary_and : public etl::unary_function<T, T>;
```
From: `20.38.11`
---
```cpp
ETL_CONSTEXPR
explicit binary_and(T and_value)
```
**Description**
Constructor.
---
```cpp
ETL_CONSTEXPR
ETL_NODISCARD
T operator()(T value) const ETL_NOEXCEPT
```
**Return**
`value & and_value`.
## binary_or
```cpp
template <typename T>
struct binary_or : public etl::unary_function<T, T>;
```
From: `20.38.11`
---
```cpp
ETL_CONSTEXPR
explicit binary_or(T or_value)
```
**Description**
Constructor.
---
```cpp
ETL_CONSTEXPR
ETL_NODISCARD
T operator()(T value) const ETL_NOEXCEPT
```
**Return**
`value | or_value`.
## binary_xor
```cpp
template <typename T>
struct binary_xor : public etl::unary_function<T, T>;
```
From: `20.38.11`
---
```cpp
ETL_CONSTEXPR
explicit binary_xor(T xor_value)
```
**Description**
Constructor.
---
```cpp
ETL_CONSTEXPR
ETL_NODISCARD
T operator()(T value) const ETL_NOEXCEPT
```
**Return**
value ^ xor_value.

117
docs/binary/bit.md Normal file
View File

@ -0,0 +1,117 @@
---
title: "bit"
---
{{< callout type="info">}}
Header: `bit.h`
Since: `TBC`
Similar to: [STL bit header](https://en.cppreference.com/cpp/header/bit)
{{< /callout >}}
Utility functions for manipulating binary numbers.
A reverse engineered version of C++20's and C++23's `<bit>` header.
## bit_cast
```cpp
template <typename TDestination, typename TSource>
ETL_CONSTEXPR14 TDestination bit_cast(const TSource& source) ETL_NOEXCEPT
```
**Description**
Returns a value of type `TDestination` by reinterpreting the `TSource` object.
## byteswap
```cpp
template <typename T>
ETL_CONSTEXPR14 T byteswap(T n) ETL_NOEXCEPT
```
**Description**
Reverses the bytes in `n`.
## has_single_bit
```cpp
template <typename T>
ETL_CONSTEXPR14 bool has_single_bit(T n) ETL_NOEXCEPT
```
**Description**
Checks if `n` is a power of two, or has one bit set.
## bit_ceil
```cpp
template <typename T>
ETL_CONSTEXPR14 T bit_ceil(T n)
```
**Description**
Calculates the smallest power of two, that is not smaller than `n`.
## bit_floor
```cpp
template <typename T>
ETL_CONSTEXPR14 T bit_floor(T n) ETL_NOEXCEPT
```
**Description**
Calculates the largest power of two that is not greater than `n`.
## bit_width
```cpp
template <typename T>
ETL_CONSTEXPR14 T bit_width(T n) ETL_NOEXCEPT
```
**Description**
If `n` is not `0`, calculates the number of bits needed to store it.
If `n` is `0`, then the result is `0`.
## rotl
```cpp
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 T rotl(T value, int n) ETL_NOEXCEPT
```
**Description**
Computes a left circular shift of value by `n`.
## rotr
```cpp
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 T rotr(T value, int n) ETL_NOEXCEPT
```
**Description**
Computes a right circular shift of value by `n`.
## countl_zero
```cpp
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 int countl_zero(T value) ETL_NOEXCEPT
```
**Description**
Returns the number of consecutive `0` bits in `n`, starting from the most significant bit (left).
## countl_one
```cpp
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 int countl_one(T value) ETL_NOEXCEPT
```
**Description**
Returns the number of consecutive `1` bits in `n`, starting from the most significant bit (left).
## countr_zero
```cpp
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 int countr_zero(T value) ETL_NOEXCEPT
```
**Description**
Returns the number of consecutive `0` bits in `n`, starting from the least significant bit (right).
## countr_one
```cpp
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 int countr_one(T value) ETL_NOEXCEPT
```
**Description**
Returns the number of consecutive `1` bits in `n`, starting from the least significant bit (right).
## popcount
```cpp
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 int popcount(T value) ETL_NOEXCEPT
```
**Description**
Counts the number of `1` bits in an unsigned integer.

149
docs/binary/byte.md Normal file
View File

@ -0,0 +1,149 @@
---
title: "byte"
---
{{< callout type="info">}}
Header: `byte.h`
From: `20.24.0`
Similar to: [std::byte](https://en.cppreference.com/cpp/types/byte)
{{< /callout >}}
A type that implements the concept of byte
**C++03**
Implemented as a class.
Cannot be cast using `static_cast`.
**C++11 or above**
Implemented as enum class.
All functions are `constexpr`.
## Constructors
```cpp
byte()
```
**Description**
Constructs a default initialised byte.
C++03
---
```cpp
template <typename T>
explicit byte(T v)
```
Constructs a byte initialised to `v`.
## Non-member functions
```cpp
template <typename TInteger>
constexpr TInteger to_integer(etl::byte b) noexcept
```
**Description**
Converts to an integral type.
`constexpr` and `noexcept` for C++11 and above.
---
```cpp
template <typename TInteger>
constexpr etl::byte operator <<(etl::byte b, TInteger shift) noexcept
```
**Description**
Shifts the value of the byte to the left and returns the new byte.
`constexpr` and `noexcept` for C++11 and above.
---
```cpp
template <typename TInteger>
constexpr etl::byte operator >>(etl::byte b, TInteger shift) noexcept
```
**Description**
Shifts the value of the byte to the right and returns the new byte.
`constexpr` and `noexcept` for C++11 and above.
---
```cpp
template <typename TInteger>
constexpr etl::byte& operator <<=(etl::byte& b, TInteger shift) noexcept
```
**Description**
Shifts the value of the byte to the left and returns a reference to the byte.
`constexpr` and `noexcept` for C++11 and above.
---
```cpp
template <typename TInteger>
constexpr etl::byte& operator >>=(etl::byte& b, TInteger shift) noexcept
```
**Description**
Shifts the value of the byte to the right and returns a reference to the byte.
`constexpr` and `noexcept` for C++11 and above.
---
```cpp
constexpr etl::byte operator |(etl::byte lhs, etl::byte rhs) noexcept
```
ORs the two bytes returns the new byte.
`constexpr` and `noexcept` for C++11 and above.
---
```cpp
constexpr etl::byte operator &(etl::byte lhs, etl::byte rhs) noexcept
```
**Description**
ANDs the two bytes returns the new byte.
`constexpr` and `noexcept` for C++11 and above.
---
```cpp
constexpr etl::byte operator ^(etl::byte lhs, etl::byte rhs) noexcept
```
**Description**
Exclusive ORs the two bytes returns the new byte.
`constexpr` and `noexcept` for C++11 and above.
---
```cpp
constexpr etl::byte& operator |=(etl::byte& lhs, etl::byte rhs) noexcept
```
**Description**
ORs the two bytes returns and a reference to the first parameter.
`constexpr` for C++14 and above.
`noexcept` for C++11 and above.
---
```cpp
constexpr etl::byte& operator &=(etl::byte& lhs, etl::byte rhs) noexcept
```
**Description**
ANDs the two bytes returns and a reference to the first parameter.
`constexpr` for C++14 and above.
`noexcept` for C++11 and above.
---
```cpp
constexpr etl::byte& operator ^=(etl::byte& lhs, etl::byte rhs) noexcept
```
**Description**
Exclusive ORs the two bytes and returns a reference to the first parameter.
`constexpr` for C++14 and above.
`noexcept` for C++11 and above.
---
```cpp
constexpr etl::byte operator ~(etl::byte b) noexcept
```
**Description**
Negates the value of the byte and returns the new value.
`constexpr` and `noexcept` for C++11 and above.

144
docs/binary/flags.md Normal file
View File

@ -0,0 +1,144 @@
---
title: "flags"
---
{{< callout type="info">}}
Header: `flags.h`
Since: `TBC`
{{< /callout >}}
Provides a wrapper around a set of binary flags.
Supports compile time and runtime variants
```cpp
template <typename T, T MASK = etl::integral_limits<T>::max>
class flags
```
`T` must be an unsigned integral type.
`MASK` is used to exclude unused or undefined bits from operations of the flags. By default, all bits are included.
Most member functions may be chained.
```cpp
bool isF5Set = flags.set(bitPattern, true).flip().test(F5);
```
## Constructor
```cpp
ETL_CONSTEXPR flags() ETL_NOEXCEPT
```
**Description**
Constructs a flag set with all elements set to `0` (`false`).
---
```cpp
ETL_CONSTEXPR flags(value_type pattern) ETL_NOEXCEPT
```
**Description**
Constructs a flag set with elements set to pattern.
---
```cpp
ETL_CONSTEXPR flags(const flags<T, MASK>& pattern) ETL_NOEXCEPT
```
**Description**
Constructs a flag set with elements set to pattern.
## Modifiers
```cpp
ETL_CONSTEXPR14 flags<T, MASK>& operator=(flags<T, MASK> other) ETL_NOEXCEPT
```
**Description**
Assigns from another flags object.
---
```cpp
ETL_CONSTEXPR14 flags<T, MASK>& operator=(value_type pattern) ETL_NOEXCEPT
```
**Description**
Assigns from a bit pattern.
---
```cpp
template <value_type pattern, bool value>
ETL_CONSTEXPR14 flags<T, MASK>& set() ETL_NOEXCEPT
```
---
```cpp
template <value_type pattern>
ETL_CONSTEXPR14 flags<T, MASK>& set(bool value) ETL_NOEXCEPT
```
---
```cpp
template <value_type pattern>
ETL_CONSTEXPR14 flags<T, MASK>& set() ETL_NOEXCEPT
```
---
```cpp
ETL_CONSTEXPR14 flags<T, MASK>& set(value_type pattern) ETL_NOEXCEPT
```
---
```cpp
ETL_CONSTEXPR14 flags<T, MASK>& set(value_type pattern, bool value) ETL_NOEXCEPT
```
---
```cpp
ETL_CONSTEXPR14 flags<T, MASK>& clear() ETL_NOEXCEPT
```
____________________________________________________________________________________________________
template <value_type pattern>
ETL_CONSTEXPR14 flags<T, MASK>& reset() ETL_NOEXCEPT
____________________________________________________________________________________________________
ETL_CONSTEXPR14 flags<T, MASK>& reset(value_type pattern) ETL_NOEXCEPT
____________________________________________________________________________________________________
ETL_CONSTEXPR14 flags<T, MASK>& flip() ETL_NOEXCEPT
____________________________________________________________________________________________________
template <value_type pattern>
ETL_CONSTEXPR14 flags<T, MASK>& flip() ETL_NOEXCEPT
____________________________________________________________________________________________________
ETL_CONSTEXPR14 flags<T, MASK>& flip(value_type pattern) ETL_NOEXCEPT
____________________________________________________________________________________________________
Access
template <value_type pattern>
ETL_CONSTEXPR bool test() const ETL_NOEXCEPT
Test the bits for the compile time pattern.
____________________________________________________________________________________________________
ETL_CONSTEXPR bool test(value_type pattern) const ETL_NOEXCEPT
Test the bits for the run time pattern.
____________________________________________________________________________________________________
ETL_CONSTEXPR value_type value() const ETL_NOEXCEPT
ETL_CONSTEXPR operator value_type() const ETL_NOEXCEPT
Returns the value of the flags as a value_type.
____________________________________________________________________________________________________
Operations
____________________________________________________________________________________________________
Non-member functions
template <typename T, T MASK>
void swap(flags<T, MASK>& lhs, flags<T, MASK>& rhs)
Swaps two flags.
template <typename T, T MASK>
bool operator == (flags<T, MASK>& lhs, flags<T, MASK>& rhs)
Checks equality of two flags.
template <typename T, T MASK>
bool operator != (flags<T, MASK>& lhs, flags<T, MASK>& rhs)
Checks inequality of two flags.

15
docs/blog/_index.md Normal file
View File

@ -0,0 +1,15 @@
---
title: "Blog"
weight: 3001
---
## Graphics
[Determining line-line intersections]({{% relref "./graphics/determining-line-line-intersections.md" %}})
[Applications of dot and cross products]({{% relref "./graphics/applications-of-dot-and-cross-products.md" %}})
[Scanning an arbitrarily rotated rectangular region]({{% relref "./graphics/scanning-an-arbitrarily-rotated-rectangular-region.md" %}})
## Algorithms
[Implementing a low cost moving average]({{% relref "implementing-a-low-cost-moving-average.md" %}})

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,5 @@
---
title: "Graphics"
weight: 1
---

View File

@ -0,0 +1,71 @@
---
title: "Applications of dot and cross products"
weight: 5
---
**Author:** John Wellbelove
**Date:** 2019
## The problem
Sometimes in graphical applications there is a need to know the relative position of a point with respect to a line from a reference point.
Where is the target in relation to the reference and its direction?
Dot and cross products can make this an easy task.
Let's start with a reminder of what dot and cross products are.
Take two vectors `x1,y1` and `x2,y2`
The dot product is `(x1 * x2) + (y1 * y2)` and the cross product is `(x1 * y2) - (x2 * y1)`.
Remember that the dot product is a scalar based on `cos(θ)` and the cross product is a scalar based on `sin(θ)`.
**Example**
![DotCross1](images/DotCross1.png)
We have a reference object at `Xr,Yr` facing in the direction of the arrow.
The target is at point `Xt,Yt`
![DotCross3](images/DotCross3.png)
A arbitrary point on the line from the reference in the specified direction is `Xw,Yw`
First, find the coordinates of the target and waypoint relative to the reference.
`dXw = Xw - Xr`
`dYw = Yw - Yr`
`dXt = Xt - Xr`
`dYt = Yt - Yr`
Now find the dot and cross products of these vectors.
`Dot = (dXw * dXt) + (dYw * dYt)`
`Cross = (dXw * dYt) - (dXt * dYw)`
The absolute values of the dot and cross products is unimportant, we just need the *sign*.
`Dot > 0`, `Cross < 0` : The target is forward of the reference and to the right.
`Dot > 0`, `Cross > 0` : The target is forward of the reference and to the left.
`Dot < 0`, `Cross < 0` : The target is behind the reference and to the right.
`Dot < 0`, `Cross > 0` : The target is behind the reference and to the left.
*forward*, *behind*, *left*, and *right* are relative to the reference's direction.
This calculation will be valid for any direction.
## Other uses
This technique can also be used to determine if a point is within a closed convex hull.
![DotCross4](images/DotCross4.png)
A closed convex hull defined by the lines `L1`, `L2`, `L3`, `L4`, and `L5`.
Point `P1` is inside the hull, point `P2` is outside.
For `P1`, the cross product for all of the lines will indicate that it is to the *right* and therefore, *must* be inside.
For `P2`, the cross product for `L1` will put it on the *left* hand side and therefore it *cannot* be inside the hull.
**Why does this work?**
The dot product of vectors `A` and `B` is `|A||B|cos(Ø)`
The cross product of vectors `A` and `B` is `|A||B|sin(Ø)`
Where `Ø` is the angle between the vectors `A` and `B`. Range `+-180°`
Therefore the sign of the result indicates the quadrant that target occupies in the circle around the reference, relative to the reference's direction.

View File

@ -0,0 +1,115 @@
---
title: "Determining line-line intersections"
weight: 2
---
**Author:** John Wellbelove
**Date:** 2019
It's quite common in graphics and image processing to want to know the intersection coordinates of two lines.
The common formula for a line is the familiar `y = Mx + C`.
But there is another that can be a lot easier to use when determining line to line intersections in a graphical environment.
## The issues
When using `y = Mx + C` you must be aware of the situations of when the line approaches 'vertical'.
In this case `M` tends towards infinity, which is not good in a programming environment.
The usual trick is to flip the coordinates when the slope is more than 1, and then flip back after the calculations have been made.
This can be confusing to follow and result in errors.
Also, to keep any accuracy, the calculations must normally be kept in the floating point domain, which is not ideal for performance, as the image will be in integral pixel coordinates.
## The solution
Change the definition of your lines to use the formula `Ax + By = C`.
Ideally, your lines would already be in the form `Ax + By = C`, but this is not normally the case, but we *can* easily generate the parameters from two points.
Assume we have a line defined by `(x1, y1)` and `(x2, y2)`.
We can deduce `A`, `B`, and `C` thus:
`A = y2 - y1`
`B = x1 - x2`
`C = Ax1`+ `By1`
---
Another useful calculation is the *determinant*.
Given two lines `A1x + B1y = C1` and `A2x + B2y = C2`:
`determinant = A1 * B2 - A2 * B1`
If `determinant` is zero, then the lines are parallel.
### Notes
- If `A` and `B` are both non-zero.
The equation represents a diagonal line.
- If `A == 0`, `B != 0`.
The line is the parallel to the x-axis.
- If `A != 0`, `B == 0`.
The line is the parallel to the y-axis.
- If `C == 0`
The line passes through the origin.
## Calculating the intersection
The intersection point is calculated like this:
Given two lines described by the points `(x1, y1)`, `(x2, y2)`, and `(x3, y3)`, `(x4, y4)`.
![LineCross1](images/LineCross1.png)
- Calculate the parameters `A`, `B`, and `C` for each.
`A1x + B1y = C1` and `A2x + B2y = C2`
- Calculate the determinant.
`determinant = A1 * B2 - A2 * B1`
- If `determinant == 0` then the lines are parallel, and there is no intersection point.
- Otherwise
`x = (B2 * C1 - B1 * C2) / determinant`
`y = (A1 * C2 - A2 * C1) / determinant`
## They don't need to physically intersect
The intersection point can be found even if the line segments aren't actually long enough to intersect.
The calculation will effectively extend them to where they *would* intersect, if long enough.
This means you can find intersection points relative to a fixed reference line.
![LineCross2](images/LineCross2.png)
## Refection
This describes reflecting a point across a reference line.
It uses the intersection method described above.
In the example below, we want to reflect `P` in the line `Reference`, to give us `P'`.
![Reflection1](images/Reflection1.png)
First, we need the reference line in the form `Ax + By = C`.
Next, we need to find the perpendicular from `Reference` through `P`.
Any line perpendicular to `Ax + By = C` takes the form `Bx + Ay = D`.
To find `D`, just substitute the `x,y` coordinates from `P`.
Now we have the two lines in the form we require to find the intersection.
Find `I`, which is the intersection of the reference line and the perpendicular to `P`.
Compute `P'` by using the formula `P' = I + (I - P)`.
This calculates the vector from `P` to `I` and then adds it to `I` to move the same amount again.
## Line to point distance
The above technique can be used to find the distance of a point to a reference line.
This distance is merely the absolute length of the vector `I - P`.

View File

@ -0,0 +1,26 @@
---
title: "Dot and cross products"
weight: 4
---
**Author:** John Wellbelove
**Date:** 2019
## Dot Product
The dot product of two vectors is the sum of the products of the corresponding elements.
The dot product of vectors `(x1, y1)` and `(x2, y2)` is `x1 * x2 + y1 * y2`.
If `A` & `B` are vectors, the dot product is `|A||B|cos(θ)`, where `θ` is the angle between the `A` and `B`.
`|A|` is the length of the vector `A`.
`|B|` is the length of the vector `B`.
Therefore, we can calculate `cos(θ) = (A ⋅ B)/(|A||B|)`.
A dot product of `0` indicates two perpendicular lines, and the dot product is greatest when the lines are parallel.
## Cross Product
The cross product of vectors `(x1, y1)` and `(x2, y2)` is `x1 * y2 - y1 * x2`
If `A` & `B` are vectors, the cross product is `|A||B|sin(θ)`.
`|θ|` is the angle between the two vectors, but `θ` can be positive or negative.
Therefore, we can calculate `sin(θ) = (A x B)/(|A||B|)`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -0,0 +1,41 @@
---
title: "Scanning an arbitrarily rotated rectangular region"
weight: 3
---
**Author:** John Wellbelove
**Date:** 2019
Quite often in image processing we need to scan a rectangular region in an image. The region is usually aligned to capture a specific feature in the image.
You may be presented with a skewed image, necessitating that the region should also be skewed.
![ScanRectangle1](images/ScanRectangle1.png)
If it is not absolutely necessary to scan the region at the angle of skew, then the fastest way to interrogate the pixels is to scan the image horizontally.
As was shown in the previous post, the crossing points between two lines can be easily and efficiently determined.
By moving a reference line down across the region, the start and end x coordinates of each scan line can be found.
Only the y coordinate of the reference line is relevant, though it must have a length of at least 1 unit.
Of course, we must check every line in the rectangle, and every line in the rectangle may produce a crossing point.
The reference line shown below will identify points `P1`, `P2`, `P3` and `P4` as valid crossing points.
![ScanRectangle4](images/ScanRectangle4.png)
The solution is to compare the crossing coordinates against the bounds of the enclosing rectangle.
![ScanRectangle5](images/ScanRectangle5.png)
This would eliminate points `P1` and `P4`.
![ScanRectangle2](images/ScanRectangle2.png)
This can be done for all scan lines in the bounded rectangle.
![ScanRectangle6](images/ScanRectangle6.png)
Vertical scans may be easily achieved by simply having a vertical reference line.
This technique can be applied to any convex hull.

View File

@ -0,0 +1,70 @@
---
title: "Implementing a moving average"
weight: 10
author: John Wellbelove
---
**Author:** John Wellbelove
**Date:** 2019
## Example
Imagine we have accumulated 10 values and our window size is 10.
`[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]`
The average of this sequence is `(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10) / 10 = 5.5`
We now add a new sample, `11` to the sequence. As the windows size is 10, we drop the first value.
`[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]`
The average of this sequence is `(2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11) / 10 = 6.5`
Now, averaging over 10 samples each time is not that big an issue, but what if it's 1000 or 10,000? Then, the overhead, both in processing time and storage has started to become a little excessive.
In the case of 10,000 samples of 'double' we are looking at 10,000 additions + 1 division each time a sample is added and a likely storage requirement of 80,000 bytes!
So we have an algorithm that has processing and storage complexity of O(N).
## What other values give the same average?
**So let's look at the problem again.**
There are many ways of getting the same average:
`[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]` = Average of `5.5`
`[ 7, 7, 7, 7, 7, 4, 4, 4, 4, 4 ]` = Average of `5.5`
---
**But what about this?**
`[ 5.5, 5.5 , 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5 ]` = Average of `5.5`
An average of `5.5` can be got from 10 samples of `5.5`.
## So why store 10 samples?
We can simply simulate the original sum just by multiplying the current average by the number of samples.
The calculation of the average for adding a new sample becomes this:
`(Old_Average * Sample_Size) + New_Sample) / (Sample_Size + 1)`
Now we have 1 multiplication, 2 additions and 1 division.
Our algorithm now has a complexity of O(1).
We can average over as large a sample size as we like and it will always take the same amount of time and use the same amount of storage. We can also change the sample size on-the-fly if we wish.
There is one downside in that the average will not exactly match the original version, as the actual oldest value is not being erased from the sum, but for the performance and storage advantages it may be a perfectly suitable solution.
You may find that you will need a slightly smaller sample size with the rolling mean to get similar results.
---
**Note**
The multiplication may be elided by re-arranging the formula.
`Old_Average + ((New_Sample - Old_Average) / (Sample_Size + 1))`
This may produce a *negative* interim value, which may be a problem if you are using scaled unsigned integral types for the average value.
---
The ETL has an implementation of this algorithm.
[pseudo_moving_average]({{% relref "../maths/pseudo_moving_average.md" %}})

Some files were not shown because too many files have changed in this diff Show More