diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 00000000..22cc390f --- /dev/null +++ b/.bazelrc @@ -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 diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 00000000..f9c71a52 --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +8.5.1 diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..59753925 --- /dev/null +++ b/.clang-tidy @@ -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: '' +... diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index f51b1a16..2e08080a 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -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: " \ diff --git a/.devcontainer/armhf/Dockerfile b/.devcontainer/armhf/Dockerfile new file mode 100644 index 00000000..a6f866df --- /dev/null +++ b/.devcontainer/armhf/Dockerfile @@ -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"] diff --git a/.devcontainer/armhf/devcontainer.json b/.devcontainer/armhf/devcontainer.json new file mode 100644 index 00000000..a1dc285e --- /dev/null +++ b/.devcontainer/armhf/devcontainer.json @@ -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" +} diff --git a/.devcontainer/armhf/toolchain-armhf.cmake b/.devcontainer/armhf/toolchain-armhf.cmake new file mode 100644 index 00000000..a7f9f00a --- /dev/null +++ b/.devcontainer/armhf/toolchain-armhf.cmake @@ -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") diff --git a/.devcontainer/context/reinstall-cmake.sh b/.devcontainer/context/reinstall-cmake.sh deleted file mode 100644 index 280d8145..00000000 --- a/.devcontainer/context/reinstall-cmake.sh +++ /dev/null @@ -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 ' /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 \ No newline at end of file diff --git a/.devcontainer/i386/Dockerfile b/.devcontainer/i386/Dockerfile new file mode 100644 index 00000000..b879ee00 --- /dev/null +++ b/.devcontainer/i386/Dockerfile @@ -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"] diff --git a/.devcontainer/i386/devcontainer.json b/.devcontainer/i386/devcontainer.json new file mode 100644 index 00000000..84e28a8e --- /dev/null +++ b/.devcontainer/i386/devcontainer.json @@ -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" +} diff --git a/.devcontainer/i386/toolchain-i386.cmake b/.devcontainer/i386/toolchain-i386.cmake new file mode 100644 index 00000000..502e2285 --- /dev/null +++ b/.devcontainer/i386/toolchain-i386.cmake @@ -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") diff --git a/.devcontainer/powerpc/Dockerfile b/.devcontainer/powerpc/Dockerfile new file mode 100644 index 00000000..a2442782 --- /dev/null +++ b/.devcontainer/powerpc/Dockerfile @@ -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 < /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 < /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"] diff --git a/.devcontainer/powerpc/devcontainer.json b/.devcontainer/powerpc/devcontainer.json new file mode 100644 index 00000000..1d7a9a05 --- /dev/null +++ b/.devcontainer/powerpc/devcontainer.json @@ -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" +} diff --git a/.devcontainer/powerpc/toolchain-powerpc.cmake b/.devcontainer/powerpc/toolchain-powerpc.cmake new file mode 100644 index 00000000..1afea7da --- /dev/null +++ b/.devcontainer/powerpc/toolchain-powerpc.cmake @@ -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") diff --git a/.devcontainer/riscv64/Dockerfile b/.devcontainer/riscv64/Dockerfile new file mode 100644 index 00000000..90a95a4c --- /dev/null +++ b/.devcontainer/riscv64/Dockerfile @@ -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"] diff --git a/.devcontainer/riscv64/devcontainer.json b/.devcontainer/riscv64/devcontainer.json new file mode 100644 index 00000000..0e673f24 --- /dev/null +++ b/.devcontainer/riscv64/devcontainer.json @@ -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" +} diff --git a/.devcontainer/riscv64/toolchain-riscv64.cmake b/.devcontainer/riscv64/toolchain-riscv64.cmake new file mode 100644 index 00000000..adc1c7f3 --- /dev/null +++ b/.devcontainer/riscv64/toolchain-riscv64.cmake @@ -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") diff --git a/.devcontainer/run-tests.sh b/.devcontainer/run-tests.sh new file mode 100755 index 00000000..9618a15b --- /dev/null +++ b/.devcontainer/run-tests.sh @@ -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 " + 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 diff --git a/.devcontainer/s390x/Dockerfile b/.devcontainer/s390x/Dockerfile index 21a6289c..536f2de4 100644 --- a/.devcontainer/s390x/Dockerfile +++ b/.devcontainer/s390x/Dockerfile @@ -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"] diff --git a/.devcontainer/s390x/devcontainer.json b/.devcontainer/s390x/devcontainer.json index 8b7f8235..535a0799 100644 --- a/.devcontainer/s390x/devcontainer.json +++ b/.devcontainer/s390x/devcontainer.json @@ -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" diff --git a/.devcontainer/ubuntu-26.04/Dockerfile b/.devcontainer/ubuntu-26.04/Dockerfile new file mode 100644 index 00000000..ddd21706 --- /dev/null +++ b/.devcontainer/ubuntu-26.04/Dockerfile @@ -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"] diff --git a/.github/workflows/bazel-gcc-c++23-no-stl.yml b/.github/workflows/bazel-gcc-c++23-no-stl.yml new file mode 100644 index 00000000..b41765a2 --- /dev/null +++ b/.github/workflows/bazel-gcc-c++23-no-stl.yml @@ -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 diff --git a/.github/workflows/clang-c++11.yml b/.github/workflows/clang-c++11.yml index d511f5b7..6b73b7c1 100644 --- a/.github/workflows/clang-c++11.yml +++ b/.github/workflows/clang-c++11.yml @@ -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 \ No newline at end of file diff --git a/.github/workflows/clang-c++14.yml b/.github/workflows/clang-c++14.yml index d06778b1..830832b5 100644 --- a/.github/workflows/clang-c++14.yml +++ b/.github/workflows/clang-c++14.yml @@ -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 \ No newline at end of file diff --git a/.github/workflows/clang-c++17.yml b/.github/workflows/clang-c++17.yml index 9fb4611f..6ae2f4b9 100644 --- a/.github/workflows/clang-c++17.yml +++ b/.github/workflows/clang-c++17.yml @@ -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 \ No newline at end of file diff --git a/.github/workflows/clang-c++20.yml b/.github/workflows/clang-c++20.yml index c68f9870..e246a795 100644 --- a/.github/workflows/clang-c++20.yml +++ b/.github/workflows/clang-c++20.yml @@ -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 diff --git a/.github/workflows/clang-c++23.yml b/.github/workflows/clang-c++23.yml index ffa88744..0c2d8c9b 100644 --- a/.github/workflows/clang-c++23.yml +++ b/.github/workflows/clang-c++23.yml @@ -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 diff --git a/.github/workflows/clang-c++26.yml b/.github/workflows/clang-c++26.yml new file mode 100644 index 00000000..35d127bf --- /dev/null +++ b/.github/workflows/clang-c++26.yml @@ -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 diff --git a/.github/workflows/clang-syntax-checks.yml b/.github/workflows/clang-syntax-checks.yml index 700b2087..2c6000e7 100644 --- a/.github/workflows/clang-syntax-checks.yml +++ b/.github/workflows/clang-syntax-checks.yml @@ -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)" diff --git a/.github/workflows/clang-tidy.yaml b/.github/workflows/clang-tidy.yaml new file mode 100644 index 00000000..214d30b2 --- /dev/null +++ b/.github/workflows/clang-tidy.yaml @@ -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 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 79f9553e..5c05ebef 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -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 diff --git a/.github/workflows/deploy_documentation.yml b/.github/workflows/deploy_documentation.yml new file mode 100644 index 00000000..fb300580 --- /dev/null +++ b/.github/workflows/deploy_documentation.yml @@ -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 }} diff --git a/.github/workflows/gcc-c++11.yml b/.github/workflows/gcc-c++11.yml index 571c6d6e..c9706aeb 100644 --- a/.github/workflows/gcc-c++11.yml +++ b/.github/workflows/gcc-c++11.yml @@ -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 diff --git a/.github/workflows/gcc-c++14.yml b/.github/workflows/gcc-c++14.yml index f623af08..a3277b66 100644 --- a/.github/workflows/gcc-c++14.yml +++ b/.github/workflows/gcc-c++14.yml @@ -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 \ No newline at end of file diff --git a/.github/workflows/gcc-c++17.yml b/.github/workflows/gcc-c++17.yml index fc0ddd97..dbeef7fa 100644 --- a/.github/workflows/gcc-c++17.yml +++ b/.github/workflows/gcc-c++17.yml @@ -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 diff --git a/.github/workflows/gcc-c++20.yml b/.github/workflows/gcc-c++20.yml index 5965e05e..be4e6fb2 100644 --- a/.github/workflows/gcc-c++20.yml +++ b/.github/workflows/gcc-c++20.yml @@ -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 \ No newline at end of file diff --git a/.github/workflows/gcc-c++23-armhf.yml b/.github/workflows/gcc-c++23-armhf.yml new file mode 100644 index 00000000..1bd2912b --- /dev/null +++ b/.github/workflows/gcc-c++23-armhf.yml @@ -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" diff --git a/.github/workflows/gcc-c++23-i386.yml b/.github/workflows/gcc-c++23-i386.yml new file mode 100644 index 00000000..31bfc331 --- /dev/null +++ b/.github/workflows/gcc-c++23-i386.yml @@ -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" diff --git a/.github/workflows/gcc-c++23-powerpc.yml b/.github/workflows/gcc-c++23-powerpc.yml new file mode 100644 index 00000000..7494ae55 --- /dev/null +++ b/.github/workflows/gcc-c++23-powerpc.yml @@ -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" diff --git a/.github/workflows/gcc-c++23-riscv64.yml b/.github/workflows/gcc-c++23-riscv64.yml new file mode 100644 index 00000000..695056a8 --- /dev/null +++ b/.github/workflows/gcc-c++23-riscv64.yml @@ -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" diff --git a/.github/workflows/gcc-c++23-s390x.yml b/.github/workflows/gcc-c++23-s390x.yml new file mode 100644 index 00000000..f6a15aca --- /dev/null +++ b/.github/workflows/gcc-c++23-s390x.yml @@ -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" diff --git a/.github/workflows/gcc-c++23.yml b/.github/workflows/gcc-c++23.yml index f91924bd..9ca6baf0 100644 --- a/.github/workflows/gcc-c++23.yml +++ b/.github/workflows/gcc-c++23.yml @@ -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 \ No newline at end of file diff --git a/.github/workflows/gcc-c++26.yml b/.github/workflows/gcc-c++26.yml new file mode 100644 index 00000000..b7ff42d3 --- /dev/null +++ b/.github/workflows/gcc-c++26.yml @@ -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" diff --git a/.github/workflows/gcc-syntax-checks.yml b/.github/workflows/gcc-syntax-checks.yml index 5f3753b1..b6b77bad 100644 --- a/.github/workflows/gcc-syntax-checks.yml +++ b/.github/workflows/gcc-syntax-checks.yml @@ -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) \ No newline at end of file + 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)" diff --git a/.github/workflows/generator.yml b/.github/workflows/generator.yml index 032ffd1e..1829c342 100644 --- a/.github/workflows/generator.yml +++ b/.github/workflows/generator.yml @@ -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 diff --git a/.github/workflows/meson-gcc-c++23-no-stl.yml b/.github/workflows/meson-gcc-c++23-no-stl.yml new file mode 100644 index 00000000..d8767317 --- /dev/null +++ b/.github/workflows/meson-gcc-c++23-no-stl.yml @@ -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 diff --git a/.gitignore b/.gitignore index d77af359..33e67bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -419,3 +419,5 @@ hugo/resources hugo/.hugo_build.lock docs/*.html test/build-coverage +include/etl/iterator.h~RFfd5eda.TMP +test/vs2022/Build diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..e69de29b diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 00000000..3bdb072e --- /dev/null +++ b/BUILD.bazel @@ -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"], +) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md new file mode 100644 index 00000000..2da43c6b --- /dev/null +++ b/DOCUMENTATION.md @@ -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. diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 00000000..a52b73e8 --- /dev/null +++ b/MODULE.bazel @@ -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") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock new file mode 100644 index 00000000..c6bcd5ce --- /dev/null +++ b/MODULE.bazel.lock @@ -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": {} +} diff --git a/README.md b/README.md index e689736a..73ac1752 100644 --- a/README.md +++ b/README.md @@ -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&utm_medium=referral&utm_content=ETLCPP/etl&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. diff --git a/arduino/Embedded_Template_Library.h b/arduino/Embedded_Template_Library.h index aed4c865..64542c84 100644 --- a/arduino/Embedded_Template_Library.h +++ b/arduino/Embedded_Template_Library.h @@ -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 diff --git a/docs/IO/_index.md b/docs/IO/_index.md new file mode 100644 index 00000000..8a93b851 --- /dev/null +++ b/docs/IO/_index.md @@ -0,0 +1,6 @@ +--- +title: "IO" +weight: 100 +--- + +Classes that address access to hardware. diff --git a/docs/IO/bip_buffer_spsc_atomic.md b/docs/IO/bip_buffer_spsc_atomic.md new file mode 100644 index 00000000..14b4cbfb --- /dev/null +++ b/docs/IO/bip_buffer_spsc_atomic.md @@ -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 +``` + +Inherits from `etl::ibip_buffer_spsc_atomic`. + +`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(); +``` + +## 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 read_reserve(size_type max_reserve_size = numeric_limits::max()) +``` +**Description** +Reserves a memory area for reading (up to the `max_reserve_size`). + +```cpp +void read_commit(const etl::span &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 write_reserve(size_type max_reserve_size) +``` +**Description** +Reserves a memory area for writing up to the `max_reserve_size`. + +--- + +```cpp +etl::span 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 &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. + diff --git a/docs/IO/buffer_descriptors.md b/docs/IO/buffer_descriptors.md new file mode 100644 index 00000000..4e49278e --- /dev/null +++ b/docs/IO/buffer_descriptors.md @@ -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 // 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` | + +## 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; + +// 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()); + +// 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())); +} +``` diff --git a/docs/IO/debounce.md b/docs/IO/debounce.md new file mode 100644 index 00000000..502c1878 --- /dev/null +++ b/docs/IO/debounce.md @@ -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 +``` + +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` + +The initial state defaults to: + +Initial state = `false` +Valid count = `Valid_Count` +Hold count = `Hold_Count` +Repeat count = `Repeat_Count` + +--- + +`etl::debounce` + +The initial state defaults to: + +Initial state = `false` +Valid count = `Valid_Count` +Hold count = `Hold_Count` +Repeat count = `0` (Disabled) + +--- + +`etl::debounce` + +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 + +// 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 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 +} +``` diff --git a/docs/IO/debounce.png b/docs/IO/debounce.png new file mode 100644 index 00000000..bfc40a8e Binary files /dev/null and b/docs/IO/debounce.png differ diff --git a/docs/IO/io_port.md b/docs/IO/io_port.md new file mode 100644 index 00000000..a5ba6dc2 --- /dev/null +++ b/docs/IO/io_port.md @@ -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 +``` +**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 +``` + +--- + +**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 +``` + +--- + +**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 +``` + +--- + +**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 +struct serial_port +{ + etl::io_port_ro rxdata; // Read only rx data register. + etl::io_port_wo txdata; // Write only tx register. + etl::io_port_wos control; // Write only, with shadow, control register. + etl::io_port_ro status; // Read only status register. + etl::io_port_ro 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)); +``` diff --git a/docs/Is the ETL free.md b/docs/Is the ETL free.md new file mode 100644 index 00000000..013c47a3 --- /dev/null +++ b/docs/Is the ETL free.md @@ -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* diff --git a/docs/Messaging/_index.md b/docs/Messaging/_index.md new file mode 100644 index 00000000..5344a178 --- /dev/null +++ b/docs/Messaging/_index.md @@ -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` 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 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) diff --git a/docs/Messaging/images/message-framework.png b/docs/Messaging/images/message-framework.png new file mode 100644 index 00000000..a4b8a424 Binary files /dev/null and b/docs/Messaging/images/message-framework.png differ diff --git a/docs/Messaging/message-broker.md b/docs/Messaging/message-broker.md new file mode 100644 index 00000000..ffc5df6d --- /dev/null +++ b/docs/Messaging/message-broker.md @@ -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 +``` + +## 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 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 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 +``` diff --git a/docs/Messaging/message-bus.md b/docs/Messaging/message-bus.md new file mode 100644 index 00000000..921e5b86 --- /dev/null +++ b/docs/Messaging/message-bus.md @@ -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 +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 +``` diff --git a/docs/Messaging/message-packet.md b/docs/Messaging/message-packet.md new file mode 100644 index 00000000..d027aaed --- /dev/null +++ b/docs/Messaging/message-packet.md @@ -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` + +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 +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 +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 +{ +}; + +struct Message2 : public etl::message +{ +}; + +struct Message3 : public etl::message +{ +}; + +using Packet = etl::message_packet + +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. +``` diff --git a/docs/Messaging/message-router-registry.md b/docs/Messaging/message-router-registry.md new file mode 100644 index 00000000..cfd21d1d --- /dev/null +++ b/docs/Messaging/message-router-registry.md @@ -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 +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 +message_router_registry(TIterator first, const TIterator& last) +``` +Constructs from an iterator range. + +--- + +```cpp +message_router_registry(std::initializer_list 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. diff --git a/docs/Messaging/message.md b/docs/Messaging/message.md new file mode 100644 index 00000000..5f6efa95 --- /dev/null +++ b/docs/Messaging/message.md @@ -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 +``` +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 +{ + void DoStuff() override + { + // Do stuff here. + } +}; + +struct Stop : public etl::message +{ + bool isEmergencyStop; +}; + +struct SetSpeed : public etl::message +{ + uint32_t speed; +}; + +void Receive(const etl::imessage& msg); +``` diff --git a/docs/Messaging/reference-counted-message-pool.md b/docs/Messaging/reference-counted-message-pool.md new file mode 100644 index 00000000..b2701cd0 --- /dev/null +++ b/docs/Messaging/reference-counted-message-pool.md @@ -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 +``` +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 +etl::reference_counted_message* 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 +etl::reference_counted_message* 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 +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 +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 +using atomic_counted_message_pool = etl::reference_counted_message_pool; +``` +Defines an alias to a reference counted message pool that uses an atomic. diff --git a/docs/Messaging/reference-counted-messages.md b/docs/Messaging/reference-counted-messages.md new file mode 100644 index 00000000..8e8bd728 --- /dev/null +++ b/docs/Messaging/reference-counted-messages.md @@ -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 +``` +Derived from `etl::ireference_counted_message`. + +```cpp +etl::persistent_message +``` +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 +``` +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 +``` + +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 +using atomic_counted_message = etl::reference_counted_message; +``` +Defines an alias to a reference counted message that uses an atomic. + diff --git a/docs/Messaging/shared-message.md b/docs/Messaging/shared-message.md new file mode 100644 index 00000000..79ea8a74 --- /dev/null +++ b/docs/Messaging/shared-message.md @@ -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 +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 +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. diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index 6fac68f0..00000000 --- a/docs/_config.yml +++ /dev/null @@ -1,6 +0,0 @@ -plugins: - - jekyll-relative-links -relative_links: - enabled: true -include: - - manchester.md diff --git a/docs/_index.md b/docs/_index.md new file mode 100644 index 00000000..e6f75a2e --- /dev/null +++ b/docs/_index.md @@ -0,0 +1,131 @@ +--- +title: "Embedded Template Library" +weight: 998 +type: hextra-home +--- + +
+ +
+ release + date + standard + license + contributors + forks + stars +
+ +
+ CI MSVC +
+ +
+ CI GCC 11 + CI GCC 14 + CI GCC 17 + CI GCC 20 + CI GCC 23 + CI GCC syntax +
+ +
+ CI Clang 11 + CI Clang 14 + CI Clang 17 + CI Clang 20 + CI Clang 23 + CI Clang syntax +
+ +
+ coverage + Codacy +
+ +
+ Sponsor +
+ +
+ +## 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, it’s 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. + +What’s 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; user’s 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. diff --git a/docs/about.md b/docs/about.md new file mode 100644 index 00000000..6068aea1 --- /dev/null +++ b/docs/about.md @@ -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. diff --git a/docs/binary/_index.md b/docs/binary/_index.md new file mode 100644 index 00000000..2e3e32da --- /dev/null +++ b/docs/binary/_index.md @@ -0,0 +1,6 @@ +--- +title: "Binary utilities" +weight: 100 +--- + +Classes and functions that define and manipulate binary data. \ No newline at end of file diff --git a/docs/binary/binary.md b/docs/binary/binary.md new file mode 100644 index 00000000..f9fd0594 --- /dev/null +++ b/docs/binary/binary.md @@ -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 +ETL_CONSTEXPR14 T rotate_left(T value) +``` +**Return** +`value` rotated left by one bit. + +```cpp +template +ETL_CONSTEXPR14 T rotate_left(T value, size_t distance) +``` +**Return** +`value` rotated left by `distance`. + +```cpp +template +ETL_CONSTEXPR14 T rotate_right(T value) +``` +**Return** +`value` rotated right by one bit. + +```cpp +template +ETL_CONSTEXPR14 T rotate_right(T value, size_t distance) +``` +**Return** +`value` rotated right by `distance`. + +```cpp +template +ETL_CONSTEXPR14 T rotate(T value, typename etl::make_signed::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 +ETL_CONSTEXPR14 T reverse_bits(T value) +``` + +The structures below define a member constant value that is Value reversed in bits. +```cpp +template +struct reverse_bits_const +``` +```cpp +template +struct reverse_bits_const +``` +```cpp +template +struct reverse_bits_const +``` +```cpp +template +struct reverse_bits_const +``` +```cpp +template +struct reverse_bits_const +``` +```cpp +template +struct reverse_bits_const +``` +```cpp +template +struct reverse_bits_const +``` +```cpp +template +struct reverse_bits_const +``` + +Defines `value` The reversed bits. + +## reverse_bytes +Reverse the order of the bytes in a value. + +```cpp +template +ETL_CONSTEXPR14 T reverse_bytes(T value) +``` + +## gray_to_binary +```cpp +template +ETL_CONSTEXPR14 T gray_to_binary(T value) +``` +Converts a gray code value to binary. + +## binary_to_gray +```cpp +template +ETL_CONSTEXPR T binary_to_gray(T value) +``` +Converts a binary value to the gray code equivalent. + +## count_bits +```cpp +template +ETL_CONSTEXPR14 uint_least8_t count_bits(T value) +``` +**Return** +The number of set bits in `value`. + +## parity +```cpp +template +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 +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 +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(0xE8C9AACCBC3D9A8F); +``` + +## sign_extend +Sign extends a binary number. + +```cpp +template +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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(uint8_t(0x12)); +``` + +--- + +```cpp +template +ETL_CONSTEXPR TResult binary_fill() +``` +*Partial compile time* + +Generate `0x12121212` +```cpp +etl::binary_fill(); +``` + +## has_zero_byte +```cpp +template +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 +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 +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 +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 +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 +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(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 +ETL_CONSTEXPR bool is_odd(T value) +``` + +```cpp +template +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 +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 +class lsb_mask; +``` +Defines the member constant value as a binary value of NBits `1` shift to the LSB. +e.g. `lsb_mask::value == 0b00000111` +From: `20.34.0` + +--- + +```cpp +template +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(3) == 0b00000111` +From: `20.34.0` + +--- + +```cpp +template +ETL_CONSTEXPR T make_lsb_mask() +``` +**Description** +Returns a binary value of nbits `1` shift to the LSB. +e.g. `make_lsb_mask() == 0b00000111` +From: `20.38.7` + +--- + +```cpp +template +class msb_mask; +``` +**Return** +A binary value of nbits `1` shift to the MSB. +e.g. `msb_mask::value == 0b11100000` +From: `20.34.0` + +--- + +```cpp +template +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(3) == 0b11100000` +20.34.0 + +--- + +```cpp +template +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() == 0b11100000` +From: `20.38.7` + +## Bit manipulation functors +These functors are most useful where lambdas are not available. + +## binary_not +```cpp +template +struct binary_not : public etl::unary_function; +``` +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 +struct binary_and : public etl::unary_function; +``` +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 +struct binary_or : public etl::unary_function; +``` +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 +struct binary_xor : public etl::unary_function; +``` +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. diff --git a/docs/binary/bit.md b/docs/binary/bit.md new file mode 100644 index 00000000..ec88ec11 --- /dev/null +++ b/docs/binary/bit.md @@ -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 `` header. + +## bit_cast +```cpp +template +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 +ETL_CONSTEXPR14 T byteswap(T n) ETL_NOEXCEPT +``` +**Description** +Reverses the bytes in `n`. + +## has_single_bit +```cpp +template +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 +ETL_CONSTEXPR14 T bit_ceil(T n) +``` +**Description** +Calculates the smallest power of two, that is not smaller than `n`. + +## bit_floor +```cpp +template +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 +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 +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 +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 +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 +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 +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 +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 +ETL_NODISCARD ETL_CONSTEXPR14 int popcount(T value) ETL_NOEXCEPT +``` +**Description** +Counts the number of `1` bits in an unsigned integer. diff --git a/docs/binary/byte.md b/docs/binary/byte.md new file mode 100644 index 00000000..0e878b3e --- /dev/null +++ b/docs/binary/byte.md @@ -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 +explicit byte(T v) +``` +Constructs a byte initialised to `v`. + +## Non-member functions +```cpp +template +constexpr TInteger to_integer(etl::byte b) noexcept +``` +**Description** +Converts to an integral type. +`constexpr` and `noexcept` for C++11 and above. + +--- + +```cpp +template +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 +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 +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 +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. diff --git a/docs/binary/flags.md b/docs/binary/flags.md new file mode 100644 index 00000000..845bf1d5 --- /dev/null +++ b/docs/binary/flags.md @@ -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 ::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& pattern) ETL_NOEXCEPT +``` +**Description** +Constructs a flag set with elements set to pattern. + +## Modifiers + +```cpp +ETL_CONSTEXPR14 flags& operator=(flags other) ETL_NOEXCEPT +``` +**Description** +Assigns from another flags object. + +--- + +```cpp +ETL_CONSTEXPR14 flags& operator=(value_type pattern) ETL_NOEXCEPT +``` +**Description** +Assigns from a bit pattern. + +--- + +```cpp +template +ETL_CONSTEXPR14 flags& set() ETL_NOEXCEPT +``` + +--- + +```cpp +template +ETL_CONSTEXPR14 flags& set(bool value) ETL_NOEXCEPT +``` + +--- + +```cpp +template +ETL_CONSTEXPR14 flags& set() ETL_NOEXCEPT +``` + +--- + +```cpp +ETL_CONSTEXPR14 flags& set(value_type pattern) ETL_NOEXCEPT +``` + +--- + +```cpp +ETL_CONSTEXPR14 flags& set(value_type pattern, bool value) ETL_NOEXCEPT +``` + +--- + +```cpp +ETL_CONSTEXPR14 flags& clear() ETL_NOEXCEPT +``` +____________________________________________________________________________________________________ +template +ETL_CONSTEXPR14 flags& reset() ETL_NOEXCEPT +____________________________________________________________________________________________________ +ETL_CONSTEXPR14 flags& reset(value_type pattern) ETL_NOEXCEPT +____________________________________________________________________________________________________ +ETL_CONSTEXPR14 flags& flip() ETL_NOEXCEPT +____________________________________________________________________________________________________ +template +ETL_CONSTEXPR14 flags& flip() ETL_NOEXCEPT +____________________________________________________________________________________________________ +ETL_CONSTEXPR14 flags& flip(value_type pattern) ETL_NOEXCEPT +____________________________________________________________________________________________________ +Access + +template +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 +void swap(flags& lhs, flags& rhs) +Swaps two flags. + +template +bool operator == (flags& lhs, flags& rhs) +Checks equality of two flags. + +template +bool operator != (flags& lhs, flags& rhs) +Checks inequality of two flags. + diff --git a/docs/blog/_index.md b/docs/blog/_index.md new file mode 100644 index 00000000..d7661667 --- /dev/null +++ b/docs/blog/_index.md @@ -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" %}}) diff --git a/docs/blog/graphics/Reflection1.png b/docs/blog/graphics/Reflection1.png new file mode 100644 index 00000000..62e84a66 Binary files /dev/null and b/docs/blog/graphics/Reflection1.png differ diff --git a/docs/blog/graphics/_index.md b/docs/blog/graphics/_index.md new file mode 100644 index 00000000..5dfecb76 --- /dev/null +++ b/docs/blog/graphics/_index.md @@ -0,0 +1,5 @@ +--- +title: "Graphics" +weight: 1 +--- + diff --git a/docs/blog/graphics/applications-of-dot-and-cross-products.md b/docs/blog/graphics/applications-of-dot-and-cross-products.md new file mode 100644 index 00000000..16928bc9 --- /dev/null +++ b/docs/blog/graphics/applications-of-dot-and-cross-products.md @@ -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. diff --git a/docs/blog/graphics/determining-line-line-intersections.md b/docs/blog/graphics/determining-line-line-intersections.md new file mode 100644 index 00000000..279103ae --- /dev/null +++ b/docs/blog/graphics/determining-line-line-intersections.md @@ -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`. diff --git a/docs/blog/graphics/dot-and-cross-products.md b/docs/blog/graphics/dot-and-cross-products.md new file mode 100644 index 00000000..e4526c19 --- /dev/null +++ b/docs/blog/graphics/dot-and-cross-products.md @@ -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|)`. \ No newline at end of file diff --git a/docs/blog/graphics/images/DotCross1.png b/docs/blog/graphics/images/DotCross1.png new file mode 100644 index 00000000..32c9de03 Binary files /dev/null and b/docs/blog/graphics/images/DotCross1.png differ diff --git a/docs/blog/graphics/images/DotCross3.png b/docs/blog/graphics/images/DotCross3.png new file mode 100644 index 00000000..ad311d95 Binary files /dev/null and b/docs/blog/graphics/images/DotCross3.png differ diff --git a/docs/blog/graphics/images/DotCross4.png b/docs/blog/graphics/images/DotCross4.png new file mode 100644 index 00000000..ac2e8a36 Binary files /dev/null and b/docs/blog/graphics/images/DotCross4.png differ diff --git a/docs/blog/graphics/images/DotCrossCoordinates.png b/docs/blog/graphics/images/DotCrossCoordinates.png new file mode 100644 index 00000000..8fc43021 Binary files /dev/null and b/docs/blog/graphics/images/DotCrossCoordinates.png differ diff --git a/docs/blog/graphics/images/LineCross1.png b/docs/blog/graphics/images/LineCross1.png new file mode 100644 index 00000000..20047e57 Binary files /dev/null and b/docs/blog/graphics/images/LineCross1.png differ diff --git a/docs/blog/graphics/images/LineCross2.png b/docs/blog/graphics/images/LineCross2.png new file mode 100644 index 00000000..a799713e Binary files /dev/null and b/docs/blog/graphics/images/LineCross2.png differ diff --git a/docs/blog/graphics/images/Reflection1.png b/docs/blog/graphics/images/Reflection1.png new file mode 100644 index 00000000..36637022 Binary files /dev/null and b/docs/blog/graphics/images/Reflection1.png differ diff --git a/docs/blog/graphics/images/ScanRectangle1.png b/docs/blog/graphics/images/ScanRectangle1.png new file mode 100644 index 00000000..9d9a30fb Binary files /dev/null and b/docs/blog/graphics/images/ScanRectangle1.png differ diff --git a/docs/blog/graphics/images/ScanRectangle2.png b/docs/blog/graphics/images/ScanRectangle2.png new file mode 100644 index 00000000..ba629fba Binary files /dev/null and b/docs/blog/graphics/images/ScanRectangle2.png differ diff --git a/docs/blog/graphics/images/ScanRectangle3.png b/docs/blog/graphics/images/ScanRectangle3.png new file mode 100644 index 00000000..86b5dfd2 Binary files /dev/null and b/docs/blog/graphics/images/ScanRectangle3.png differ diff --git a/docs/blog/graphics/images/ScanRectangle4.png b/docs/blog/graphics/images/ScanRectangle4.png new file mode 100644 index 00000000..d39a7e38 Binary files /dev/null and b/docs/blog/graphics/images/ScanRectangle4.png differ diff --git a/docs/blog/graphics/images/ScanRectangle5.png b/docs/blog/graphics/images/ScanRectangle5.png new file mode 100644 index 00000000..a5270323 Binary files /dev/null and b/docs/blog/graphics/images/ScanRectangle5.png differ diff --git a/docs/blog/graphics/images/ScanRectangle6.png b/docs/blog/graphics/images/ScanRectangle6.png new file mode 100644 index 00000000..e210213f Binary files /dev/null and b/docs/blog/graphics/images/ScanRectangle6.png differ diff --git a/docs/blog/graphics/scanning-an-arbitrarily-rotated-rectangular-region.md b/docs/blog/graphics/scanning-an-arbitrarily-rotated-rectangular-region.md new file mode 100644 index 00000000..e6ea649c --- /dev/null +++ b/docs/blog/graphics/scanning-an-arbitrarily-rotated-rectangular-region.md @@ -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. + diff --git a/docs/blog/implementing-a-low-cost-moving-average.md b/docs/blog/implementing-a-low-cost-moving-average.md new file mode 100644 index 00000000..21219a67 --- /dev/null +++ b/docs/blog/implementing-a-low-cost-moving-average.md @@ -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" %}}) diff --git a/docs/callbacks/_index.md b/docs/callbacks/_index.md new file mode 100644 index 00000000..621c59a7 --- /dev/null +++ b/docs/callbacks/_index.md @@ -0,0 +1,8 @@ +--- +title: "Callbacks" +weight: 100 +--- + +Classes that allow callbacks to be easily defined. + +Includes delegates, STL style function wrappers, closures, and signal/slot frameworks. diff --git a/docs/callbacks/callback-service.md b/docs/callbacks/callback-service.md new file mode 100644 index 00000000..d06e04ad --- /dev/null +++ b/docs/callbacks/callback-service.md @@ -0,0 +1,80 @@ +--- +title: "callback_service" +--- + +{{< callout type="info">}} + Header: `callback_service.h` +{{< /callout >}} + +This template class allows easier integration of 'C' style events (such as interrupt vectors) and C++ handlers. +It can allow abstraction between low level events such as interrupts and their application dependent handlers. +The handlers may be any combination of global, static or member functions. +It utilises the templated function wrapper. + +The callbacks are identified by an id. The values of the ids must range from zero or a specified offset, up to the maximum number of specified callbacks. Calling an unused callback id will either do nothing or, if the user has specified a handler, call this with the id of the callback. + +There are functions that use both runtime and compile time checks of the callback id. +Compile time is preferable. + +## Member functions + +```cpp +template +etl::callback_service +``` +`RANGE` The id range of the callbacks. +`OFFSET` The starting id for the range. + +It can allow abstraction between low level events such as interrupts and their application dependent handlers. + +```cpp +callback_service() +``` +Sets all of the callbacks to route to the unhandled callback. +Sets the unhandled callback to default (do nothing). + +--- + +```cpp +template +void register_callback(etl::ifunction& callback) +``` +Registers callback with the id specified in the template parameter. +A compile time error will occur if the id is out of range. + +--- + +```cpp +void register_callback(size_t id, etl::ifunction& callback) +``` +Registers callback with the id specified in the template parameter. +The registration will be ignored if the id is out of range. + +--- + +```cpp +void register_unhandled_callback(etl::ifunction& callback) +``` +Registers the callback to be used for unhandled ids. + +--- + +```cpp +template +void callback() +``` +Calls the callback associated with the id. +Calls the unhandled callback if the id has not been registered. +A compile time error will occur if the id is out of range. + +--- + +```cpp +void callback(const size_t id) +``` +Calls the callback associated with the id. +Calls the unhandled callback if the id has not been registered or if is out of range. + +## Example + +See the example project in `examples\FunctionInterruptSimulation`. diff --git a/docs/callbacks/closure.md b/docs/callbacks/closure.md new file mode 100644 index 00000000..e79626cc --- /dev/null +++ b/docs/callbacks/closure.md @@ -0,0 +1,75 @@ +--- +title: "closure" +--- + +`etl::closure` wraps an `etl::delegate` and a set of arguments. + +**C++11 and above** +```cpp +etl::closure +``` + +**C++03.** +```cpp +etl::delegate +etl::delegate +etl::delegate +etl::delegate +etl::delegate +``` + +## Types + +`delegate_type` The delegate type `etl::delegate` + +## Constructor + +C++11 and above. +```cpp +ETL_CONSTEXPR14 closure(const delegate_type& f, const TArgs... args) +``` + +C++03. +```cpp +closure(const delegate_type& f, const TArg0 arg0) +closure(const delegate_type& f, const TArg0 arg0, const TArg1 arg1) +closure(const delegate_type& f, const TArg0 arg0, const TArg1 arg1, const TArg2 arg2) +closure(const delegate_type& f, const TArg0 arg0, const TArg1 arg1, const TArg2 arg2, + const TArg3 arg3) +closure(const delegate_type& f, const TArg0 arg0, const TArg1 arg1, const TArg2 arg2, + const TArg3 arg3, const TArg4 arg4) +``` + +## Operations +```cpp +template +void bind(UArg arg) +``` +**Description** +Bind a new value to the argument at the specified index. +`UArg` must be one of `TArgs`. +Only non-reference types can be rebound. +Static asserts if `UArg` is not convertible to the closure's argument. +Static asserts if `UArg` is a reference type. +*C++11 and above.* + +--- + +```cpp +template +void bind(UArgs&&... args) +``` +**Description** +Bind new values to all of the arguments at once. +The number of arguments must match the delegate. +Static asserts if the number of arguments don't match the delegate. +*C++11 and above.* + +--- + +```cpp +ETL_CONSTEXPR14 TReturn operator()(TParams... args) const +``` +**Description** +Invokes the stored delegate with the bound arguments. + diff --git a/docs/callbacks/delegate-service.md b/docs/callbacks/delegate-service.md new file mode 100644 index 00000000..c7498744 --- /dev/null +++ b/docs/callbacks/delegate-service.md @@ -0,0 +1,93 @@ +--- +title: "delegate_service" +--- + +{{< callout type="info">}} + Header: `delegate_service.h` +{{< /callout >}} + +Delegate Service +This template class allows easier integration of 'C' style events (such as interrupt vectors) and C++ handlers. +It can allow abstraction between low level events such as interrupts and their application dependent handlers. +The handlers may be any combination of global, static, member functions, lambdas and functors. +It utilises the templated function wrapper. + +The delegate callbacks are identified by an id. The values of the ids must range from zero or a specified offset, up to the maximum range of specified delegates. Calling an unused delegate id will either do nothing or, if the user has specified a handler, call this with the id of the delegate. + +There are functions that use both runtime and compile time checks of the delegate id. +Compile time is preferable. + +--- + +```cpp +template * Delegates = nullptr> +delegate_service +``` +`Range` +The id range of the delegates (last - first + 1). + +`Offset` +The starting id for the range. Default `0`. + +`Delegates` +An optional pointer to an array of delegate pointers. + +If the pointer to a delegate array is supplied as a template parameter then the delegate service may be declared `constexpr`, otherwise the service is runtime only. + +## Member functions + +```cpp +delegate_service() +``` +Runtime only. +Sets all of the delegates to route to the unhandled delegate. +Sets the unhandled delegate to default (do nothing). + +--- + +```cpp +template +void register_delegate(etl::delegate& callback) +``` +Runtime only. +Registers delegate with the id specified in the template parameter. +A compile time error will occur if the id is out of range. + +--- + +```cpp +void register_delegate(size_t id, etl::delegate& callback) +``` +Runtime only. +Registers delegate with the id specified in the template parameter. +The registration will be ignored if the id is out of range. + +--- + +```cpp +void register_unhandled_delegate(etl::delegate& callback) +``` +Runtime only. +Registers the delegate to be used for unhandled ids. + +--- + +```cpp +template +void call() +``` +Calls the delegate associated with the id. +Calls the unhandled delegate if the id has not been registered. +A compile time error will occur if the id is out of range. + +--- + +```cpp +void call(const size_t id) +``` +Calls the delegate associated with the id. +Calls the unhandled delegate if the id has not been registered or if is out of range. + +## Example + +See the example project in `examples\FunctionInterruptSimulation-Delegates`. diff --git a/docs/callbacks/delegate-vs-inplace_function.md b/docs/callbacks/delegate-vs-inplace_function.md new file mode 100644 index 00000000..92994db7 --- /dev/null +++ b/docs/callbacks/delegate-vs-inplace_function.md @@ -0,0 +1,220 @@ +--- +title: "delegate vs inplace_function" +weight: 1 +--- + +## Efficiency and performance +### Invocation cost + +**delegate** +One indirect call via stub function pointer; no allocation; forwards args directly; minimal overhead. + +**inplace_function** +One indirect call via vtable invoke pointer; no allocation; overhead effectively the same as `delegate`. + +### Copy / move cost + +**delegate** +Trivial copy/move (object pointer + stub pointer). + +**inplace_function** +Copies/moves the stored callable in an inline buffer; cost depends on callable traits; may run destructor on clear/reset. + +### Size / footprint + +**delegate** +Typically two pointers; very small, stable footprint. + +**inplace_function** +Buffer + vtable pointer + object pointer; size depends on `Object_Size`/`Object_Alignment`. + +### Ownership / lifetime + +**delegate** +Non-owning for functors/lambdas; stores pointer to external callable; caller must ensure lifetime. + +**inplace_function** +Owning; stores a copy/move of the callable inline (RAII). + +### When to prefer + +**delegate** +Minimal footprint, cheapest copies, free/member function binding, controlled lifetimes. + +**inplace_function** +Value semantics, safe storage of lambdas with captures, uniform SBO wrapper. + +## External API differences + +### Template shape and size + +`delegate` +`inplace_function` + +### Construction / binding + +**delegate** +`create()` +`create(T& obj, Method)` and `create(const T& obj, ConstMethod)` at run time +`create()` +Construct from functor/lambda by reference (non-owning); rvalues deleted to avoid dangling +`set()` mirrors `create()` for re-binding + +**inplace_function** +Constructor from function pointer +Constructor from object + (const/non-const) member function (run time) +Constructor from functor/lambda by (const) reference; callable stored inline (owning) +`set()` mirrors constructors; also `set()` and `set()` (compile time) +`create()`, `create()` (compile time) +`make_inplace_function` helpers: `make_inplace_function(free_fn)`, `make_inplace_function(obj, &T::Method)` , `make_inplace_function(lambda)`. + +### Equality and swap + +**delegate** +`operator==`/`!=` compare stub and object; structural equality. + +**inplace_function** +`operator==`/`!=` with `nullptr`; `swap()` provided; no general equality between two functions. + +### Introspection helpers +**delegate** +`delegate_tag` +`is_delegate`. + +**inplace_function** +`is_inplace_function`. + +### Call helpers +`is_valid()` +`explicit bool` +`call_if(...)` +`call_or(alternative, ...)` +`call_or(...)`. + +### Functor storage semantics +**delegate** +Non-owning pointer to external functor/lambda. + +**inplace_function** +Owns a copy/move in fixed buffer. + +### Size control +**delegate** +Fixed small size (two pointers). + +**inplace_function** +User-controlled via `Object_Size`/`Object_Alignment`; aliases `inplace_function_for` and `inplace_function_for_any` to compute required size/alignment. + +### C++ language features +Classic non-type template parameter APIs; C++17 "auto" `make_*` helpers exist when enabled. + +## Performance differences: + +### Call overhead +**delegate** +One indirect call through a stub function pointer; minimal overhead. + +**inplace_function** +One indirect call via `vtable->invoke(object, ...);` typically one extra pointer load; practically similar. + +### Copy / move and lifetime +**delegate** +Trivial POD-like copy/move (object pointer + stub); no construction/destruction of target. + +**inplace_function** +Copies/moves/destroys the stored callable in the inline buffer; cost depends on callable traits. + +### Construction / binding cost +**delegate** +Binding free/member functions sets two pointers; binding a functor stores its address (non-owning). + +**inplace_function** +Constructs a copy/move of the callable into the SBO buffer; more work up front. + +### Memory footprint and cache locality +**delegate** +~2 pointers regardless of target; high container density and good cache locality. + +**inplace_function** +Buffer + vtable pointer + object pointer; larger, size depends on Object_Size/Object_Alignment. + +### Clear / reset cost +**delegate** +Clears pointers; no destructor invocation. + +**inplace_function** +May run callable’s destructor; potentially non-trivial. + +### Determinism / Real-time suitability +**delegate** +Very predictable and minimal costs at call/copy/reset; good for ISR/RT paths. + +**inplace_function** +Deterministic at call; copy/move/reset depend on callable’s traits (still allocation-free). + +## Rule of thumb +- Use `delegate` when: + You only bind free/member functions or non-owning functors and want the smallest handle with the cheapest copies. + +- Use `inplace_function` when: + You must own captured state safely (value semantics) and still avoid the heap; accept slightly larger handle/copy costs for safety. + +## Choose etl::delegate when +- You need the smallest possible callable handle (two pointers) for large arrays/vectors of callbacks. +- You must avoid any allocation, construction, destruction, or SBO buffer management in the callable wrapper. +- You bind free functions or member functions and the target object’s lifetime is externally guaranteed. +- You want trivial copy/move/equality semantics (copy two pointers; compare stub+object) for fast shuffling/lookup. +- You need deterministic, RT/ISR-safe behavior with no hidden destructors or move/destruct paths on clear/reset. +- You build static/ROM lookup tables of callbacks (compile-time create(), create()). +- You store callbacks in fixed-capacity containers (etl::array/vector) and must minimize memory per element. +- You need ABI-stable, non-owning callback tokens passed across modules without copying callables. +- You already use etl::delegate_service or similar indexed dispatch; its API expects etl::delegate. +- You don't want to size/tune an inline buffer (Object_Size/Object_Alignment) per signature or platform. + +### Typical scenarios +- Interrupt vectors, GPIO/event ISR callbacks, hard real-time control loops. +- Command/ID -> handler tables, message routing switchboards, state-machine transition actions. +- Global registries/singletons where handler objects are static or live for program lifetime. +- Shared tables of callbacks across DLLs/modules where owning captured state is undesirable. + +### Why etl::delegate over etl::inplace_function in these cases +- Lower footprint: always two pointers versus user-sized SBO buffer + vtable pointer + object pointer. +- Lower copy/move cost: trivial POD-like copies; no callable copy/move/dtor required. +- Non-owning by design: avoids accidental copies of heavy callables; no lifetime surprises at clear/reset. +- Compile-time binding support: completely payload-free delegates for fixed targets (no storage touched). +- Equality: pointer-based equality lets you deduplicate/lookup handlers efficiently. + +### Notes +- `etl::delegate` is non-owning; only choose it when the bound object outlives the delegate (rvalue lambdas are rejected by API). +- Prefer `etl::inplace_function`0 when you must own captured state (value semantics) or need to accept arbitrary lambdas safely. + +## Choose etl::inplace_function when +- You need value semantics (own the callable) so lifetimes are safe without tracking external objects. +- You want to accept arbitrary lambdas with captures and store them inline using small-buffer optimization (no heap). +- You need a single uniform callable wrapper that erases the concrete type across modules/APIs. +- You plan to copy/move callbacks between threads/queues safely (callable is self-contained in the buffer). +- You must avoid dynamic allocation but still need to store captured state (tune Object_Size/Object_Alignment). +- You want compile-time or run-time binding to free functions, member functions, and functors in one type. +- You need reset/clear semantics that correctly destroy the stored callable (RAII). +- You prefer exceptions on misuse (invoking uninitialized) to surface bugs early. + +### Typical scenarios +- Job systems, task queues, and executors that capture small state per task without heap churn. +- Pipelines and event buses that accept user-provided lambdas with captures. +- Configurable command tables where handlers carry lightweight configuration/state. +- Deferred work items, timeouts, and continuations stored in fixed-capacity containers. +- API boundaries returning/storing callbacks where the provider shouldn't manage the callee's lifetime. + +### Why etl::inplace_function over etl::delegate in these cases +- Ownership: inplace_function owns the callable; no external lifetime management needed. +- Safety with captures: stores copies/moves of lambdas/functors; no dangling pointers to external objects. +- Uniform wrapper: a single type covers free/member/functor targets with the same call site and storage. +- No heap: SBO avoids allocations while still allowing captured state; predictable embedded-friendly footprint. +- Destruction: clear()/reset() run the callable's destructor when needed; no leaks or latent state. + +### Notes +- Tune the buffer size/alignment to the largest expected callable; too-small buffers will `static_assert`. +- Copy/move cost depends on the callable; prefer lightweight captures for best performance. +- Invocation overhead is one indirect call through a vtable stub (similar to delegate). +- Use make_inplace_function helpers or create<> to bind targets; is_valid(), call_if(), and call_or() are available. +- If you only bind free/member functions and can guarantee lifetimes, etl::delegate is smaller and cheaper to copy. diff --git a/docs/callbacks/delegate.md b/docs/callbacks/delegate.md new file mode 100644 index 00000000..f3dd7bc6 --- /dev/null +++ b/docs/callbacks/delegate.md @@ -0,0 +1,406 @@ +--- +title: "delegate" +--- + +{{< callout type="info">}} + Header: `delegate.h` + Since: `TBC` + Similar to: [std::function_ref](https://en.cppreference.com/w/cpp/utility/functional/function_ref.html) +{{< /callout >}} + +`etl::delegate` is a type-safe, generic, and efficient delegate implementation. A delegate is essentially a type-safe function pointer. + +It can be used to encapsulate a callable unit (like a function, a function pointer, member function, or a callable object like a functor or a lambda function) and call it later. + +`etl::delegate` is similar in some ways to `std::function_ref` introduced with C++26. + +The delegate functions may be defined at compile time and/or runtime, depending on the function type. +Most delegates can only be constructed via a `create` function, except lambdas and functors, which can be created by the delegate constructor. + +This may be used to implement a platform abstraction layer that allows an embedded application to interface with multiple hardware platforms. + +Here's a high-level overview of how `etl::delegate` works: + +**Creation** +When you create a delegate, you specify the function signature that it should match. This is done using template parameters. For example, `etl::delegate` creates a delegate that can hold references to functions that take an integer as an argument and return `void`. + +**Assignment** +You can assign a function to the delegate using the create method. The function you assign must match the delegate's function signature. For example, if you have a delegate of type `etl::delegate`, you could assign a function `void myFunction(int)` to it like this: + +`auto myDelegate = etl::delegate::create();` + +**Invocation** +Once a function has been assigned to the delegate, you can call that function through the delegate just like you would call a regular function. For example, if `myDelegate` is a delegate that holds a reference to `myFunction`, you could call myFunction through the delegate like this: `myDelegate(123);` + +## Notes +`<=20.21.0` +This class only supports >=C++11. + +--- + +`>=20.22.0` +This class is automatically selects C++03 or C++11 versions based on the value of `ETL_USING_CPP11` +The C++03 variant only supports delegates taking 0 or 1 parameters. + +`etl::delegate` is non-owning. You cannot use lambdas that capture variables that will have gone out of scope when the delegate is called. This would result in dangling references. Lambdas are not copied; The delegate merely keeps pointers to lambdas. This also applies to functors. + +--- + +`>=20.40.0` +Move constructors from lambdas or functors are disabled, thereby stopping a delegate being created from a temporary defined in a parameter. + +`>=20.42.0` +`etl::delegate` is `noexcept` + +--- + +`>=20.47.0` +A delegate can be created from a run-time global function pointer, or a non-capturing lambda. + +--- + +`>=20.22.0` +*For C++03* +`etl::delegate` +`etl::delegate` + +For the examples below, assume the following definitions. + +```cpp +class Test +{ +public: + + int member_function(int); + static int member_static(int); + int operator()(int); + int operator()(int) const; +}; + +Test test; + +int global(int); + +auto lambda = [](int i){ return i; }; +``` + +**Public types** + +```cpp +return_type TReturn 20.43.0 +argument_types etl::type_list 20.43.0 +``` + +### Run time construction + +**Lambdas** +```cpp +etl::delegate d(lambda); +etl::delegate d = lambda; +etl::delegate d = etl::delegate::create(lambda); + +d.set(lambda); +``` + +**Functors** +```cpp +etl::delegate d(test); +etl::delegate d = test; +etl::delegate d = etl::delegate::create(test); + +d.set(); +``` + +**Member functions** +```cpp +etl::delegate d = etl::delegate::create(test); + +d.set(test); +d.set(); +``` + +### Compile time construction + +**Global functions** +```cpp +auto d = etl::delegate::create(); +``` + +**Member functions** (if the instance is known at compile time) +```cpp +auto d = etl::delegate::create(); // Deprecated +auto d = etl::delegate::create(); // New +``` + +**Functors** (if the instance is known at compile time) +```cpp +auto d = etl::delegate::create(); +auto d = etl::delegate::create(); +``` +Note: These are disabled for GCC <= v8.1 as it generates an 'Internal Compiler Error'. + +**Static member functions** +```cpp +auto d = etl::delegate::create(); +``` + +**Global functions or non-capturing lambdas** +*From 20.47.0* +```cpp +auto d = etl::delegate::create(+[](int a){ return a * 2; }) +``` + +### Constexpr + +Most delegates can be declared as `constexpr`. (C++11 and above) +```cpp +static Test test; +constexpr auto d = etl::delegate::create(); +``` + +All create functions are `constexpr` under C++14. +All create functions are `[[nodiscard]]` under C++17. + +### Calling the delegate + +The delegate may be called as a function with the defined parameter signature. + +```cpp +etl::delegate d; + +int r = d(3); +``` + +## Types + +`return_type` The return type of the callback. +`argument_types` An `etl::type_list` of the arguments. + +## Constructors + +```cpp +ETL_CONSTEXPR14 delegate() ETL_NOEXCEPT +``` +**Description** +Constructs an uninitialised delegate. + +--- + +```cpp +ETL_CONSTEXPR14 delegate(const delegate& other) ETL_NOEXCEPT +``` +**Description** +Copy constructs a delegate. + +--- + +```cpp +delegate(TReturn (*)(TArgs...) fp) ETL_NOEXCEPT +``` +**Description** +Constructs from a run-time function pointer, or non-capturing lambda converted to a function pointer. +*From `20.47.0`* + +## Creation + +```cpp +template +ETL_NODISCARD +static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT +``` +**Description** +Create from a global function (Compile time). + +**Returns** +A constructed delegate. + +--- + +```cpp +ETL_NODISCARD +static delegate create(function_ptr fp) ETL_NOEXCEPT +``` +**Description** +Create from a run-time function pointer. +*From `20.47.0`* + +**Returns** +A constructed delegate. + +--- + +```cpp +template +ETL_NODISCARD +static ETL_CONSTEXPR14 delegate create(TLambda& instance) ETL_NOEXCEPT +``` +**Description** +Create from lambda or functor. + +**Returns** +A constructed delegate. + +## Calling the delegate + +```cpp +ETL_CONSTEXPR14 TReturn operator()(TParams... args) const ETL_NOEXCEPT +``` +**Description** +Calls the delegate. +`constexpr` from `20.42.1` + +--- + +20.17.0 +```cpp +ETL_CONSTEXPR14 bool call_if(TParams... args) const ETL_NOEXCEPT +``` +**Description** +For delegates returning void. +Calls the delegate if valid. +Returns `true` if valid, otherwise `false`. +`constexpr` from `20.42.2` + +--- + +```cpp +ETL_CONSTEXPR14 etl::optional call_if(TParams... args) const ETL_NOEXCEPT +``` +**Description** +For delegates returning `TReturn`. +Calls the delegate if valid. +Returns a valid `etl::optional` containing the return value, if valid. +`constexpr` from `20.42.2` + +--- + +20.17.0 +```cpp +template +ETL_CONSTEXPR14 TReturn call_or(TAlternative alternative, TParams... args) const ETL_NOEXCEPT +``` +**Description** +Calls the delegate if valid, otherwise calls `alternative`. +`constexpr` from `20.42.2` + +--- + +```cpp +template +ETL_CONSTEXPR14 TReturn call_or(TParams... args) const ETL_NOEXCEPT +``` +**Description** +Calls the delegate if valid, otherwise calls `Method`. + +## Modifiers + +```cpp +void clear() ETL_NOEXCEPT +``` +**Description** +Sets the delegate back to the uninitialised state. + +## Status + +```cpp +ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT +ETL_CONSTEXPR14 operator bool() const +``` +**Description** +Returns true if the delegate has been initialised, otherwise `false`. + +--- + +```cpp +ETL_CONSTEXPR14 operator =() ETL_NOEXCEPT +``` +**Description** +Assigns from a delegate or lambda. + +--- + +```cpp +ETL_CONSTEXPR14 operator ==() ETL_NOEXCEPT +ETL_CONSTEXPR14 operator !=() ETL_NOEXCEPT +``` +**Description** +Compares delegates. + +## Make a delegate + +```cpp +make_delegate +``` +**Description** +For C++17 and above. +`20.39.5` + +--- + +```cpp +template +constexpr auto make_delegate() noexcept +``` +**Description** +Make a delegate from a free function. +Returns `etl::delegate::create()` + +--- + +```cpp +template +constexpr auto make_delegate(TLambda& instance) noexcept +``` +**Description** +Make a delegate from a functor or lambda function. +Returns `etl::delegate(instance)` + +--- + +```cpp +template +constexpr auto make_delegate() noexcept +``` +**Description** +Make a delegate from a functor, compile time. +Returns `etl::delegate::create()` + +--- + +```cpp +template +constexpr auto make_delegate() noexcept +``` +**Description** +Make a delegate from a member function at compile time. +Returns `etl::delegate::create()` + +--- + +```cpp +template +constexpr auto make_delegate() noexcept +``` +**Description** +Make a delegate from a const member function at compile time. +Returns `etl::delegate::create()` + +--- + +```cpp +template +constexpr auto make_delegate(T& instance) noexcept +``` +**Description** +Make a delegate from a member function at run time. +Returns `etl::delegate::create(instance)` + +--- + +```cpp +template +constexpr auto make_delegate(const T& instance) noexcept +``` +**Description** +Make a delegate from a member function at run time. +Returns `etl::delegate::create(instance)` diff --git a/docs/callbacks/delegate_observable.md b/docs/callbacks/delegate_observable.md new file mode 100644 index 00000000..2b9249a4 --- /dev/null +++ b/docs/callbacks/delegate_observable.md @@ -0,0 +1,115 @@ +--- +title: "delegate_observable" +--- + +{{< callout type="info">}} + Header: `delegate_observable.h` + Since: `TBC` +{{< /callout >}} + +`etl::delegate_observable` is a variation on the observer pattern idea, but using delegates as the callback mechanism. + +```cpp +template +class delegate_observable +``` + +`TNotification` is the notification type. +`Max_Observers` is the maximum number of observers that can be handled. + +## Template deduction guide + +```cpp +template +delegate_observable(TNotification, TDelegates...) + -> delegate_observable; +``` + +**Example** +```cpp +etl::delegate delegate1; +etl::delegate delegate2; + +etl::delegate_observable observable(int{}, delegate1, delegate2); +``` + +## Public types + +| Type | Description | +| ------------------- | ------------------------------------------- | +| `delegate_type` | The type of delegate used in this observer. | +| `size_type` | The type used internally for sizes. | +| `notification_type` | The type of the notification. | + +## Construction + +```cpp +ETL_CONSTEXPR14 delegate_observable() +``` +**Description** +Default constructor. + +--- + +```cpp +template +ETL_CONSTEXPR14 delegate_observable(TDelegate&&... delegates) +``` +**Description** +Construct from a collection of observers. + +--- + +```cpp +template +ETL_CONSTEXPR14 delegate_observable(notification_type, TDelegate&&... delegates) +``` +**Description** +Construct from notification type and a list of observers. +Variant for template deduction guide. +The notification value is ignored. It is here to allow deduction of the notification type for the template deduction guide. + +## Modifiers + +```cpp +ETL_CONSTEXPR14 bool add_observer(delegate_type observer) +``` +**Description** +Add an observer to the list. + +**Return** +`true` if the observer was removed, `false` if not. + +--- + +```cpp +ETL_CONSTEXPR14 bool remove_observer(const delegate_type& observer) +``` +**Description** +Remove a particular observer from the list. +**Return** +`true if the observer was removed, false if not. + +--- + +```cpp +ETL_CONSTEXPR14 void clear_observers() +``` +**Description** +Clear all observers. + +## Status + +```cpp +ETL_CONSTEXPR14 size_type number_of_observers() const +``` +**Return** +The number of observers. + +## Notofication + +```cpp +ETL_CONSTEXPR14 void notify_observers(notification_type n) const +``` +**Description** +Notify all of the observers, sending them the notification. diff --git a/docs/callbacks/function.md b/docs/callbacks/function.md new file mode 100644 index 00000000..7785b0f1 --- /dev/null +++ b/docs/callbacks/function.md @@ -0,0 +1,332 @@ +--- +title: "function" +--- + +{{< callout type="warning">}} + Deprecated: Please use the more versatile `etl::delegate` or `etl::inplace_function` classes instead. +{{< /callout >}} + +{{< callout type="info">}} + Header: `function.h` + Since: `TBC` +{{< /callout >}} + +A set of wrapper templates to allow a member or static function to be called without the caller having to know the specific details of the callee apart from the parameter type. The templates allow the called function to be abstracted. + +This may be used to implement a platform abstraction layer that allows an embedded application to interface with multiple hardware platforms. + +| Template | Description | +| ----------------- | ------------------------------------------------------------------------- | +| etl::function | Callbacks to free or member functions taking zero or one parameter.
Function pointer at runtime. | +| etl::function_fv | Callback to a free function taking no parameters. (Functiion Void).
Function pointer at compile time. | +| etl::function_fp | Callback to a free function taking one parameter. (Function Parameter).
Function pointer at compile time. +| etl::function_mv | Callback to a member function taking no parameters. (Member Void).
Function pointer at compile time. | +| etl::function_imv | Callback to a member function taking no parameters. (Instance Member Void ).
Instance reference and function pointer at compile time. | +| etl::function_mp | Callback to a member function taking one parameter. (Member Parameter).
Function pointer at compile time.| +| etl::function_imp | Callback to a member function taking one parameter. (Instance Member Parameter).
Instance reference and function pointer at compile time.| + +*Instances of any of these types may be passed as pointers or references to etl::ifunction.* + +## Interface classes. + +```cpp +template +class ifunction +``` +**Description** +Interface class for a function taking one parameter. + +--- + +```cpp +template <> +class ifunction +``` +**Description** +Interface class for a function taking no parameters. + +**All of the following classes are derived from the above interface classes.** + +## Function address at run time. +The functions are called indirectly through an internal pointer. + +```cpp +template +class function : public ifunction +``` +**Description** +Class for a member function taking one parameter. + +--- + +```cpp +template +class function : public ifunction +``` +**Description** +Class for a member function taking no parameters. + +```cpp +template +class function : public ifunction +``` +**Description** +Class for a free function taking one parameter. + +--- + +```cpp +template <> +class function : public ifunction +``` +**Description** +Class for a free function taking no parameters. + +## Function address at compile time. +These will be more efficient than the previous definitions, as the one level of indirection is eliminated. + +```cpp +template +class function_mv : public ifunction +``` +**Description** +Class for a member function taking no parameters. + +--- + +```cpp +template +class function_imv : public ifunction +``` +**Description** +Class for a member function taking no parameters. + +--- + +```cpp +template +class function_mp : public ifunction +``` +**Description** +Class for a member function taking one parameter. + +--- + +```cpp +template +class function_imp : public ifunction +``` +**Description** +Class for a member function taking one parameter. + +--- + +```cpp +template +class function_fv : public ifunction +``` +**Description** +Class for a free function taking no parameters. + +--- + +```cpp +template +class function_fp : public ifunction +``` +**Description** +Class for a free function taking one parameter. + +## Example + +```cpp +etl::function +``` + +These templates are designed to enable easy creation of callbacks to global, static and class member functions without the caller having to know which type actually it is. + +One use that is applicable to embedded platforms is to use them connect interrupt vectors to class member handling functions. Particularly useful when the code is applicable to multiple targets devices. + +The template is designed in such a way that the caller does not need to be aware of the type of the callee. + +The caller declares an instance of `etl::function` or one of its variants. The caller defines a pointer or reference to an `etl::ifunction`. This pointer or reference will be initialised with the instance defined in the caller. + +**Example** + +The interrupt vector table contains entries for three timer timeouts and two uart character rx handlers. These are vectored to normal static functions. + +```cpp +void Timer1TimeoutInterrupt(); +void Timer2TimeoutInterrupt(); +void Timer3TimeoutInterrupt(); +void Uart1RxInterrupt(); +void Uart2RxInterrupt(); +``` + +The timer timeout interrupts are handled by an instance of the class `Timer` and the free function `FreeTimerInterruptHandler`. The UART Rx interrupts are handled by instances of the class `Uart`. + +`Timer1` interrupts call the member function of an instance of `Timer`. +`Timer2` interrupts call the static member function of `Timer`. +`Timer3` interrupts call the free function `FreeTimerInterruptHandler`. +`UART1` interrupts call the member function of instance 1 of `Uart`. +`UART1` interrupts call the member function of instance 2 of `Uart`. + +```cpp +#include +#include + +#include "function.h" + +//******************************** +// Fake UART Rx register. +//******************************** +char get_char() +{ + static char c = 'A'; + return c++; +} + +//******************************** +// Interrupt vectors & callbacks. +//******************************** +// Callback interfaces. +// Note that they do not require any knowledge about the callee apart from the parameter type. +etl::ifunction* timer1_callback; // A pointer to a callback taking no parameters. +etl::ifunction* timer2_callback; // A pointer to a callback taking no parameters. +etl::ifunction* timer3_callback; // A pointer to a callback taking no parameters. +etl::ifunction* uart1_rx_callback; // A pointer to a callback taking a char parameter. +etl::ifunction* uart2_rx_callback; // A pointer to a callback taking a char parameter. + +extern "C" +{ +// Function called from the timer1 interrupt vector. +void Timer1Interrupt() +{ + (*timer1_callback)(); +} + +// Function called from the timer2 interrupt vector. +void Timer2Interrupt() +{ + (*timer2_callback)(); +} + +// Function called from the timer3 interrupt vector. +void Timer3Interrupt() +{ + (*timer3_callback)(); +} + +// Function called from the UART1 rx interrupt vector. +void Uart1RxInterrupt() +{ + (*uart1_rx_callback)(get_char()); +} + +// Function called from the UART2 rx interrupt vector. +void Uart2RxInterrupt() +{ + (*uart2_rx_callback)(get_char()); +} +} + +//******************************** +// Timer driver. +//******************************** +class Timer +{ +public: + + // Constructor. + Timer() + { + } + + // Handler for interrupts from the timer. + void MemberTimerInterruptHandler() + { + std::cout << "Timer interrupt (member)\n"; + } + + // Static handler for interrupts from the timer. + static void StaticTimerInterruptHandler() + { + std::cout << "Timer interrupt (static)\n"; + } +}; + +//******************************** +// Free function timer driver. +//******************************** +void FreeTimerInterruptHandler() +{ + std::cout << "Timer interrupt (free)\n"; +} + +etl::function_fv free_callback; + +//******************************** +// UART driver. +//******************************** +class Uart +{ +public: + + // Constructor. + Uart(int port_id) + : port_id(port_id) + { + } + + // Handler for rx interrupts from the UART. + void RxInterruptHandler(char c) + { + std::cout << "UART" << port_id << " Rx char interrupt : Received '" << c << "'\n"; + } + + int port_id; +}; + +// Declare the driver instances. +Timer timer; +Uart uart1(0); +Uart uart2(1); + +etl::function_imv timer_member_callback; +etl::function_fv<&Timer::StaticTimerInterruptHandler> timer_static_callback; +etl::function_imp uart1_callback; +etl::function_imp uart2_callback; + +//******************************** +// Test it out. +//******************************** +int main() +{ + + // Setup the callbacks. + timer1_callback = &timer_member_callback; + timer2_callback = &timer_static_callback; + timer3_callback = &free_callback; + uart1_rx_callback = &uart1_callback; + uart2_rx_callback = &uart2_callback; + + // Simulate the interrupts. + Timer1Interrupt(); + Timer2Interrupt(); + Timer3Interrupt(); + Uart1RxInterrupt(); + Uart2RxInterrupt(); + + return 0; +} +``` diff --git a/docs/callbacks/inplace_function.md b/docs/callbacks/inplace_function.md new file mode 100644 index 00000000..6e675a54 --- /dev/null +++ b/docs/callbacks/inplace_function.md @@ -0,0 +1,414 @@ +--- +title: "inplace_function" +weight: 1 +--- + +{{< callout type="info">}} + Header: `inplace_function.h` + From: `20.45.0` + Similar to: [std::function](https://en.cppreference.com/w/cpp/utility/functional/function.html) +{{< /callout >}} + +A small, in-place function wrapper that stores callable objects inside a fixed-size buffer (no dynamic allocation). It supports free functions, member functions, functors, and lambdas, with both runtime and compile-time bindings. + +```cpp +template +class inplace_function; +``` + +The defaults are defined as follows:- + +```cpp +#if !defined(ETL_DEFAULT_INPLACE_FUNCTION_SIZE) + #define ETL_DEFAULT_INPLACE_FUNCTION_SIZE 32 +#endif +``` + +```cpp +#if !defined(ETL_DEFAULT_INPLACE_FUNCTION_ALIGNMENT) + #define ETL_DEFAULT_INPLACE_FUNCTION_ALIGNMENT alignof(void*) +#endif +``` + +Set your own definitions if you require different defaults. + +## Template Parameters + +```cpp +TSignature +``` +**Description** +The function signature. e.g. `int(char, float)` + +--- + +```cpp +Object_Size +``` +**Description** +Size of the internal storage buffer. +Defaults to `ETL_DEFAULT_INPLACE_FUNCTION_SIZE`. + +--- + +```cpp +Object_Alignment +``` +**Description** +Alignment of the internal storage buffer. +Defaults to `ETL_DEFAULT_INPLACE_FUNCTION_ALIGNMENT`. + +## Exceptions + +```cpp +etl::inplace_function_exception +``` +**Description** +Base exception. + +--- + +```cpp +etl::inplace_function_uninitialized +``` +**Description** +Thrown (via `ETL_ASSERT`) when invoked without a target. + +## Member Types + +```cpp +function_type +``` +**Description** + +--- + +```cpp +return_type +``` +**Description** + +--- + +```cpp +argument_types +``` +**Description** + +## Constructors + +**Description** +Default constructor. + +**Description** +Copy/move constructors. + +**Description** +Construction from a free function pointer. + +**Description** +Construction from an object + member function pointer (const or non-const). + +**Description** +Construction from a lambda/functor (const or non-const). + +## Assignment + +**Description** +Copy/move assignment. + +--- + +**Description** +Assignment from nullptr clears the target. + +--- + +**Description** +Assignment from function pointer. + +--- + +**Description** +Assignment from lambda/functor. + +## Invocation + +```cpp +operator() +``` +**Description** +Invokes the bound callable and asserts if uninitialised. + +**Parameters** + +**Returns** + +--- + +```cpp +call_if(...) +``` +**Description** +Calls the delegate function, if valid. +Indicates success in the return type. + +**Parameters** +`TArgs...` + +**Returns** +For `void` return `bool` indicating whether it executed. +For non-void returns `etl::optional`. + +--- + +```cpp +call_or(...) +``` +**Description** +Invokes the target or a fallback callable. + +**Parameters** + +**Returns** + +## Observers + +```cpp +bool is_valid() const +``` +**Returns** +`true` if there is a valid callable. + +--- + +```cpp +explicit operator bool() const +``` +**Description** + +**Parameters** + +**Returns** +The result of `is_valid()` + +## Modifiers + +```cpp +void clear() +``` +**Description** +Clears any stored callable. + +**Parameters** +None + +**Returns** +`void` + +--- + +```cpp +void swap(inplace_function& other) +``` +**Description** +Swaps with another inplace_function. + + +**Parameters** +None + +**Returns** +'void` + +## Storage Introspection + +```cpp +static constexpr size_t size() +``` +**Description** +Interogates the internal storage size. + +**Parameters** +None + +**Returns** +The size of the internal storage. + +--- + +```cpp +static constexpr size_t alignment() +``` +**Description** +Interogates the internal storage alignment. + +**Parameters** +None + +**Returns** +The alignment of the internal storage. + +## Compile-Time Binding (No Payload) + +### Free function + +```cpp +template +void set() +``` +**Description** +Sets the callable to `Function`. + +--- + +```cpp +template +inplace_function create() +``` +**Description** +Creates an `etl::inplace_function` using `Function`. + +--- + +### Member function + instance (external linkage) + +```cpp +template +set() +``` +**Description** +Sets the callable to the member function `Method` for the object `Instance`. + +--- + +```cpp +create() +``` +**Description** + +**Parameters** + +**Returns** + +--- + +### Callable object + instance (operator()) + +```cpp +set() +``` +**Description** + +**Parameters** + +**Returns** + +--- + +```cpp +create() +``` +**Description** + +**Parameters** + +**Returns** + +## Helper Aliases + +```cpp +etl::inplace_function_for +``` +**Description** + +**Parameters** + +**Returns** + +--- + +```cpp +etl::inplace_function_for_any +``` +**Description** + +**Parameters** + +**Returns** + +## Helper Factories + +```cpp +make_inplace_function(function_ptr) +``` +**Description** + +**Parameters** + +**Returns** + +```cpp +make_inplace_function(obj, &Type::Method) +``` +**Description** + +**Parameters** + +**Returns** + +```cpp +make_inplace_function(lambda_or_functor) +``` +**Description** + +```cpp +make_inplace_function(function_like) +``` +**Description** + +**Parameters** + +**Returns** + +C++17-only overloads also exist for compile-time binding. + +## Example + +```cpp +#include "etl/inplace_function.h" + +int add(int a, int b) { return a + b; } + +struct Accumulator +{ + int base = 0; + + int add_to(int v) { return base + v; } +}; + +void example() +{ + etl::inplace_function f(add); + int sum = f(1, 2); + + Accumulator acc{ 10 }; + + etl::inplace_function g(&Accumulator::add_to, acc); + + int result = g(5); +} +``` + +## Notes + +If the callable object is larger than `Object_Size` or requires stricter alignment than `Object_Alignment`, compilation fails with a `static_assert`. + + +`operator()` asserts when called without a target; use `call_if` or `call_or` to avoid this. + +Prefer `inplace_function_for`, `inplace_function_for_any` or `make_inplace_function` to deduce storage sizes safely. diff --git a/docs/callbacks/signal.md b/docs/callbacks/signal.md new file mode 100644 index 00000000..a8c19efc --- /dev/null +++ b/docs/callbacks/signal.md @@ -0,0 +1,327 @@ +--- +title: "signal" +--- + +{{< callout type="info">}} + Header: `signal.h` + From: `20.44.0` +{{< /callout >}} + +A class that implements simple signal/slot framework. +Uses `etl::delegate` as the default slot type, though other types may be used. + +```cpp +template > +class signal +``` +`TFunction` The callback function signature. +`Size` The maximum numbr of slots for the signal. +`TSlot` The callback slot type. Default = `etl::delegate` + +## Types +`slot_type` Defined as the slot type. +`size_type` The size type used internally. +`span_type` The span type used in the connect API. + +## Constructors +```cpp +template +ETL_CONSTEXPR14 explicit signal(TSlots&&... slots) ETL_NOEXCEPT +``` +Construct the signal from a variadic list of slots. +Can be used as a `constexpr` constructor. +Static asserts if any of the slots are not `slot_type`. +Static asserts if the number of slots exceeds capacity. + +## Connect +```cpp +bool connect(const slot_type& slot) +``` +Connects the slot, if not already connected and returns `true`. +If the signal is full, asserts `etl::signal_full` and returns `false`. + +--- + +```cpp +bool connect(std::initializer_list slots) +``` +Connects all of the slots and returns `true`. +If the number of slots exceeds the signal's max size, asserts an `etl::signal_full` and returns `false`. +Enabled if `ETL_HAS_INITIALIZER_LIST` and `ETL_USING_CPP17` are defined as `1`. + +--- + +```cpp +bool connect(const span_type slots) +``` +Connects all of the slots and returns `true`. +If the number of slots exceeds the signal's max size, asserts an `etl::signal_full` and returns `false`. + +## Disconnect + +```cpp +void disconnect(const slot_type& slot) ETL_NOEXCEPT +``` +Disconnects slot from the signal. +If the signal does not contain the slot there is no error. + +--- + +```cpp +void disconnect(std::initializer_list slots) ETL_NOEXCEPT +``` +Disconnects all of the slots from the signal. +If the signal does not contain a particular slot, there is no error. +Enabled if `ETL_HAS_INITIALIZER_LIST` and `ETL_USING_CPP17` are defined as `1`. + +--- + +```cpp +void disconnect(const span_type slots) ETL_NOEXCEPT +``` +Disconnects all of the slots from the signal. +If the signal does not contain a particular slot, there is no error. + +```cpp +void disconnect_all() ETL_NOEXCEPT +``` +Disconnects all slots from the signal. + +## Status + +```cpp +ETL_CONSTEXPR14 bool connected(const slot_type& slot) const ETL_NOEXCEPT +``` +Checks if a slot is connected to the signal. + +--- + +```cpp +ETL_CONSTEXPR14 bool empty() const ETL_NOEXCEPT +``` +Return `true` if the signal has no slots connected. + +--- + +```cpp +ETL_CONSTEXPR14 bool full() const ETL_NOEXCEPT +``` +Return `true` if the signal has the maximum number of slots connected. + +--- + +```cpp +ETL_CONSTEXPR14 size_type max_size() const ETL_NOEXCEPT +``` +Returns the total number of slots that can be connected. + +--- + +```cpp +ETL_CONSTEXPR14 size_type size() const ETL_NOEXCEPT +``` +Returns the total slots currently connected. + +--- + +```cpp +ETL_CONSTEXPR14 size_type available() const ETL_NOEXCEPT +``` +Returns the total empty slots available. + +## Call +```cpp +template +void operator()(TArgs&&... args) const ETL_NOEXCEPT +``` +Function operator that calls each slot with the supplied parameters. + +## Errors + +```cpp +etl::signal_full +``` +Indicates that an attempt to add a slot to a full signal occurred. +Inherits from `etl::signal_exception`. + +## Examples + +```cpp +constexpr size_t MaxSlots = 3; + +using callback_type = void(int a, int b); +using signal_type = etl::signal; +using slot_type = signal_type::slot_type; +using span_type = signal_type::span_type; + +using not_slot_type = etl::delegate; +``` + +**Defining the slot functions** + +```cpp +void Function1(int a, int b) +{ + std::cout << "Function1: " << a << "," << b << "\n"; +} + +void Function2(int a, int b) +{ + std::cout << "Function2: " << a << "," << b << "\n"; +} + +void Function3(int a, int b) +{ + std::cout << "Function3: " << a << "," << b << "\n"; +} +0 +void Function4(int a, int b) +{ + std::cout << "Function4: " << a << "," << b << "\n"; +} + +void Function5(int a) +{ + std::cout << "Function5: " << a << "\n"; +} +``` + +**Creating the slots** + +```cpp +constexpr slot_type MakeSlot1() noexcept +{ +return slot_type::create(); +} + +constexpr slot_type MakeSlot2() noexcept +{ +return slot_type::create(); +} + +constexpr slot_type MakeSlot3() noexcept +{ +return slot_type::create(); +} + +constexpr slot_type MakeSlot4() noexcept +{ +return slot_type::create(); +} + +constexpr not_slot_type MakeSlot5() noexcept +{ +return not_slot_type::create(); +} +``` + +**Define the signals as `constexpr`** + +```cpp +// Define the signal and connect as constexpr +constexpr signal_type({ MakeSlot1(), MakeSlot2(), MakeSlot3() }); + +// Define the signal and connect as constexpr. +// Static assert "Number of slots exceeds capacity" +constexpr signal_type({ MakeSlot1(), MakeSlot2(), MakeSlot3(), MakeSlot4() }); + +// Define the signal and connect as constexpr. +// Static assert "All slots must be slot_type" +constexpr signal_type({ MakeSlot1(), MakeSlot2(), MakeSlot5() }); +``` + +**Defining the signal at runtime** + +```cpp +// Define the signal. +signal_type signal; + +// Connect one at a time. +signal.connect(MakeSlot1()); +signal.connect(MakeSlot2()); +signal.connect(MakeSlot3()); + +// Connect using initializer_list. +signal.connect({ MakeSlot1(), MakeSlot2(), MakeSlot3() }); + +// Connect using span. +const slot_type slot_list[] = { MakeSlot1(), MakeSlot2(), MakeSlot3() }; +signal.connect(slot_list); +``` + +**Checking the status** + +```cpp +// Define the signal. +signal_type signal; + +signal.max_size() // Returns 3 +signal.size() // Returns 0 +signal.available() // Returns 3 +signal.empty(); // Returns true +signal.full(); // Returns false +signal.connected(MakeSlot1()) // Returns false +signal.connected(MakeSlot2()) // Returns false +signal.connected(MakeSlot3()) // Returns false + +signal.connect(MakeSlot1()); // Returns true + +signal.max_size() // Returns 3 +signal.size() // Returns 1 +signal.available() // Returns 2 +signal.empty(); // Returns false +signal.full(); // Returns false +signal.connected(MakeSlot1()) // Returns true +signal.connected(MakeSlot2()) // Returns false +signal.connected(MakeSlot3()) // Returns false + +signal.connect(MakeSlot1()); // Already connected. Returns true + +signal.max_size() // Returns 3 +signal.size() // Returns 1 +signal.available() // Returns 2 +signal.empty(); // Returns false +signal.full(); // Returns false +signal.connected(MakeSlot1()) // Returns true +signal.connected(MakeSlot2()) // Returns false +signal.connected(MakeSlot3()) // Returns false + +signal.connect(MakeSlot2()); // Returns true + +signal.max_size() // Returns 3 +signal.size() // Returns 2 +signal.available() // Returns 1 +signal.empty(); // Returns false +signal.full(); // Returns false +signal.connected(MakeSlot1()) // Returns true +signal.connected(MakeSlot2()) // Returns true +signal.connected(MakeSlot3()) // Returns false + +signal.connect(MakeSlot3()); // Returns true + +signal.max_size() // Returns 3 +signal.size() // Returns 3 +signal.available() // Returns 0 +signal.empty(); // Returns false +signal.full(); // Returns true +signal.connected(MakeSlot1()) // Returns true +signal.connected(MakeSlot2()) // Returns true +signal.connected(MakeSlot3()) // Returns true + +signal.connect(MakeSlot4()); // ETL_ASSERT etl::signal_full. Returns false +``` + +**Calling the signal** + +```cpp +signal_type signal({ MakeSlot1(), MakeSlot2(), MakeSlot3() }); + +signal(1, 2); // Call all of the slots with the parameters 1 & 2 +``` + +**Output** +``` +Function1: 1,2 +Function2: 1,2 +Function3: 1,2 +``` diff --git a/docs/chrono/_index.md b/docs/chrono/_index.md new file mode 100644 index 00000000..80e4e3df --- /dev/null +++ b/docs/chrono/_index.md @@ -0,0 +1,12 @@ +--- +title: "Chrono" +weight: 100 +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono](https://en.cppreference.com/w/cpp/chrono.html) +{{< /callout >}} + +An implementation of C++11's date and time library. diff --git a/docs/chrono/chrono-literals.md b/docs/chrono/chrono-literals.md new file mode 100644 index 00000000..76b3ed5e --- /dev/null +++ b/docs/chrono/chrono-literals.md @@ -0,0 +1,38 @@ +--- +title: "Chrono literals" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::literals::chrono_literals](https://en.cppreference.com/w/cpp/chrono.html#Literals) +{{< /callout >}} + +The ETL Chrono literals are define slightly differently from the STL in that they are *user* defined, as opposed to *language* defined. + +**Example** +For STL, the literal to define year `2025` would be `2025y`. +For ETL, the literal is `2025_y`. + +By default, the ETL uses the designations of the STL. +As this may clash with other user defined literals, the ETL allows more verbose forms to be used, by defining the macro `ETL_USE_VERBOSE_CHRONO_LITERALS`. +If enabled, the example of `2025_y` would be written as `2025_year`. + +| Duration type | STL like | Verbose | +| --------------------------- | ---------- | ------------------- | +| `etl::chrono::year` | `2025_y` | `2025_year` | +| `etl::chrono::day` | `10_d` | `10_day` | +| `etl::chrono::hours` | `14_h` | `14_hours` | +| `etl::chrono::minutes` | `30_min` | `30_minutes` | +| `etl::chrono::seconds` | `45_s` | `45_seconds` | +| `etl::chrono::milliseconds` | `500_ms` | `500_milliseconds` | +| `etl::chrono::microseconds` | `500_us` | `500_microseconds` | +| `etl::chrono::nanoseconds` | `500_ns` | `500_nanoseconds` | + +Chrono literals may by accessed by using one of the following namespaces. + +```cpp +using namespace etl::chrono; +using namespace etl::literals; +using namespace etl::chrono_literals; +``` diff --git a/docs/chrono/clocks.md b/docs/chrono/clocks.md new file mode 100644 index 00000000..9ca0fb3e --- /dev/null +++ b/docs/chrono/clocks.md @@ -0,0 +1,123 @@ +--- +title: "Clocks" +--- + +## Macros +Default macro definitions. +Define these in `etl_profile.h` to set your own duration types for the clocks. + +| Macro | Definition | +| -------------------------------------------- | -------------------------- | +| `ETL_CHRONO_SYSTEM_CLOCK_DURATION` | `etl::chrono::nanoseconds` | +| `ETL_CHRONO_SYSTEM_CLOCK_IS_STEADY` | `true` | +| `ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION` | `etl::chrono::nanoseconds` | +| `ETL_CHRONO_HIGH_RESOLUTION_CLOCK_IS_STEADY` | `true` | +| `ETL_CHRONO_STEADY_CLOCK_DURATION` | `etl::chrono::nanoseconds` | + +## Platform clock access +Declarations of the functions that must be defined to interface the clocks with the underlying platform. + +```cpp +extern "C" ETL_CHRONO_SYSTEM_CLOCK_DURATION::rep etl_get_system_clock(); +extern "C" ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION::rep etl_get_high_resolution_clock(); +extern "C" ETL_CHRONO_STEADY_CLOCK_DURATION::rep etl_get_steady_clock(); +``` + +These functions must return the current count of the underlying clock. The value is in terms of the +clock duration defined for that clock. + +**Example** +If the `system_clock` duration is set to `etl::chrono::nanoseconds`, then a return value of `1000` represents `1000ns`. + +## system_clock + +```cpp +class system_clock +``` + +### Member types +```cpp +using duration = ETL_CHRONO_SYSTEM_CLOCK_DURATION +using rep = duration::rep +using period = duration::period +using time_point = time_point +``` + +### Member functions +```cpp +static time_point now() ETL_NOEXCEPT +static time_t to_time_t(const time_point& t) ETL_NOEXCEPT +static time_point from_time_t(time_t t) ETL_NOEXCEPT +``` + +## high_resolution_clock +```cpp +class high_resolution_clock +``` + +### Member types +```cpp +using duration = ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION +using rep = duration::rep +using period = duration::period +using time_point = time_point +``` + +### Member functions +```cpp +static time_point now() ETL_NOEXCEPT +``` + +## steady_clock +```cpp +class steady_clock +``` + +### Member types +```cpp +using duration = ETL_CHRONO_STEADY_CLOCK_DURATION +using rep = duration::rep +using period = duration::period +using time_point = time_point +``` + +### Member functions +```cpp +static time_point now() ETL_NOEXCEPT +``` + +## system_time +```cpp +template +using sys_time = etl::chrono::time_point + +using sys_seconds = sys_time +using sys_days = sys_time +``` + +## local_time +```cpp +struct local_t +``` + +```cpp +template +using local_time = etl::chrono::time_point + +using local_seconds = local_time +using local_days = local_time +``` + +## clock_cast + +Cast a time point from one clock to another. +This implementation assumes all clock epochs are the same. + +```cpp +template +ETL_CONSTEXPR14 etl::chrono::time_point + clock_cast(const etl::chrono::time_point& from_time_point) ETL_NOEXCEPT +``` diff --git a/docs/chrono/day.md b/docs/chrono/day.md new file mode 100644 index 00000000..ec123908 --- /dev/null +++ b/docs/chrono/day.md @@ -0,0 +1,317 @@ +--- +title: "day" +--- + +{{< callout type="info">}} + Header: `chrono.h` + Since: `TBC` + Similar to: [std::chrono::day](https://en.cppreference.com/w/cpp/chrono/day.html) +{{< /callout >}} + +A class representing a day. + +```cpp +class day +``` + +## Typesdefs +rep The internal representation. + +## Construction +```cpp +ETL_CONSTEXPR +day() +ETL_NOEXCEPT +``` +**Description** +Default constructor. + +--- +```cpp +ETL_CONSTEXPR +explicit day(unsigned value) +ETL_NOEXCEPT +``` +**Description** +Construct from unsigned. + +--- + +```cpp +ETL_CONSTEXPR14 +day(const etl::chrono::day& other) +ETL_NOEXCEPT +``` +**Description** +Copy constructor. + +## Tests +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the day is within the valid range. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +int compare(const etl::chrono::day& other) const +ETL_NOEXCEPT +``` +**Description** +Compare `day` with another. +if `day < other`, returns `-1` +else if `day > other`, returns `1` +else returns `0` + +## Assignment +```cpp +ETL_CONSTEXPR14 +etl::chrono::day& operator =(const etl::chrono::day& rhs) +ETL_NOEXCEPT +``` +**Description** +Assignment operator + +## Increment/decrement +```cpp +ETL_CONSTEXPR14 +etl::chrono::day& operator ++() +ETL_NOEXCEPT +``` +**Description** +Pre-increment operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::day operator ++(int) +ETL_NOEXCEPT +``` +**Description** +Post-increment operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::day& operator --() +ETL_NOEXCEPT +``` +**Description** +Pre-decrement operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::day operator --(int) +ETL_NOEXCEPT +``` +**Description** +Post-decrement operator. + +## Mathematical operators +```cpp +ETL_CONSTEXPR14 +etl::chrono::day& operator +=(const etl::chrono::days& ms) +ETL_NOEXCEPT +``` +**Description** +Plus-equals operator adding etl::chrono::days. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::day& operator -=(const etl::chrono::days& ms) +ETL_NOEXCEPT +``` +**Description** +Minus-equals operator subtracting `etl::chrono::days`. + +## Conversion +```cpp +ETL_CONSTEXPR14 +operator unsigned() const +ETL_NOEXCEPT +``` +**Description** +Conversion operator to unsigned int. + +## Non-member mathematical operators +```cpp +ETL_CONSTEXPR14 +etl::chrono::day operator +(const etl::chrono::day& m, + const etl::chrono::days& ms) +ETL_NOEXCEPT +``` +**Description** +Add `etl::chrono::days` to `etl::chrono::day`. + +**Return** +`etl::chrono::day.` + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::day operator +(const etl::chrono::days& ms, + const etl::chrono::day& m) +ETL_NOEXCEPT +``` +**Description** +Add `etl::chrono::day` to `etl::chrono::days`. + +**Return** +`etl::chrono::day`. + +--- +```cpp +ETL_CONSTEXPR14 +etl::chrono::day operator -(const etl::chrono::day& m, + const etl::chrono::days& ms) +ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::days` from `etl::chrono::day`. + +**Return** +`etl::chrono::day`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::day operator -(const etl::chrono::days& ms, + const etl::chrono::day& m) +ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::day` from `etl::chrono::days`. + +**Return** +`etl::chrono::days`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::days operator -(const etl::chrono::day& m1, + const etl::chrono::day& m2) ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::day` from `etl::chrono::day`. + +**Return** +`etl::chrono::days`. + +## Non-member comparison operators +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::day& m1, + const etl::chrono::day& m2) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::day& m1, + const etl::chrono::day& m2) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::day& m1, + const etl::chrono::day& m2) +ETL_NOEXCEPT +``` +**Description** +Less-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::day& m1, + const etl::chrono::day& m2) +ETL_NOEXCEPT +``` +**Description** +Less-than-or-equal operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator >(const etl::chrono::day& m1, + const etl::chrono::day& m2) +ETL_NOEXCEPT +``` +**Description** +Greater-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator >=(const etl::chrono::day& m1, + const etl::chrono::day& m2) +ETL_NOEXCEPT +``` +**Description** +Greater-than-or-equal operator. + +--- + +```cpp +[[nodiscard]] inline constexpr +auto operator <=>(const etl::chrono::day& m1, + const etl::chrono::day& m2) +noexcept +``` +**Description** +Spaceship operator. +C++20 + +## Defined days + +```cpp +etl::chrono::January +etl::chrono::February +etl::chrono::March +etl::chrono::April +etl::chrono::May +etl::chrono::June +etl::chrono::July +etl::chrono::August +etl::chrono::September +etl::chrono::October +etl::chrono::November +etl::chrono::December +``` + +## Hash + +```cpp +template <> +struct hash +``` +**Description** +Hash function for `etl::chrono::day`. + diff --git a/docs/chrono/duration/_index.md b/docs/chrono/duration/_index.md new file mode 100644 index 00000000..f41bb632 --- /dev/null +++ b/docs/chrono/duration/_index.md @@ -0,0 +1,16 @@ +--- +title: "Durations" +weight: 100 +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono](https://en.cppreference.com/w/cpp/chrono.html) +{{< /callout >}} + +Classes that represent a duration. + +`etl::chrono::duration` +`etl::chrono::duration_cast` +`etl::chrono::duration_values` diff --git a/docs/chrono/duration/duration.md b/docs/chrono/duration/duration.md new file mode 100644 index 00000000..c75c6a7b --- /dev/null +++ b/docs/chrono/duration/duration.md @@ -0,0 +1,526 @@ +--- +title: "duration" +--- + +{{< callout type="info">}} + Header: `chrono.h` + Since: `TBC` + Similar to: [std::chrono::duration](https://en.cppreference.com/w/cpp/chrono/duration.html) + Similar to: [std::chrono::duration_values](https://en.cppreference.com/w/cpp/chrono/duration_values.html) +{{< /callout >}} + +Templates representing a time interval. + +## duration_values +```cpp +template +struct duration_values +``` +```cpp +ETL_NODISCARD static ETL_CONSTEXPR TRep zero() ETL_NOEXCEPT +``` +**Return** +`TRep(0)` + +--- + +```cpp +ETL_NODISCARD static ETL_CONSTEXPR14 TRep min() ETL_NOEXCEPT +``` +**Return** +`etl::numeric_limits::min()` + +--- + +```cpp +ETL_NODISCARD static ETL_CONSTEXPR14 TRep max() ETL_NOEXCEPT +``` +**Returns** +`etl::numeric_limits::max()` + +## duration +```cpp +template > +class duration +``` +```cpp +using rep = TRep +using period = typename TPeriod::type; +``` + +### Construction +```cpp +ETL_CONSTEXPR +duration() +ETL_NOEXCEPT +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +duration(const etl::chrono::duration& other) +ETL_NOEXCEPT +``` +--- + +```cpp +template +ETL_CONSTEXPR14 +explicit duration(const TRep2& value) +ETL_NOEXCEPT +``` + +--- + +```cpp +template +ETL_CONSTEXPR14 +duration(const etl::chrono::duration& other) +ETL_NOEXCEPT +``` +**Description** +Construct from another duration type. +Enabled if `etl::ratio_divide::den == 1` + +### Tests +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +int compare(const time_point& other) const +ETL_NOEXCEPT +``` +**Description** +Compare day with another. +if `time_point < other`, returns `-1` +else if `time_point > other`, returns `1` +else returns `0` + +### Assignment +```cpp +ETL_CONSTEXPR14 +etl::chrono::duration operator =(const etl::chrono::duration& other) ETL_NOEXCEPT +``` + +--- + +```cpp +template +ETL_CONSTEXPR14 +etl::chrono::duration operator =(const etl::chrono::duration& other) ETL_NOEXCEPT +``` + +### Convertion +```cpp +ETL_CONSTEXPR14 +TRep count() const +ETL_NOEXCEPT +``` +**Return** +The duration count as a numeric. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::common_type_t operator +() const +ETL_NOEXCEPT +``` +**Description** +Implements unary plus. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::common_type_t operator -() const +ETL_NOEXCEPT +``` +**Description** +Implements unary minus. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::duration absolute() const +ETL_NOEXCEPT +``` +**Return** +The absolute value of the duration. + +--- + +### Constants +```cpp +ETL_NODISCARD +static ETL_CONSTEXPR14 etl::chrono::duration zero() +ETL_NOEXCEPT +``` +**Return** +The duration zero value. + +--- + +```cpp +ETL_NODISCARD +static ETL_CONSTEXPR14 etl::chrono::duration min() +ETL_NOEXCEPT +``` +**Return** +The minimum duration value. + +--- + +```cpp +ETL_NODISCARD +static ETL_CONSTEXPR14 etl::chrono::duration max() +ETL_NOEXCEPT +--- +**Return** +The maximum duration value. + +## Increment/decrement +```cpp +ETL_CONSTEXPR14 +duration& operator ++() +ETL_NOEXCEPT +``` +**Description** +Pre-increments the duration count. + +--- + +```cpp +ETL_CONSTEXPR14 +duration operator ++(int) +ETL_NOEXCEPT +``` +**Description** +Post-increments the duration count. + +--- + +```cpp +ETL_CONSTEXPR14 +duration& operator --() +ETL_NOEXCEPT +``` +**Description** +Pre-decrements the duration count. + +--- +```cpp +ETL_CONSTEXPR14 +duration operator --(int) +ETL_NOEXCEPT +``` +**Description** +Post-decrements the duration count. + +### Mathematical operators +```cpp +ETL_CONSTEXPR14 +duration& operator +=(const duration& d) +ETL_NOEXCEPT +``` +**Description** +Adds duration `d` to this duration. + +--- + +```cpp +ETL_CONSTEXPR14 +duration& operator -=(const duration& d) +ETL_NOEXCEPT +``` +**Description** +Subtracts duration `d` to this duration. + +--- +```cpp +ETL_CONSTEXPR14 +duration& operator *=(const TRep& r) +ETL_NOEXCEPT +``` +**Description** +Multiplies this duration by `r`. + +--- + +```cpp +ETL_CONSTEXPR14 +duration& operator /=(const TRep& r) +ETL_NOEXCEPT +``` +**Description** +Divides this duration by `r`. + +--- + +```cpp +ETL_CONSTEXPR14 +duration& operator %=(const TRep& r) +ETL_NOEXCEPT +``` +**Description** +Sets this duration to the modulus of `r`. + +--- + +```cpp +ETL_CONSTEXPR14 +duration& operator %=(const duration& d) +ETL_NOEXCEPT +``` +**Description** +Sets this duration to the modulus of duration `d`. + +### Comparison +```cpp +template +ETL_CONSTEXPR14 +int compare(const duration& other) const +ETL_NOEXCEPT +``` +**Description** +Compare duration with another. +If `duration < other`, returns `-1` +else if `duration > other`, returns `1` +else returns `0` + +### Non-member mathematical operators +```cpp +template +ETL_CONSTEXPR14 +etl::common_type_t, + etl::chrono::duration> +operator +(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Operator `+` + +--- + +```cpp +template +ETL_CONSTEXPR14 +etl::common_type_t, + etl::chrono::duration >::type +operator -(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Operator `-` + +--- + +```cpp +template +ETL_CONSTEXPR14 +etl::chrono::duration, TPeriod1>> +operator *(const etl::chrono::duration& lhs, + const TRep2& rhs) +ETL_NOEXCEPT +``` +**Description** +Operator `*` +Enabled if `TRep2` is not a specialization of `etl::chrono::duration`. + +--- + +```cpp +template +ETL_CONSTEXPR14 +etl::chrono::duration, TPeriod2> +operator *(const TRep1& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Operator `*` + +--- + +```cpp +template +ETL_CONSTEXPR14 +etl::common_type_t, TPeriod1> +operator /(const etl::chrono::duration& lhs, + const TRep2& rhs) +ETL_NOEXCEPT +``` +**Description** +Operator `/` +Enabled if `TRep2` is not a specialization of `etl::chrono::duration`. + +--- + +```cpp +template +ETL_CONSTEXPR14 +etl::common_type_t +operator /(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Operator `/` + +--- + +```cpp +template +ETL_CONSTEXPR14 +etl::chrono::duration, TPeriod1> +operator %(const etl::chrono::duration& lhs, + const TRep2& rhs) +ETL_NOEXCEPT +``` +**Description** +Operator `%` + +``` + +```cpp +template +ETL_CONSTEXPR14 +etl::common_type_t, + etl::chrono::duration> +operator %(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Operator `%` + +### Non-member comparison operators +```cpp +template +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Checks for equality. + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Checks for inequality. + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Checks for less-than. + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Checks for less-than-or-equal. + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator >(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Checks for greater-than. + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator >=(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Checks for greater-than-or-equal. + +--- + +```cpp +template +[[nodiscard]] +constexpr +auto operator <=>(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) +noexcept +``` +**Description** +Spaceship operator. +C++20 + +## common_type + +```cpp +template +struct common_type, etl::chrono::duration> +``` +**Description** +`etl::common_type` specialisation for `etl::duration`. + +## Hash +```cpp +template +struct hash> +``` + +## Pre-defined duration types + +```cpp +etl::chrono::years +etl::chrono::months +etl::chrono::weeks +etl::chrono::days +etl::chrono::hours +etl::chrono::minutes +etl::chrono::seconds +etl::chrono::milliseconds +etl::chrono::microseconds +etl::chrono::nanoseconds +``` + +## duration_cast +```cpp +template +ETL_CONSTEXPR14 +TToDuration duration_cast(const etl::chrono::duration& d) +ETL_NOEXCEPT +``` +**Description** +Converts from one duration type to another. diff --git a/docs/chrono/duration/duration_cast.md b/docs/chrono/duration/duration_cast.md new file mode 100644 index 00000000..c75f1166 --- /dev/null +++ b/docs/chrono/duration/duration_cast.md @@ -0,0 +1,21 @@ +--- +title: "duration_cast" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::duration_cast](https://en.cppreference.com/w/cpp/chrono/duration/duration_cast.html) +{{< /callout >}} + +Templates representing a time interval. + +## duration_cast +```cpp +template +ETL_CONSTEXPR14 +TToDuration duration_cast(const etl::chrono::duration& d) +ETL_NOEXCEPT +``` +**Description** +Converts from one duration type to another. diff --git a/docs/chrono/duration/duration_values.md b/docs/chrono/duration/duration_values.md new file mode 100644 index 00000000..1373458e --- /dev/null +++ b/docs/chrono/duration/duration_values.md @@ -0,0 +1,38 @@ +--- +title: "duration_values" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::duration_values](https://en.cppreference.com/w/cpp/chrono/duration_values.html) +{{< /callout >}} + +Templates representing a time interval. + +## duration_values +```cpp +template +struct duration_values +``` +```cpp +ETL_NODISCARD static ETL_CONSTEXPR TRep zero() ETL_NOEXCEPT +``` +**Return** +`TRep(0)` + +--- + +```cpp +ETL_NODISCARD static ETL_CONSTEXPR14 TRep min() ETL_NOEXCEPT +``` +**Return** +`etl::numeric_limits::min()` + +--- + +```cpp +ETL_NODISCARD static ETL_CONSTEXPR14 TRep max() ETL_NOEXCEPT +``` +**Returns** +`etl::numeric_limits::max()` diff --git a/docs/chrono/hh_mm_ss.md b/docs/chrono/hh_mm_ss.md new file mode 100644 index 00000000..f7744ff1 --- /dev/null +++ b/docs/chrono/hh_mm_ss.md @@ -0,0 +1,138 @@ +--- +title: "hh_mm_ss" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::hh_mm_ss](https://en.cppreference.com/w/cpp/chrono/hh_mm_ss.html) +{{< /callout >}} + +A type to hold hours, minutes, and seconds. + +```cpp +template +class hh_mm_ss +``` +**Description** +Static asserts if `TDuration` is not a specialisation of `etl::chrono::duration`. + + +## Constants +```cpp +static constexpr int fractional_width; +``` +**Description** +The number of fractional digits. + +## Member types +```cpp +precision +``` +**Description** +The return type for `to_duration`. + +## Constructors +```cpp +ETL_CONSTEXPR +hh_mm_ss() +ETL_NOEXCEPT +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +explicit hh_mm_ss(TDuration d) +ETL_NOEXCEPT +``` +**Description** +Construct from `duration`. + +## Access +```pp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool is_negative() const +ETL_NOEXCEPT +``` +**Description** +Checks for negative duration. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::hours hours() const +ETL_NOEXCEPT +``` +**Return** +The hours. + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::minutes minutes() const +ETL_NOEXCEPT +``` +**Return** +The minutes. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::seconds seconds() const +ETL_NOEXCEPT +``` +**Return** +The seconds. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +precision subseconds() const +ETL_NOEXCEPT +``` +**Return** +The subseconds. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +explicit operator precision() const +ETL_NOEXCEPT +``` +**Return** +The duration. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +precision to_duration() const +ETL_NOEXCEPT +``` +**Return*** +The duration. + +## absolute +```cpp +template +ETL_NODISCARD +ETL_CONSTEXPR14 +TDuration absolute(TDuration dur) +ETL_NOEXCEPT +``` +A specialisation of absolute for `etl::chrono::duration`. +**Return** +The absolute duration value. \ No newline at end of file diff --git a/docs/chrono/last_spec.md b/docs/chrono/last_spec.md new file mode 100644 index 00000000..cc6d2a2b --- /dev/null +++ b/docs/chrono/last_spec.md @@ -0,0 +1,25 @@ +--- +title: "last_spec" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::last_spec](https://en.cppreference.com/w/cpp/chrono/last_spec.html) +{{< /callout >}} + +`last_spec` is a tag type that is used in conjunction with other calendar types to indicate the last thing in a sequence. + +```cpp +struct last_spec +{ + explicit last_spec() = default; +}; + +inline constexpr last_spec last{}; +``` + +**Example** + +`2025_y/March/last` for last day of March 2025 i.e. 2025-03-31 + diff --git a/docs/chrono/month/_index.md b/docs/chrono/month/_index.md new file mode 100644 index 00000000..d62bb8c3 --- /dev/null +++ b/docs/chrono/month/_index.md @@ -0,0 +1,18 @@ +--- +title: "Months" +weight: 100 +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono](https://en.cppreference.com/w/cpp/chrono.html) +{{< /callout >}} + +Classes that represent months. + +`etl::chrono::month` +`etl::chrono::month_day` +`etl::chrono::month_day_last` +`etl::chrono::month_weekday` +`etl::chrono::month_weekday_last` diff --git a/docs/chrono/month/month.md b/docs/chrono/month/month.md new file mode 100644 index 00000000..1099622b --- /dev/null +++ b/docs/chrono/month/month.md @@ -0,0 +1,337 @@ +--- +title: "month" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::month](https://en.cppreference.com/w/cpp/chrono/month.html) +{{< /callout >}} + +A class representing a month. + +```cpp +class month +``` +## Member types +`rep` The internal representation. + +## Construction +```cpp +ETL_CONSTEXPR +month() +ETL_NOEXCEPT +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR +explicit month(unsigned value) +ETL_NOEXCEPT +``` +**Description** +Construct from unsigned. + +--- + +```cpp +ETL_CONSTEXPR14 +month(const etl::chrono::month& other) +ETL_NOEXCEPT +``` +**Description** +Copy constructor. + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Description** +Returns true if the month is in range. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +int compare(const etl::chrono::month& other) const +ETL_NOEXCEPT +``` +**Description** +Compare month with another. +if month < other, returns -1 +else if month > other, returns 1 +else returns 0 + +## Assignment +```cpp +ETL_CONSTEXPR14 +etl::chrono::month& operator =(const etl::chrono::month& rhs) +ETL_NOEXCEPT +``` +**Description** +Assignment operator + +## Increment / decrement + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month& operator ++() +ETL_NOEXCEPT +``` +**Description** +Pre-increment operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month operator ++(int) +ETL_NOEXCEPT +``` +**Description** +Post-increment operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month& operator --() +ETL_NOEXCEPT +``` +**Description** +Pre-decrement operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month operator --(int) +ETL_NOEXCEPT +``` +**Description** +Post-decrement operator. + +## Mathematical operators + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month& operator +=(const etl::chrono::months& ms) +ETL_NOEXCEPT +``` +**Description** +Plus-equals operator adding `etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month& operator -=(const etl::chrono::months& ms) +ETL_NOEXCEPT +``` +**Description** +Minus-equals operator subtracting `etl::chrono::months`. + +## Constants + +```cpp +ETL_NODISCARD +static +ETL_CONSTEXPR14 +etl::chrono::month min() +ETL_NOEXCEPT +``` +**Description** +The minimum month value for which ok() will return true. + +--- + +```cpp +ETL_NODISCARD +static +ETL_CONSTEXPR14 +etl::chrono::month max() +ETL_NOEXCEPT +``` +**Description** +The maximum month value for which ok() will return true. + +## Conversion + +```cpp +ETL_CONSTEXPR14 +operator unsigned() const +ETL_NOEXCEPT +``` +**Description** +Conversion operator to `unsigned int`. + +## Non-member mathematical operators + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month operator +(const etl::chrono::month& m, + const etl::chrono::months& ms) +ETL_NOEXCEPT +``` +**Description** +Add `etl::chrono::months` to `etl::chrono::month`. +**Return** +`etl::chrono::month.` + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month operator +(const etl::chrono::months& ms, + const etl::chrono::month& m) +ETL_NOEXCEPT +``` +**Description** +Add `etl::chrono::month` to `etl::chrono::months`. +**Return** +`etl::chrono::month`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month operator -(const etl::chrono::month& m, + const etl::chrono::months& ms) +ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::months` from `etl::chrono::month`. +**Return** +`etl::chrono::month`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month operator -(const etl::chrono::months& ms, + const etl::chrono::month& m) +ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::month` from `etl::chrono::months`. +**Return** +`etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::months operator -(const etl::chrono::month& m1, + const etl::chrono::month& m2) ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::month` from `etl::chrono::month`. +**Return** +`etl::chrono::months`. + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::month& m1, + const etl::chrono::month& m2) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::month& m1, + const etl::chrono::month& m2) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::month& m1, + const etl::chrono::month& m2) +ETL_NOEXCEPT +``` +**Description** +Less-than operator. + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::month& m1, + const etl::chrono::month& m2) +ETL_NOEXCEPT +``` +**Description** +Less-than-or-equal operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator >(const etl::chrono::month& m1, + const etl::chrono::month& m2) +ETL_NOEXCEPT +``` +**Description** +Greater-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator >=(const etl::chrono::month& m1, + const etl::chrono::month& m2) +ETL_NOEXCEPT +``` +**Description** +Greater-than-or-equal operator. + +--- + +```cpp +[[nodiscard]] inline constexpr +auto operator <=>(const etl::chrono::month& m1, + const etl::chrono::month& m2) +noexcept +``` +**Description** +Spaceship operator. +C++20 + +## Defined months +```cpp +etl::chrono::January +etl::chrono::February +etl::chrono::March +etl::chrono::April +etl::chrono::May +etl::chrono::June +etl::chrono::July +etl::chrono::August +etl::chrono::September +etl::chrono::October +etl::chrono::November +etl::chrono::December +``` +## Hash +```cpp +template <> +struct hash +``` +Hash function for `etl::chrono::month`. + diff --git a/docs/chrono/month/month_day.md b/docs/chrono/month/month_day.md new file mode 100644 index 00000000..ccabdc33 --- /dev/null +++ b/docs/chrono/month/month_day.md @@ -0,0 +1,171 @@ +--- +title: "month_day" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::month_day](https://en.cppreference.com/w/cpp/chrono/month_day.html) +{{< /callout >}} + +A class representing a month and day. + +```cpp +class month_day +``` + +## Construction + +```cpp +ETL_CONSTEXPR +month_day() +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +month_day(const etl::chrono::month& m, + const etl::chrono::day& d) +ETL_NOEXCEPT +``` +**Description** +Construct from `month` and `day`. + +## Access + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::month month() const +ETL_NOEXCEPT +``` +**Return** +The month. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::day day() const +ETL_NOEXCEPT +``` +**Return** +The day. + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the month and day is within the valid limits. + +--- + +```cpp +ETL_CONSTEXPR14 +int compare(const month_day& other) const +ETL_NOEXCEPT +``` +**Description** +Compare `month_day` with another. +if `month < other.month`, returns `-1` +else if `month > other.month`, returns `1` +else if `day < other.day`, returns `-1` +else if `day > other.day`, returns `1` +else returns `0` + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Less-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Less-than-equal operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Greater-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Greater-than-equal operator. + +--- + +```cpp +[[nodiscard]] constexpr +auto operator <=>(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Spaceship operator. +C++20 + +## Hash + +```cpp +template +struct hash +``` +**Description** +Hash function for `etl::chrono::month_day`. + diff --git a/docs/chrono/month/month_day_last.md b/docs/chrono/month/month_day_last.md new file mode 100644 index 00000000..32733195 --- /dev/null +++ b/docs/chrono/month/month_day_last.md @@ -0,0 +1,147 @@ +--- +title: "month_day_last" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::month_day_last](https://en.cppreference.com/w/cpp/chrono/month_day_last.html) +{{< /callout >}} + +A class representing a month and last day. + +```cpp +class month_day_last +``` + +## Construction + +```cpp +ETL_CONSTEXPR14 +explicit month_day_last(const etl::chrono::month& m) +ETL_NOEXCEPT +``` +**Description** +Construct from month. + +## Access + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::month month() const +ETL_NOEXCEPT +``` +**Return** +The month. + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the month is within the valid limits. + +--- + +```cpp +ETL_CONSTEXPR14 +int compare(const month_day_last& other) const +ETL_NOEXCEPT +``` +**Description** +Compare `month_day_last` with another. +if `month < other.month`, returns `-1` +else if `month > other.month`, returns `1` +else returns `0` + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::month_day_last& lhs, + const etl::chrono::month_day_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::month_day_last& lhs, + const etl::chrono::month_day_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::month_day_last& lhs, + const etl::chrono::month_day_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Less-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::month_day_last& lhs, + const etl::chrono::month_day_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Less-than-equal operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::month_day_last& lhs, + const etl::chrono::month_day_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Greater-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::month_day_last& lhs, + const etl::chrono::month_day_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Greater-than-equal operator. + +--- + +```cpp +[[nodiscard]] constexpr +auto operator <=>(const etl::chrono::month_day_last& lhs, + const etl::chrono::month_day_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Spaceship operator. +C++20 + +## Hash + +```cpp +template +struct hash +``` +**Description** +Hash function for `etl::chrono::month_day_last`. diff --git a/docs/chrono/month/month_weekday.md b/docs/chrono/month/month_weekday.md new file mode 100644 index 00000000..ab73505e --- /dev/null +++ b/docs/chrono/month/month_weekday.md @@ -0,0 +1,156 @@ +--- +title: "month_weekday" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::month_weekday](https://en.cppreference.com/w/cpp/chrono/month_weekday.html) +{{< /callout >}} + +A class representing a month and weekday. + +```cpp +class month_weekday +``` + +## Construction + +```cpp +ETL_CONSTEXPR +month_weekday() +``` +**Decription** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +month_weekday(const etl::chrono::month& m, + const etl::chrono::weekday_indexed& wd) +ETL_NOEXCEPT +``` +**Decription** +Construct from month and weekday_indexed. + +## Access + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::month month() const +ETL_NOEXCEPT +``` +**Returns** +The month. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::weekday_indexed weekday_indexed() const +ETL_NOEXCEPT +``` +**Return** +The weekday. + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the month and day is within the valid limits. + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::month_weekday& lhs, + const etl::chrono::month_weekday& rhs) +ETL_NOEXCEPT +``` +**Decription** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::month_weekday& lhs, + const etl::chrono::month_weekday& rhs) +ETL_NOEXCEPT +``` +**Decription** +Inequality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::month_weekday& lhs, + const etl::chrono::month_weekday& rhs) +ETL_NOEXCEPT +``` +**Decription** +Less-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::month_weekday& lhs, + const etl::chrono::month_weekday& rhs) +ETL_NOEXCEPT +``` +**Decription** +Less-than-equal operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::month_weekday& lhs, + const etl::chrono::month_weekday& rhs) +ETL_NOEXCEPT +``` +**Decription** +Greater-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::month_weekday& lhs, + const etl::chrono::month_weekday& rhs) +ETL_NOEXCEPT +``` +**Decription** +Greater-than-equal operator. + +--- + +```cpp +[[nodiscard]] constexpr +auto operator <=>(const etl::chrono::month_weekday& lhs, + const etl::chrono::month_weekday& rhs) +ETL_NOEXCEPT +``` +**Decription** +Spaceship operator. +C++20 + +## Hash + +```cpp +template +struct hash +``` +**Decription** +Hash function for `etl::chrono::month_weekday`. + diff --git a/docs/chrono/month/month_weekday_last.md b/docs/chrono/month/month_weekday_last.md new file mode 100644 index 00000000..4af59d1d --- /dev/null +++ b/docs/chrono/month/month_weekday_last.md @@ -0,0 +1,143 @@ +--- +title: "month_weekday_last" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::month_weekday_last](https://en.cppreference.com/w/cpp/chrono/month_weekday_last.html) +{{< /callout >}} + +A class representing a month and weekday_last. + +```cpp +class month_weekday_last +``` + +## Construction + +```cpp +ETL_CONSTEXPR +month_weekday_last() +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +month_weekday_last(const etl::chrono::month& m, + const etl::chrono::weekday_last& wd) +ETL_NOEXCEPT +``` +**Description** +Construct from `month` and `weekday_last`. + +## Access + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::month month() const +ETL_NOEXCEPT +``` +**Return** +The month. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::weekday_last weekday_last() const +ETL_NOEXCEPT +``` +**Return** +The weekday. + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the month and day is within the valid limits. + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::month_weekday_last& lhs, + const etl::chrono::month_weekday_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::month_weekday_last& lhs, + const etl::chrono::month_weekday_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::month_weekday_last& lhs, + const etl::chrono::month_weekday_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Less-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::month_weekday_last& lhs, + const etl::chrono::month_weekday_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Less-than-equal operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::month_weekday_last& lhs, + const etl::chrono::month_weekday_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Greater-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::month_weekday_last& lhs, + const etl::chrono::month_weekday_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Greater-than-equal operator. + +## Hash + +```cpp +template +struct hash +``` +**Description** +Hash function for `etl::chrono::month_weekday_last`. diff --git a/docs/chrono/operators.md b/docs/chrono/operators.md new file mode 100644 index 00000000..719afea0 --- /dev/null +++ b/docs/chrono/operators.md @@ -0,0 +1,329 @@ +--- +title: "Operators" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::operator /](https://en.cppreference.com/w/cpp/chrono/operator_slash.html) +{{< /callout >}} + +Operators for building dates. + +## month_day + +Create from month and day. + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_day operator /(const etl::chrono::month& m, + const etl::chrono::day& d) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_day operator /(const etl::chrono::month& m, + int d) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_day operator /(int m, + const etl::chrono::day& d) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_day operator /(const etl::chrono::day& d, + const etl::chrono::month& m) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_day operator /(const etl::chrono::day& d, + int m) +ETL_NOEXCEPT +``` + +## month_day_last + +Create from month and last_spec. + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_day_last operator /(const etl::chrono::month& m, + etl::chrono::last_spec) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_day_last operator /(int m, + etl::chrono::last_spec) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_day_last operator /(etl::chrono::last_spec, + const etl::chrono::month& m) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_day_last operator /(etl::chrono::last_spec, + int m) +ETL_NOEXCEPT +``` + +## month_weekday + +Create from month and weekday. + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_weekday operator /(const etl::chrono::month& m, + const etl::chrono::weekday_indexed& wdi) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_weekday operator /(int m, + const etl::chrono::weekday_indexed& wdi) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_weekday operator /(const etl::chrono::weekday_indexed& wdi, + const etl::chrono::month& m) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_weekday operator /(const etl::chrono::weekday_indexed& wdi, + int m) +ETL_NOEXCEPT +``` + +## month_weekday_last + +Create from month and weekday_last. + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_weekday_last operator /(const etl::chrono::month& m, + const etl::chrono::weekday_last& wdl) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_weekday_last operator /(int m, + const etl::chrono::weekday_last& wdl) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_weekday_last operator /(const etl::chrono::weekday_last& wdl, + const etl::chrono::month& m) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::month_weekday_last operator /(const etl::chrono::weekday_last& wdl, + int m) +ETL_NOEXCEPT +``` + +## year_month + +Create from year and month. + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator /(const etl::chrono::year& y, + const etl::chrono::month& m) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator /(const etl::chrono::year& y, + int m) +ETL_NOEXCEPT +``` + +## year_month_day + +Create from year, month, and day. + +```cpp +ETL_CONSTEXPR14 etl::chrono::year_month_day operator /(const etl::chrono::year_month& ym, + const etl::chrono::day& d) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 etl::chrono::year_month_day operator /(const etl::chrono::year_month& ym, + int d ) +ETL_NOEXCEPT +``` + +## year_month_day + +Create from year and month_day. + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day operator /(const etl::chrono::year& y, + const etl::chrono::month_day& md) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day operator /(int y, + const etl::chrono::month_day& md) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day operator /(const etl::chrono::month_day& md, + const etl::chrono::year& y) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day operator /(const etl::chrono::month_day& md, + int y) +ETL_NOEXCEPT +``` + +## year_month_day_last + +Create from year_month and last_spec. + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator /(const etl::chrono::year_month& ym, + etl::chrono::last_spec) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator /(const etl::chrono::year& y, + const etl::chrono::month_day_last& mdl) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator /(int y, + const etl::chrono::month_day_last& mdl) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator /(const etl::chrono::month_day_last& mdl, + const etl::chrono::year& y) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator /(const etl::chrono::month_day_last& mdl, + int y) +ETL_NOEXCEPT +``` + +## year_month_weekday + +Create from year_month and weekday. + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday operator /(const etl::chrono::year_month& ym, + const etl::chrono::weekday_indexed& wdi) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday operator /(const etl::chrono::year& y, + const etl::chrono::month_weekday& mwd) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday operator /(int y, + const etl::chrono::month_weekday& mwd) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday operator /(const etl::chrono::month_weekday& mwd, + const etl::chrono::year& y) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday operator /(const etl::chrono::month_weekday& mwd, + int y) +ETL_NOEXCEPT +``` + +## year_month_weekday_last + +Create from year_month and weekday_last. + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday_last operator /(const etl::chrono::year_month& ym, + const etl::chrono::weekday_last& wdl) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday_last operator /(const etl::chrono::year& y, + const etl::chrono::month_weekday_last& mwdl) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday_last operator /(int y, + const etl::chrono::month_weekday_last& mwdl) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday_last operator /(const etl::chrono::month_weekday_last& mwdl, + const etl::chrono::year& y) +ETL_NOEXCEPT +``` + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_weekday_last operator /(const etl::chrono::month_weekday_last& mwdl, + int y) +ETL_NOEXCEPT +``` diff --git a/docs/chrono/time_point.md b/docs/chrono/time_point.md new file mode 100644 index 00000000..3a9ec057 --- /dev/null +++ b/docs/chrono/time_point.md @@ -0,0 +1,273 @@ +--- +title: "time_point" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::time_point](https://en.cppreference.com/w/cpp/chrono/time_point.html) +{{< /callout >}} + +```cpp +template +class time_point; +``` +Represents a point in time storing a `TDuration` indicating the time +interval from the start of the `TClock`'s epoch. + +## Member types + +```cpp +using clock = TClock +using duration = TDuration +using rep = typename TDuration::rep +using period = typename TDuration::period +``` + +## Constructors + +```cpp +ETL_CONSTEXPR +time_point() +ETL_NOEXCEPT +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +explicit time_point(const duration& dur_) +ETL_NOEXCEPT +``` +**Description** +Construct from a duration. + +--- + +```cpp +ETL_CONSTEXPR14 +time_point(const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Copy constructor. + +--- + +```cpp +template +ETL_CONSTEXPR14 +explicit time_point(const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Copy construct from another time_point with a different duration type. + +## Assignment +```cpp +ETL_CONSTEXPR14 +time_point& operator =(const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Assignment operator. + +## Access +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 duration time_since_epoch() const +ETL_NOEXCEPT +``` +**Return** +A duration representing the amount of time between this and the clock's epoch. + +## Member arithmetic operators +```cpp +ETL_CONSTEXPR14 time_point& operator +=(const duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Adds a duration. + +--- + +```cpp +ETL_CONSTEXPR14 time_point& operator -=(const duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Subtracts a duration. + +## Constants +```cpp +ETL_NODISCARD +static ETL_CONSTEXPR14 time_point min() +ETL_NOEXCEPT +``` +**Return** +A time_point with the smallest possible duration. + +--- + +```cpp +ETL_NODISCARD +static ETL_CONSTEXPR14 time_point max() +ETL_NOEXCEPT +``` +**Return** +A time_point with the largest possible duration. + +## Rounding +```cpp +template +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::time_point + floor(const etl::chrono::time_point& tp) +ETL_NOEXCEPT +``` +**Description** +Rounds down a duration to the nearest lower precision. + +--- + +```cpp +template +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::time_point + ceil(const etl::chrono::time_point& tp) +ETL_NOEXCEPT +``` +**Description** +Rounds up a duration to the nearest higher precision. + +--- + +```cp +template +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::time_point + round(const etl::chrono::time_point& tp) +ETL_NOEXCEPT +``` +**Description** +Rounds a duration to the nearest precision. +If the duration is exactly halfway, it rounds away from zero. + +## Casting +```cpp +template +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::time_point + time_point_cast(const etl::chrono::time_point& tp) +ETL_NOEXCEPT +``` + +## Comparison +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 int compare(const time_point& other) const +ETL_NOEXCEPT +``` +**Description** +Compare day with another. +If time_point < other, returns -1 +else if time_point > other, returns 1 +else returns 0 + +## Non-member comparison operators +```cpp +template +ETL_CONSTEXPR14 +bool operator ==(const time_point& lhs, + const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Equality operator + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator !=(const time_point& lhs, + const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Inequality operator + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator <(const time_point& lhs, + const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Less-than operator + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator <=(const time_point& lhs, + const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Less-than-equal operator + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator >(const time_point& lhs, + const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Greater-than operator + +--- + +```cpp +template +ETL_CONSTEXPR14 +bool operator >=(const time_point& lhs, + const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Greater-than-equal operator + +--- + +```cpp +template +[[nodiscard]] constexpr auto operator <=>(const etl::chrono::time_point& lhs, + const etl::chrono::time_point& rhs) +noexcept +``` +**Description** +Spaceship operator +C++20 + +## etl::common_type specialisation +```cpp +template +struct common_type, + etl::chrono::time_point> +``` +**Description** +Defines type, which is the common type of two `etl::chrono::time_point`. diff --git a/docs/chrono/weekday/_index.md b/docs/chrono/weekday/_index.md new file mode 100644 index 00000000..ef7a2c81 --- /dev/null +++ b/docs/chrono/weekday/_index.md @@ -0,0 +1,16 @@ +--- +title: "Weekdays" +weight: 100 +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono](https://en.cppreference.com/w/cpp/chrono.html) +{{< /callout >}} + +Classes that represent weekdays. + +`etl::chrono::weekday` +`etl::chrono::weekday_indexed` +`etl::chrono::weekday_last` diff --git a/docs/chrono/weekday/weekday.md b/docs/chrono/weekday/weekday.md new file mode 100644 index 00000000..70cf2e06 --- /dev/null +++ b/docs/chrono/weekday/weekday.md @@ -0,0 +1,386 @@ +--- +title: "weekday" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::weekday](https://en.cppreference.com/w/cpp/chrono/weekday.html) +{{< /callout >}} + +A class representing a weekday. + +```cpp +class weekday +``` + +## Construction + +```cpp +ETL_CONSTEXPR +weekday() +ETL_NOEXCEPT +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR +explicit weekday(unsigned value) +ETL_NOEXCEPT +``` +**Description** +Construct from `unsigned`. + +--- + +```cpp +ETL_CONSTEXPR14 +weekday(const etl::chrono::sys_days& sd) +ETL_NOEXCEPT +``` +**Description** +Construct from `sys_days`. + +--- + +```cpp +ETL_CONSTEXPR14 +weekday(const etl::chrono::local_days& sd) +ETL_NOEXCEPT +``` +**Description** +Construct from `local_days`. + +--- + +```cpp +ETL_CONSTEXPR14 +weekday(const etl::chrono::weekday& other) +ETL_NOEXCEPT +``` +**Description** +Copy constructor. + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the weekday is valid + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool is_weekend() const +ETL_NOEXCEPT +``` +**Return** +`true` if the weekday is a Saturday or Sunday. + +## Assignment + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday& operator =(const etl::chrono::weekday& rhs) +ETL_NOEXCEPT +``` +**Description** +Assignment operator + +## Access + +```cpp +ETL_CONSTEXPR14 +int c_encoding() const +ETL_NOEXCEPT +``` +**Description** +Gets the value of the weekday using C encoding. + +--- + +```cpp +ETL_CONSTEXPR14 +int iso_encoding() const +ETL_NOEXCEPT +``` +**Description** +Gets the value of the weekday using ISO encoding. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::weekday_indexed operator[](unsigned index) const +ETL_NOEXCEPT +``` +**Description** +Index operator, from index. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::weekday_last operator[](etl::chrono::last_spec last) const +ETL_NOEXCEPT +``` +**Description** +Index operator, from `etl::chrono::last_spec`. + +## Increment/decrement + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday& operator ++() +ETL_NOEXCEPT +``` +**Description** +Pre-increment operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday operator ++(int) +ETL_NOEXCEPT +``` +**Description** +Post-increment operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday& operator --() +ETL_NOEXCEPT +``` +**Description** +Pre-decrement operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday operator --(int) +ETL_NOEXCEPT +``` +**Description** +Post-decrement operator. + +## Mathematical operators + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday& operator +=(const etl::chrono::weekdays& ms) +ETL_NOEXCEPT +``` +**Description** +Plus-equals operator adding `etl::chrono::weekdays`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday& operator -=(const etl::chrono::weekdays& ms) +ETL_NOEXCEPT +``` +**Description** +Minus-equals operator subtracting `etl::chrono::weekdays`. + +## Constants + +```cpp +ETL_NODISCARD +static +ETL_CONSTEXPR14 +etl::chrono::weekday min() +ETL_NOEXCEPT +``` +**Description** +The minimum weekday value for which `ok()` will return true. + +--- + +```cpp +ETL_NODISCARD +static +ETL_CONSTEXPR14 +etl::chrono::weekday max() +ETL_NOEXCEPT +``` +**Description** +The maximum weekday value for which `ok()` will return true. + +## Non-member mathematical operators + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday operator +(const etl::chrono::weekday& m, + const etl::chrono::weekdays& ms) +ETL_NOEXCEPT +``` +**Description** +Add `etl::chrono::weekdays` to `etl::chrono::weekday`. +**Return** +`etl::chrono::weekday`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday operator +(const etl::chrono::weekdays& ms, + const etl::chrono::weekday& m) +ETL_NOEXCEPT +``` +**Description** +Add `etl::chrono::weekday` to `etl::chrono::weekdays`. +**Return** +`etl::chrono::weekday`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday operator -(const etl::chrono::weekday& m, + const etl::chrono::weekdays& ms) +ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::weekdays` from `etl::chrono::weekday`. +**Return** +`etl::chrono::weekday`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday operator -(const etl::chrono::weekdays& ms, + const etl::chrono::weekday& m) +ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::weekday` from `etl::chrono::weekdays`. +**Return** +`etl::chrono::weekdays`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekdays operator -(const etl::chrono::weekday& m1, + const etl::chrono::weekday& m2) ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::weekday` from `etl::chrono::weekday`. +**Return** +`etl::chrono::weekdays`. + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::weekday& m1, + const etl::chrono::weekday& m2) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::weekday& m1, + const etl::chrono::weekday& m2) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::weekday& m1, + const etl::chrono::weekday& m2) +ETL_NOEXCEPT +``` +**Description** +Less-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::weekday& m1, + const etl::chrono::weekday& m2) +ETL_NOEXCEPT +``` +**Description** +Less-than-or-equal operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator >(const etl::chrono::weekday& m1, + const etl::chrono::weekday& m2) +ETL_NOEXCEPT +``` +**Description** +Greater-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator >=(const etl::chrono::weekday& m1, + const etl::chrono::weekday& m2) +ETL_NOEXCEPT +``` +**Description** +Greater-than-or-equal operator. + +--- + +```cpp +[[nodiscard]] inline constexpr +auto operator <=>(const etl::chrono::weekday& m1, + const etl::chrono::weekday& m2) +noexcept +``` +**Description** +Spaceship operator. +C++20 + +## Defined weekdays + +```cpp +etl::chrono::Monday +etl::chrono::Tuesday +etl::chrono::Wednesday +etl::chrono::Thursday +etl::chrono::Friday +etl::chrono::Saturday +etl::chrono::Sunday +``` + +## Hash + +```cpp +template <> +struct hash +``` +**Description** +Hash function for `etl::chrono::weekday`. diff --git a/docs/chrono/weekday/weekday_indexed.md b/docs/chrono/weekday/weekday_indexed.md new file mode 100644 index 00000000..4062e3cc --- /dev/null +++ b/docs/chrono/weekday/weekday_indexed.md @@ -0,0 +1,127 @@ +--- +title: "weekday_indexed" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::weekday_indexed](https://en.cppreference.com/w/cpp/chrono/weekday_last.html) +{{< /callout >}} + +A class representing an indexed weekday. + +```cpp +class weekday_indexed +``` + +## Construction + +```cpp +ETL_CONSTEXPR +weekday_indexed() +ETL_NOEXCEPT +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +weekday_indexed(const etl::chrono::weekday& wd, unsigned index) +ETL_NOEXCEPT +``` +**Description** +Construct from `weekday` and `index`. + +--- + +```cpp +ETL_CONSTEXPR14 +weekday_indexed(const etl::chrono::weekday_indexed& other) +ETL_NOEXCEPT +``` +**Description** +Copy constructor. + +## Tests + +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +**Return** +`true` if the weekday_indexed is valid + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool is_weekend() const +ETL_NOEXCEPT +``` +**Return** +`true` if the `weekday_indexed` is a `Saturday` or `Sunday`. + +## Assignment + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday_indexed& operator =(const etl::chrono::weekday_indexed& rhs) +ETL_NOEXCEPT +``` +**Description** +Assignment operator + +## Access + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday weekday() const +ETL_NOEXCEPT +``` +**Description** +Gets the weekday. + +--- + +```cpp +ETL_CONSTEXPR14 +unsigned index() const +ETL_NOEXCEPT +``` +**Description** +Gets the index. + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::weekday_indexed& m1, + const etl::chrono::weekday_indexed& m2) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::weekday_indexed& m1, + const etl::chrono::weekday_indexed& m2) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +## Hash + +```cpp +template <> +struct hash +``` +**Description** +Hash function for `etl::chrono::weekday_indexed`. + \ No newline at end of file diff --git a/docs/chrono/weekday/weekday_last.md b/docs/chrono/weekday/weekday_last.md new file mode 100644 index 00000000..d1219e57 --- /dev/null +++ b/docs/chrono/weekday/weekday_last.md @@ -0,0 +1,107 @@ +--- +title: "weekday_last" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::weekday_last](https://en.cppreference.com/w/cpp/chrono/weekday_last.html) +{{< /callout >}} + +A class representing the last day of a weekday. + +```cpp +class weekday_last +``` + +## Construction + +```cpp +ETL_CONSTEXPR +weekday_last() +ETL_NOEXCEPT +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +weekday_last(const etl::chrono::weekday& wd) +ETL_NOEXCEPT +``` +**Description** +Construct from weekday and index. + +--- + +```cpp +ETL_CONSTEXPR14 +weekday_last(const etl::chrono::weekday_last& other) +ETL_NOEXCEPT +``` +**Description** +Copy constructor. + +--- + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the weekday_last valid. + +## Assignment + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday_last& operator =(const etl::chrono::weekday_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Assignment operator + +## Access + +```cpp +ETL_CONSTEXPR14 +etl::chrono::weekday weekday() const +ETL_NOEXCEPT +``` +**Description** +Gets the weekday. + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::weekday_last& m1, + const etl::chrono::weekday_last& m2) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::weekday_last& m1, + const etl::chrono::weekday_last& m2) +ETL_NOEXCEPT +**Description** +Inequality operator. + +## Hash + +```cpp +template <> +struct hash +``` +**Description** +Hash function for `etl::chrono::weekday_last`. diff --git a/docs/chrono/year/_index.md b/docs/chrono/year/_index.md new file mode 100644 index 00000000..bc9b9e27 --- /dev/null +++ b/docs/chrono/year/_index.md @@ -0,0 +1,17 @@ +--- +title: "Years" +weight: 100 +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono](https://en.cppreference.com/w/cpp/chrono.html) +{{< /callout >}} + +Classes that represent years. + +`etl::chrono::year` +`etl::chrono::year_month` +`etl::chrono::year_month_day` +`etl::chrono::year_month_day_last` diff --git a/docs/chrono/year/year.md b/docs/chrono/year/year.md new file mode 100644 index 00000000..9d409d4a --- /dev/null +++ b/docs/chrono/year/year.md @@ -0,0 +1,328 @@ +--- +title: "year" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::year](https://en.cppreference.com/w/cpp/chrono/year.html) +{{< /callout >}} + +A class representing a year. + +```cpp +class year +``` + +## Member types + +`rep` The internal representation. + +## Construction +```cpp +ETL_CONSTEXPR +year() +ETL_NOEXCEPT +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR +explicit year(unsigned value) +ETL_NOEXCEPT +``` +**Description** +Construct from unsigned. + +--- + +```cpp +ETL_CONSTEXPR14 +year(const etl::chrono::year& other) +ETL_NOEXCEPT +``` +**Description** +Copy constructor. + +## Tests +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +int compare(const etl::chrono::year& other) const +ETL_NOEXCEPT +``` +**Description** +Compare day with another. +if `year < other`, returns `-1` +else if `year > other`, returns `1` +else returns `0` + +## Assignment +```cpp +ETL_CONSTEXPR14 +etl::chrono::year& operator =(const etl::chrono::year& rhs) +ETL_NOEXCEPT +``` +**Description** +Assignment operator + +## Increment / decrement +```cpp +ETL_CONSTEXPR14 +etl::chrono::year& operator ++() +ETL_NOEXCEPT +``` +**Description** +Pre-increment operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year operator ++(int) +ETL_NOEXCEPT +``` +**Description** +Post-increment operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year& operator --() +ETL_NOEXCEPT +``` +**Description** +Pre-decrement operator. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year operator --(int) +ETL_NOEXCEPT +``` +**Description** +Post-decrement operator. + +## Mathematical operators +```cpp +ETL_CONSTEXPR14 +etl::chrono::year& operator +=(const etl::chrono::years& ys) +ETL_NOEXCEPT +``` +**Description** +Plus-equals operator adding etl::chrono::years. + +--- +```cpp +ETL_CONSTEXPR14 +etl::chrono::year& operator -=(const etl::chrono::years& ys) +ETL_NOEXCEPT +``` +**Description** +Minus-equals operator subtracting etl::chrono::years. + +## Tests +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Description** +Returns true if the year is within the valid -32767 to 32767 range. + +--- +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool is_leap() const +ETL_NOEXCEPT +``` +**Description** +Returns true if the year is a leap year. + +## Constants +```cpp +ETL_NODISCARD +static +ETL_CONSTEXPR14 +etl::chrono::year min() +ETL_NOEXCEPT +``` +**Description** +The minimum year value for which ok() will return true. + +--- + +```cpp +ETL_NODISCARD +static +ETL_CONSTEXPR14 +etl::chrono::year max() +ETL_NOEXCEPT +``` +**Description** +The maximum year value for which ok() will return true. + +## Conversion +```cpp +ETL_CONSTEXPR14 +operator int() const +ETL_NOEXCEPT +``` +**Description** +Conversion operator to `unsigned int`. + +## Non-member mathematical operators +```cpp +ETL_CONSTEXPR14 +etl::chrono::year operator +(const etl::chrono::year& y, + const etl::chrono::years& ys) +ETL_NOEXCEPT +``` +**Description** +Add `etl::chrono::years` to `etl::chrono::year`. +**Return** +`etl::chrono::year`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year operator +(const etl::chrono::years& ys, + const etl::chrono::year& y) +ETL_NOEXCEPT +``` +**Description** +Add `etl::chrono::year` to `etl::chrono::years`. +**Return** +`etl::chrono::year`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year operator -(const etl::chrono::year& y, + const etl::chrono::years& ys) +ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::years` from `etl::chrono::year`. +**Return** +`etl::chrono::year`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year operator -(const etl::chrono::years& ys, + const etl::chrono::year& y) +ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::year` from `etl::chrono::years`. +**Return** +`etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::years operator -(const etl::chrono::year& y1, + const etl::chrono::year& y2) ETL_NOEXCEPT +``` +**Description** +Subtract `etl::chrono::year` from `etl::chrono::year`. +**Return** +`etl::chrono::years`. + +## Non-member comparison operators +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::year& y1, + const etl::chrono::year& y2) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::year& y1, + const etl::chrono::year& y2) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <(const etl::chrono::year& y1, + const etl::chrono::year& y2) +ETL_NOEXCEPT +``` +**Description** +Less-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator <=(const etl::chrono::year& y1, + const etl::chrono::year& y2) +ETL_NOEXCEPT +``` +**Description** +Less-than-or-equal operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator >(const etl::chrono::year& y1, + const etl::chrono::year& y2) +ETL_NOEXCEPT +``` +**Description** +Greater-than operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator >=(const etl::chrono::year& y1, + const etl::chrono::year& y2) +ETL_NOEXCEPT +``` +**Description** +Greater-than-or-equal operator. + +--- + +```cpp +[[nodiscard]] inline constexpr +auto operator <=>(const etl::chrono::year& y1, + const etl::chrono::year& y2) +noexcept +``` +**Description** +Spaceship operator. +C++20 + +## Hash +```cpp +template +struct hash +``` +**Description** +Hash function for `etl::chrono::year`. + diff --git a/docs/chrono/year/year_month.md b/docs/chrono/year/year_month.md new file mode 100644 index 00000000..9c271073 --- /dev/null +++ b/docs/chrono/year/year_month.md @@ -0,0 +1,214 @@ +--- +title: "year_month" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::year_month](https://en.cppreference.com/w/cpp/chrono/year_month.html) +{{< /callout >}} + +A class representing a year and month. + +```cpp +class year_month +``` + +## Construction +```cpp +ETL_CONSTEXPR +year_month() +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +year_month(const etl::chrono::year& y, + const etl::chrono::month& m) +ETL_NOEXCEPT +``` +**Description** +Construct from month and day. + +## Access + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::year year() const +ETL_NOEXCEPT +``` +**Return** +The year. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::month month() const +ETL_NOEXCEPT +``` +**Return** +The month. + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the year and month is within the valid limits. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +int compare(const etl::chrono::year_month& other) const +ETL_NOEXCEPT +``` +**Description** +If `y < other.y` return `-1` +If `y > other.y` return `1` +If `m < other.m` return `-1` +If `m > other.m` return `1` +Else return `0` + +## Non-member mathematical operators + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator +(const etl::chrono::year_month& ym, + const etl::chrono::years& dy) +``` +**Description** +Adds `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator +(const etl::chrono::years& dy, + const etl::chrono::year_month& ym) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator +(const etl::chrono::year_month& ym, + const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator +(const etl::chrono::months& dm, + const etl::chrono::year_month& ym) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator -(const etl::chrono::year_month& ym, + const etl::chrono::years& dy) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator -(const etl::chrono::year_month& ym, + const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::months operator -(const etl::chrono::year_month& ym1, + const etl::chrono::year_month& ym2) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::year_month`. + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::year_month& lhs, + const etl::chrono::year_month& rhs) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::year_month& lhs, + const etl::chrono::year_month& rhs) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +[[nodiscard]] friend constexpr +auto operator <=>(const etl::chrono::year_month& lhs, + const etl::chrono::year_month& rhs) +ETL_NOEXCEPT +``` +**Description** +Spaceship operator +C++20 + +--- + +``` +ETL_CONSTEXPR14 +int compare(const year_month& other) const +ETL_NOEXCEPT +``` +**Description** +Compare year_month with another. +if `month < other.month`, returns `-1` +else if `month > other.month`, returns `1` +else if `day < other.day`, returns `-1` +else if `day > other.day`, returns `1` +else returns `0`; + +## Hash + +template +struct hash +**Description** +Hash function for `etl::chrono::year_month`. diff --git a/docs/chrono/year/year_month_day.md b/docs/chrono/year/year_month_day.md new file mode 100644 index 00000000..728971de --- /dev/null +++ b/docs/chrono/year/year_month_day.md @@ -0,0 +1,277 @@ +--- +title: "year_month_day" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::year_month_day](https://en.cppreference.com/w/cpp/chrono/year_month_day.html) +{{< /callout >}} + +A class representing a year, month, and day. + +```cpp +class year_month_day +``` + +## Construction + +```cpp +ETL_CONSTEXPR year_month_day() +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +year_month_day(const etl::chrono::year& y, + const etl::chrono::month& m, + const etl::chrono::day& d) +ETL_NOEXCEPT +``` +**Description** +Construct from `month` and `day`. + +--- + +```cpp +ETL_CONSTEXPR14 +year_month_day(const etl::chrono::year_month_day_last& ymdl) +ETL_NOEXCEPT +``` +**Description** +Construct from `year_month_day_last`. + +--- + +```cpp +ETL_CONSTEXPR14 +year_month_day(const etl::chrono::sys_days& sd) +ETL_NOEXCEPT +``` +**Description** +Construct from `sys_days`. + +--- + +```cpp +ETL_CONSTEXPR14 +year_month_day(const etl::chrono::local_days& ld) +ETL_NOEXCEPT +``` +**Description** +Construct from `local_days`. + +## Access + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::year year() const +ETL_NOEXCEPT +``` +**Return** +The year. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::month month() const +ETL_NOEXCEPT +``` +**Return** +The month. + +--- + +``` +ETL_NODISCARD +ETL_CONSTEXPR14 etl::chrono::day day() const +ETL_NOEXCEPT +``` +**Return** +The day. + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the year and month is within the valid limits. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +int compare(const etl::chrono::year_month_day& other) const +ETL_NOEXCEPT +``` +**Description** +Compare `year_month_day` with another. +if `year < other.year`, returns `-1` +else if `year > other.year`, returns `1` +if `month < other.month`, returns `-1` +else if `month > other.month`, returns `1` +else if `day < other.day`, returns `-1` +else if `day > other.day`, returns `1` +else returns `0` + +## operators + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day& operator +=(const etl::chrono::years& dy) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day& operator +=(const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day& operator -=(const etl::chrono::years& dy) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::years`. + +--- + +``` +ETL_CONSTEXPR14 +etl::chrono::year_month_day& operator -=(const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::months`. + +## Non-member operators + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day operator +(const etl::chrono::year_month_day& ym, + const etl::chrono::years& dy) +``` +**Description** +Adds `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day operator +(const etl::chrono::years& dy, + const etl::chrono::year_month_day& ym) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day operator +(const etl::chrono::year_month_day& ym, + const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::months`. + +--- + +``` +ETL_CONSTEXPR14 +etl::chrono::year_month operator +(const etl::chrono::months& dm, + const etl::chrono::year_month_day& ym) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator -(const etl::chrono::year_month_day& ym, + const etl::chrono::years& dy) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month operator -(const etl::chrono::year_month_day& ym, + const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::months`. + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::year_month_day& lhs, + const etl::chrono::year_month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::year_month_day& lhs, + const etl::chrono::year_month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +[[nodiscard]] friend constexpr +auto operator <=>(const etl::chrono::year_month_day& lhs, + const etl::chrono::year_month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Spaceship operator +C++20 + +## Hash + +```cpp +template <> +struct hash +``` +**Description** +Hash function for `etl::chrono::year_month_day`. + + + diff --git a/docs/chrono/year/year_month_day_last.md b/docs/chrono/year/year_month_day_last.md new file mode 100644 index 00000000..426a51ab --- /dev/null +++ b/docs/chrono/year/year_month_day_last.md @@ -0,0 +1,251 @@ +--- +title: "year_month_day_last" +--- + +{{< callout type="info">}} + Header: `chrono.h` + From: `20.41.0` + Similar to: [std::chrono::year_month_day_last](https://en.cppreference.com/w/cpp/chrono/year_month_day_last.html) +{{< /callout >}} + +A class representing a year, month and last day. + +```cpp +class year_month_day_last +``` + +## Construction + +```cpp +ETL_CONSTEXPR year_month_day_last() +``` +**Description** +Default constructor. + +--- + +```cpp +ETL_CONSTEXPR14 +year_month_day(const etl::chrono::year& y, + const etl::chrono::month_day_last& mdl) +ETL_NOEXCEPT +``` +**Description** +Construct from month and day. + +--- + +```cpp +ETL_CONSTEXPR14 +year_month_day(const etl::chrono::year_month_day_last& ymdl) +ETL_NOEXCEPT +``` +**Description** +Construct from `year_month_day_last`. + +## Access + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::year year() const +ETL_NOEXCEPT +``` +**Return** +The year. + +--- + +```coo +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::month month() const +ETL_NOEXCEPT +``` +**Return** +The month. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +etl::chrono::month_day_last month_day_last() const +ETL_NOEXCEPT +``` +**Returns** +The month. + +## Tests + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +bool ok() const +ETL_NOEXCEPT +``` +**Return** +`true` if the year and month is within the valid limits. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +int compare(const etl::chrono::year_month_day_last& other) const +ETL_NOEXCEPT +``` +**Description** +Compare `year_month_day` with another. +if `year < other.year`, returns `-1` +else if `year > other.year`, returns `1` +if `month < other.month`, returns `-1` +else if `month > other.month`, returns `1` +else returns `0` + +## operators + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last& operator +=(const etl::chrono::years& dy) +ETL_NOEXCEPT +``` +Adds `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last& operator +=(const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last& operator -=(const etl::chrono::years& dy) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last& operator -=(const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::months`. + +## Non-member operators + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator +(const etl::chrono::year_month_day_last& ym, + const etl::chrono::years& dy) +``` +**Description** +Adds `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator +(const etl::chrono::years& dy, + const etl::chrono::year_month_day_last& ym) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator +(const etl::chrono::year_month_day_last& ym, + const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator +(const etl::chrono::months& dm, + const etl::chrono::year_month_day_last& ym) +ETL_NOEXCEPT +``` +**Description** +Adds `etl::chrono::months`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_last operator -(const etl::chrono::year_month_day_last& ym, + const etl::chrono::years& dy) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::years`. + +--- + +```cpp +ETL_CONSTEXPR14 +etl::chrono::year_month_day_last operator -(const etl::chrono::year_month_day& ym, + const etl::chrono::months& dm) +ETL_NOEXCEPT +``` +**Description** +Subtracts `etl::chrono::months`. + +## Non-member comparison operators + +```cpp +ETL_CONSTEXPR14 +bool operator ==(const etl::chrono::year_month_day_last& lhs, + const etl::chrono::year_month_day_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Equality operator. + +--- + +```cpp +ETL_CONSTEXPR14 +bool operator !=(const etl::chrono::year_month_day_last& lhs, + const etl::chrono::year_month_day_last& rhs) +ETL_NOEXCEPT +``` +**Description** +Inequality operator. + +--- + +```cpp +[[nodiscard]] friend constexpr +auto operator <=>(const etl::chrono::year_month_day& lhs, + const etl::chrono::year_month_day& rhs) +ETL_NOEXCEPT +``` +**Description** +Spaceship operator. +C++20 + +## Hash + +```cpp +template <> +struct hash +``` +**Description** +Hash function for `etl::chrono::year_month_day_last`. diff --git a/docs/codecs/_index.md b/docs/codecs/_index.md new file mode 100644 index 00000000..f4ac827a --- /dev/null +++ b/docs/codecs/_index.md @@ -0,0 +1,6 @@ +--- +title: "Codecs" +weight: 100 +--- + +Encoder and decoder algorithms. diff --git a/docs/codecs/base64.md b/docs/codecs/base64.md new file mode 100644 index 00000000..e76f0040 --- /dev/null +++ b/docs/codecs/base64.md @@ -0,0 +1,313 @@ +--- +title: "Base64" +--- + +{{< callout type="info">}} + Headers: + `base64.h` Common definitions + `base64_encoder.h` Encoder class + `base64_decoder.h` Decoder class + From: `20.38.4` +{{< /callout >}} + +Encodes and decodes data to and from Base64 format. + +## Encode + +**Input -> pointer/length : Output -> pointer/length** +```cpp +template +ETL_CONSTEXPR14 +static +size_t encode(const T* input, size_t input_length, + char* output, size_t output_length) +``` +**Description** +Transforms the input data described by input and input_length to Base64 format to be stored in output output_length. +Enabled if `etl::is_integral` is `true` and `etl::integral_limits::bits == 8`. + +**Return** +The length of the encoded data. + +**Error** +If output_length is not large enough to hold the encoded data then an `etl::base64_overflow` is raised. + +--- + +**Input -> pointer/length : Output -> string** +```cpp +template +ETL_CONSTEXPR14 +static +size_t encode(const T* input, size_t input_length, + etl::istring& output) +``` +**Description** +Transforms the input data described by input and input_length to Base64 format to be stored in output. +Enabled if `etl::is_integral` is `true` and `etl::integral_limits::bits == 8`. +The output string must have capacity of at least `etl::base64::encode_size(input)`. + +**Return** +The length of the encoded data. + +**Error** +If output_length is not large enough to hold the encoded data then an `etl::base64_overflow` is raised. + +--- + +**Input -> pointer/pointer : Output -> pointer/pointer** +```cpp +template +ETL_CONSTEXPR14 +static +size_t encode(const T* input_begin, const T* input_end, + char* output_begin, char* output_end) +``` +**Description** +Transforms the input data described by input_begin and input_end to Base64 format to be stored in output_begin to output_end. +Enabled if `etl::is_integral` is `true` and `etl::integral_limits::bits == 8`. + +**Return** +The length of the encoded data. + +**Error** +If the output buffer is not large enough to hold the encoded data then an `etl::base64_overflow` is raised. + +--- + +**Input -> pointer/pointer : Output -> string** +```cpp +template +ETL_CONSTEXPR14 +static +size_t encode(const T* input_begin, const T* input_end, + etl::istring& output) +``` +**Description** +Transforms the input data described by input_begin and input_end to Base64 format to be stored in output. +Enabled if `etl::is_integral` is `true` and `etl::integral_limits::bits == 8`. +The output string must have capacity of at least `etl::base64::encode_size(input)`. + +**Return** +The length of the encoded data. + +**Error** +If the output buffer is not large enough to hold the encoded data then an `etl::base64_overflow` is raised. + +--- + +**Input -> span : Output -> span** +```cpp +template +ETL_CONSTEXPR14 +static +size_t encode(const etl::span& input_span, + const etl::span& output_span) +``` +**Description** +Transforms the input data described by input_span to Base64 format to be stored in output_span. +Enabled if etl::is_integral is true and etl::integral_limits::bits == 8. + +**Return** +The length of the encoded data. + +**Error** +If the output span is not large enough to hold the encoded data then an etl::base64_overflow is raised. + +--- + +**Input -> span : Output -> string** +```cpp +template +ETL_CONSTEXPR14 +static +size_t encode(const etl::span& input_span, + etl::istring& output) +``` +**Description** +Transforms the input data described by input_span to Base64 format to be stored in output. +Enabled if etl::is_integral is true and etl::integral_limits::bits == 8 +The output string must have capacity of at least etl::base64::encode_size(input). + +**Return** +The length of the encoded data. + +**Error** +If the output span is not large enough to hold the encoded data then an etl::base64_overflow is raised. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +static +size_t encode_size(size_t input_length) +``` +**Return** +Returns the size of the output buffer required to encode the specified input data length. + +## Decode + +**Input -> pointer/length : Output -> pointer/length** +```cpp +template +ETL_CONSTEXPR14 +static +size_t decode(const char* input, size_t input_length, + T* output, size_t output_length) +``` +**Description** +Transforms the Base64 format input data described by input and input_length to by output and output_length. +Enabled if `etl::is_integral` is `true` and `etl::integral_limits::bits == 8`. + +**Return** +The length of the decoded data. + +**Error** +If `output_length` is not large enough to hold the decoded data then an `etl::base64_overflow` is raised. + +--- + +**Input -> pointer/pointer: Output -> pointer/pointer** +```cpp +template +ETL_CONSTEXPR14 +static +size_t decode(const char* input_begin, const char* input_end, + T* output_begin, T* output_end) +``` +**Description*** +Transforms the Base64 format input data described by `input_begin` and `input_end` to `output_begin` and `output_end`. +Enabled if `etl::is_integral` is `true` and `etl::integral_limits::bits == 8`. + +**Return** +The length of the decoded data. + +**Error** +If the output buffer is not large enough to hold the decoded data then an `etl::base64_overflow` is raised. + +--- + +**Input -> span: Output -> span** +```cpp +template +ETL_CONSTEXPR14 +static +size_t decode(const etl::span& input_span, + const etl::span& output_span) +``` +**Description** +Transforms the Base64 format input data described by input_span to output_span. +Enabled if `etl::is_integral` is `true` and `etl::integral_limits::bits == 8`. + +**Return** +The length of the decoded data. + +**Error** +If the output span is not large enough to hold the decoded data then an `etl::base64_overflow` is raised. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +static +size_t decode_size(const char* input, size_t input_length) +``` +**Return** +The size of the output buffer required to decode the specified input Base64 data length. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +static +size_t decode_size(const char* input_begin, const char* input_end) +``` +**Return** +The size of the output buffer required to decode the specified input Base64 data length. + +--- + +```cpp +ETL_NODISCARD +ETL_CONSTEXPR14 +static +size_t decode_size(etl::span input) +``` +**Return** +The size of the output buffer required to decode the specified input Base64 data length. + +## Examples + +### Encode +```cpp +const etl::array input = +{ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, + 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21 // "Hello World!" +}; + +etl::string<20> encoded; + +size_t encoded_size = etl::base64::encode(input.data(), input.size(), + encoded.data(), encoded.size()); + +encoded.resize(encoded_size); +// encoded == "OycDQy37KCphrg==" +``` + +--- + +*For C++14 or above* +```cpp +const etl::array input = +{ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, + 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21 // "Hello World!" +}; + +constexpr size_t length = etl::base64::encode_size(input.size()); +etl::string output; +output.uninitialized_resize(output.capacity()); + +etl::base64::encode(input.data(), input.size(), output.data(), output.size()); +// output == "OycDQy37KCphrg==" +``` + +--- + +### Decode +```cpp +const etl::string<16> encoded = "OycDQy37KCphrg=="; + +etl::vector output; + +size_t decoded_size = etl::base64::decode(encoded.data(), encoded.size(), + output.data(), output.size()); + +output.resize(decoded_size); +// output == { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, +// 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21 }; +``` + +--- + +*For C++14 or above* +```cpp +// "OycDQy37KCphrg==" +constexpr const etl::array input = +{ + 0x4F, 0x79, 0x63, 0x44, 0x51, 0x79, 0x33, 0x37, + 0x4B, 0x43, 0x70, 0x68, 0x72, 0x67, 0x3D, 0x3D +}; + +constexpr size_t length = etl::base64::decode_size(input.data(), input.size()); +etl::vector output; + +etl::base64::decode(input.data(), input.size(), output.data(), output.size()); +// output == { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, +// 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21 }; +``` + diff --git a/docs/manchester.md b/docs/codecs/manchester.md similarity index 73% rename from docs/manchester.md rename to docs/codecs/manchester.md index d73cb958..945964c0 100644 --- a/docs/manchester.md +++ b/docs/codecs/manchester.md @@ -1,8 +1,14 @@ --- title: Manchester encoding and decoding +weight: 1 --- -Efficient Manchester encoding and decoding of data. The Manchester code represents a data bit as a sequence of a 'high' and a 'low' value. In software this translates to a conversion from one to two bits, or in a practical situation, from `n` bytes to `n*2` bytes. +{{< callout type="info">}} + Header: `manchester.h` + Support: `20.45.0` +{{< /callout >}} + +Efficient Manchester encoding and decoding of data. The Manchester code represents a data bit as a sequence of a 'high' and a 'low' values. In software this translates to a conversion from one to two bits, or in a practical situation, from `n` bytes to `n*2` bytes. ## See also @@ -58,13 +64,11 @@ Comparing all 8 bit pairs in a 16-bit word is done as follows. Most traditional ways to Manchester encode data consist of a loop over all bits and a nested if-statement to check the value of the current bit. This approach does not scale well to increasing number of bits. The algorithm implemented here contains no conditional code and scales well. Doubling the number of processed bits per step (the chunk size) adds a single row to the bit duplication table. Because of the lack of loops and conditional code, this algorithm is likely to perform better than traditional ones on simple processors or when compiler optimization is disabled. On modern, powerful processors with caches and advanced optimization possibilities this algorithm may not show much benefit. In any case, the performance of the algorithm depends heavily on the processor type, compiler and compiler (optimization) settings. -## API Reference - -### Classes +## Classes Classes `etl::manchester` and `etl::manchester_inverted` contain static functions for encoding, decoding and validity checking. It is not necessary to instantiate objects of these classes. -#### etl::manchester +### etl::manchester ```cpp typedef manchester_base manchester; @@ -72,7 +76,7 @@ typedef manchester_base manchester; Manchester encoder using normal encoding (no inversion). -#### etl::manchester_inverted +### etl::manchester_inverted ```cpp typedef manchester_base manchester_inverted; @@ -80,9 +84,9 @@ typedef manchester_base manchester Manchester encoder using inverted encoding. -### Encoding Functions +## Encoding Functions -#### Encode single value +### Encode single value ```cpp template @@ -91,21 +95,21 @@ static ETL_CONSTEXPR14 typename encoded::type encode(TDecoded decoded) Encodes a single value using Manchester encoding. -**Parameters:** +**Parameters** -- `decoded`: The value to encode (`uint8_t`, `uint16_t`, or `uint32_t`) +`decoded`: The value to encode (`uint8_t`, `uint16_t`, or `uint32_t`) -**Returns:** +**Returns** -- The Manchester encoded value (twice the bit width of input) +The Manchester encoded value (twice the bit width of input) -**Example:** +**Example** ```cpp uint16_t encoded = etl::manchester::encode(0x55); ``` -#### Encode range +### Encode range ```cpp template @@ -115,16 +119,16 @@ static ETL_CONSTEXPR14 void encode(etl::span decoded, Encodes a span of data using the specified chunk size. -**Parameters:** +**Parameters** -- `decoded`: Source data to encode -- `encoded`: Destination for encoded data (must be twice the size of `decoded`) +`decoded`: Source data to encode +`encoded`: Destination for encoded data (must be twice the size of `decoded`) -**Template Parameters:** +**Template Parameters** -- `TChunk`: Chunk size for encoding (`uint8_t`, `uint16_t` or `uint32_t`) +`TChunk`: Chunk size for encoding (`uint8_t`, `uint16_t` or `uint32_t`) -**Example:** +**Example** ```cpp std::array data = {0x12, 0x34, 0x56, 0x78}; @@ -138,51 +142,56 @@ etl::manchester::encode(data, encoded_data1); etl::manchester::encode(data, encoded_data2); ``` -### Decoding Functions +## Decoding Functions -#### Decode single value +### Decode single value ```cpp template static ETL_CONSTEXPR14 typename decoded::type decode(TEncoded encoded) ``` +**Description** + Decodes a single Manchester encoded value. -**Parameters:** +**Parameters** -- `encoded`: The encoded value to decode (`uint16_t`, `uint32_t`, or `uint64_t`) +`encoded`: The encoded value to decode (`uint16_t`, `uint32_t`, or `uint64_t`) -**Returns:** +**Returns** -- The Manchester decoded value (half the bit width of input) +The Manchester decoded value (half the bit width of input) -**Example:** +**Example** ```cpp uint8_t decoded = etl::manchester::decode(0x5A5A); ``` +--- -#### Decode range +### Decode range ```cpp -template ::type> -static ETL_CONSTEXPR14 void decode(etl::span encoded, - etl::span decoded) +template ::type> +static ETL_CONSTEXPR14 +void decode(etl::span encoded, + etl::span decoded) ``` Decodes a span of Manchester encoded data. -**Parameters:** +**Parameters** -- `encoded`: Source data to decode -- `decoded`: Destination for decoded data (must be half the size of `encoded`) +`encoded`: Source data to decode +`decoded`: Destination for decoded data (must be half the size of `encoded`) -**Template Parameters:** +**Template Parameters** -- `TChunk`: Chunk type for decoding (`uint16_t`, `uint32_t`, or `uint64_t`) +`TChunk`: Chunk type for decoding (`uint16_t`, `uint32_t`, or `uint64_t`) -**Example:** +**Example** ```cpp std::array encoded = {/* ... */}; @@ -196,9 +205,9 @@ etl::manchester::decode(encoded, decoded1); etl::manchester::decode(encoded, decoded2); ``` -### Validation Functions +## Validation Functions -#### Single value +### Single value ```cpp template @@ -207,53 +216,53 @@ static ETL_CONSTEXPR14 bool is_valid(TChunk encoded) Validates that a single value contains valid Manchester encoded data. -**Parameters:** +**Parameters** -- `encoded`: The encoded value to validate +`encoded`: The encoded value to validate -**Returns:** +**Returns** -- `true` if the value contains valid Manchester encoded data, `false` otherwise +`true` if the value contains valid Manchester encoded data, `false` otherwise -**Example:** +**Example** ```cpp bool valid = etl::manchester::is_valid(0x5A5A); ``` -#### Range +### Range ```cpp -static ETL_CONSTEXPR14 bool is_valid(etl::span encoded) +static +ETL_CONSTEXPR14 +bool is_valid(etl::span encoded) ``` Validates that a range contains valid Manchester encoded data. -**Parameters:** +**Parameters** -- `encoded`: The range of encoded data to validate +`encoded`: The range of encoded data to validate -**Returns:** +**Returns** -- `true` if all data is valid Manchester encoding, `false` otherwise +`true` if all data is valid Manchester encoding, `false` otherwise -**Example:** +**Example** ```cpp std::array encoded_data = {/* ... */}; bool valid = etl::manchester::is_valid(encoded_data); ``` -## Supported Types +## Input/chunk types for encoding -### Input/chunk types for encoding +`uint8_t` → `uint16_t` (if 8-bit types are supported) +`uint16_t` → `uint32_t` +`uint32_t` → `uint64_t` (if 64-bit types are supported) -- `uint8_t` → `uint16_t` (if 8-bit types are supported) -- `uint16_t` → `uint32_t` -- `uint32_t` → `uint64_t` (if 64-bit types are supported) +## Input/chunk types for decoding -### Input/chunk types for decoding - -- `uint16_t` → `uint8_t` (if 8-bit types are supported) -- `uint32_t` → `uint16_t` -- `uint64_t` → `uint32_t` (if 64-bit types are supported) +`uint16_t` → `uint8_t` (if 8-bit types are supported) +`uint32_t` → `uint16_t` +`uint64_t` → `uint32_t` (if 64-bit types are supported) diff --git a/docs/containers/Views/_index.md b/docs/containers/Views/_index.md new file mode 100644 index 00000000..df454f87 --- /dev/null +++ b/docs/containers/Views/_index.md @@ -0,0 +1,6 @@ +--- +title: "Views" +weight: 100 +--- + +View like containers. \ No newline at end of file diff --git a/docs/containers/Views/array-view.md b/docs/containers/Views/array-view.md new file mode 100644 index 00000000..079c3f46 --- /dev/null +++ b/docs/containers/Views/array-view.md @@ -0,0 +1,373 @@ +--- +title: "array_view" +--- + +{{< callout >}} + Header: `array_view.h` + Since: All versions + Similar to: [gsl::array_view](https://learn.microsoft.com/en-us/previous-versions/cpp/parallel/amp/reference/array-view-class) +{{< /callout >}} + +This class implements a view in to a range of a C array, `etl::array`, `std::array`, `etl::vector` and `std::vector`. +It will support construction from any class that supports data() and size() member functions as well as plain C arrays. + +If `ETL_ARRAY_VIEW_IS_MUTABLE` is defined, then the contents of the view are mutable. +The view is non-mutable by default, which is the opposite to the behaviour in 17.5.0 or earlier. + +```cpp +etl::array_view +``` + +## Template deduction guides +**C++17 and above** +```cpp +template +etl::array_view(TArray& a) + -> etl::array_view; +``` +```cpp +template +etl::array_view(const TIterator begin_, const TIterator end_) + -> etl::array_view>; +``` +```cpp +template +etl::array_view(const TIterator begin_, const TSize size_) + -> etl::array_view>; +``` + +## Examples + +```cpp +etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + +etl::array_view view1{ data }; +etl::array_view view2{ data.begin(), data.end() }; +etl::array_view view3{ data.begin(), data.size() }; +etl::array_view view4{ view1 }; +``` +## Member types + +`value_type` +`size_type` +`difference_type` +`reference` +`const_reference` +`pointer` +`const_pointer` +`iterator` +`const_iterator` +`reverse_iterator` +`const_reverse_iterator` + +## Constructors + +```cpp +ETL_CONSTEXPR array_view() +``` +**Description** +Default constructor. + +--- + +```cpp +template +ETL_CONSTEXPR explicit array_view(TArray& a) +``` +**Description** +Construct from array or vector like class. + +--- + +```cpp +template +ETL_CONSTEXPR array_view(TIterator begin_, TIterator end_) +``` +**Description** +Construct from an iterator or pointer range. + +--- + +```cpp +template +ETL_CONSTEXPR array_view(TIterator begin_, TSize size_) +``` +**Description** +Construct from a start and size + +--- + +```cpp +template +ETL_CONSTEXPR explicit array_view(T(&begin_)[ARRAY_SIZE]) +``` +**Description** +Construct from a compile time sized C array. + +--- + +```cpp +ETL_CONSTEXPR array_view(const array_view& other) +``` +**Description** +Copy constructor. + +## Modifiers + +```cpp +template +void assign(TIterator begin_, TIterator end_) +``` +**Description** +Assigns begin and end of the supplied range. +Does not copy the elements in the range. + +--- + +```cpp +template +void assign(TIterator begin_, TSize size_) +``` +**Description** +Assign from a start iterator and length. +Does not copy the elements in the range. + +--- + +```cpp +void remove_prefix(size_type n) +``` +**Description** +Shrinks the view from the front. +A value of `n` larger than the array will result in undefined behaviour. + +--- + +```cpp +void remove_suffix(size_type n) +``` +**Description** +Shrinks the view from the back. +A value of `n` larger than the array will result in undefined behaviour. + +--- +```cpp +void fill(value_type value) +``` +*Introduced:* `20.24.0` + +**Description** +Fill the underlying array with value. + +## Element access + +Mutable access is only possible by defining the macro `ETL_ARRAY_VIEW_IS_MUTABLE`. +In this case, `reference`, `pointer`, `iterator` and `reverse_iterator` are defined as their `const` counterparts. + +```cpp +reference at(size_t i) +const_reference at(size_t i) const +``` +**Description** +Gets a reference or const reference to the indexed element. +Emits an `etl::array_view_uninitialised` if the view is not initialised. +Emits an `etl::array_view_bounds` if the index is not in range. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +**Parameters** +`i` The index. + +**Returns** +A reference or const reference to the indexed element + +--- + +```cpp +reference operator[](size_t i) +const_reference operator[](size_t i) const +``` +**Description** +Gets a reference or const reference to the indexed element. + +**Returns** +A reference or const reference to the indexed element. +Undefined behaviour if the `array_view` is empty. + +--- + +```cpp +reference front() +const_reference front() const +``` +**Description** +Gets a reference or const reference to the first element. + +**Returns** +A reference or const reference to the first element. +Undefined behaviour if the `array_view` is empty. + +--- + +```cpp +reference back() +const_reference back() const +``` +**Description** +Gets a reference or const reference to the last element. + +**Returns** +A reference or const reference to the last element. +Undefined behaviour if the `array_view` is empty. + +--- + +```cpp +pointer data() +const_pointer data() const +``` +**Description** +Gets a pointer or const pointer to the first element. + +**Returns** +A pointer or const pointer to the first element. +Equal to `end()` if the array_view is empty. + +## Iterators +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the array view. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the array view. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Gets a reverse iterator to the beginning of the array view. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Gets a reverse iterator to the end of the array view. + +--- + +Capacity + +```cpp +bool empty() const +``` +**Description** +Returns true if the size of the array view is zero, otherwise false. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the view. + +--- + +``` +C++size_t max_size() const +``` +**Description** +Returns the maximum possible size of the view. + +--- + +## Non-member functions +**Lexicographically comparisons** +```cpp +operator == +``` +**Description** +`true` if the contents of the lists are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the lists are not equal, otherwise `false`. + +--- + +```cpp +operator < +``` +**Description** +`true` if the contents of the lhs are lexicographically less than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator <= +``` +**Description** +`true` if the contents of the lhs are lexicographically less than or equal to the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator > +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator >= +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than or equal to the contents of the rhs, otherwise `false`. + + +## Hash +There are specialisations of `etl::hash` for `array_view`. + +## Example +```cpp +etl::array data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + +typedef etl::array_view View; + +View view(data.begin() + 2, data.end() - 2); + +void Print(const View& view) +{ + for (size_t i = 0; i < view.size(); ++i) + { + std::cout << view[i] << " "; + } +} + +Print(view); // Prints "3 4 5 6 7 8" + +size_t hashvalue = etl::hash()(view); +``` \ No newline at end of file diff --git a/docs/containers/Views/array-wrapper.md b/docs/containers/Views/array-wrapper.md new file mode 100644 index 00000000..c84afe5d --- /dev/null +++ b/docs/containers/Views/array-wrapper.md @@ -0,0 +1,266 @@ +--- +title: "array_wrapper" +--- + +{{< callout >}} + Header: `array_wrapper.h` + Since: All versions +{{< /callout >}} + +This class implements a zero cost C++ interface around a const or non-const C array. It presents the same API as std::array. +It allows legacy C data to be more easily integrated with C++ interfaces and be accessed in a less error prone fashion. +If C++11 or above is supported then most functions can be 'constexpr'. + +--- + +## Member types + +`value_type` +`size_type` +`difference_type` +`reference` +`value_type` +`reference` +`const_reference` +`pointer` +`const_pointer` +`iterator` +`const_iterator` +`reverse_iterator` +`const_reverse_iterator` + +## Member constants +**May be used as indexes in to the array.** + +`SIZE =` Size of the array +`MAX_SIZE = SIZE` +`FRONT = 0` +`BACK = SIZE - 1` +`BEGIN = 0` +`END = SIZE` +`RBEGIN = SIZE - 1` +`REND = -1` + +## Element access +```cpp +T& at(size_t i) +``` +```cpp +ETL_CONSTEXPR const T& at(size_t i) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Emits an `etl::array_wrapper_bounds` if the index isout of range of the array. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- +```cpp +T& operator[](size_t i) +``` +```cpp +ETL_CONSTEXPR const T& operator[](size_t i) const +``` +**Description** +Returns a reference or const reference to the indexed element.if the index is out of range of the array then undefined behaviour occurs.--- + +--- + +```cpp +T& front() +``` +```cpp +ETL_CONSTEXPR const T& front() const +``` +**Description** +Returns a reference or const reference to the first element.--- + +--- + +```cpp +T& back() +``` +```cpp +ETL_CONSTEXPR const T& back() const +``` +**Description** +Returns a reference or const reference to the last element.--- + +--- + +```cpp +T* data() +``` +```cpp +ETL_CONSTEXPR const T* data() const +``` +**Description** +Returns a pointer or const pointer to the array.---Modifiers + +--- +```cpp +void fill(parameter_t value) +``` +**Description** +Fill a non-cost array with the value.--- + +--- + +```cpp +template +void swap(etl::array_wrapper& other) +``` +**Description** +Swaps the array contents with another.---Iterators + +--- + +```cpp +ETL_CONSTEXPR iterator begin() +``` +```cpp +ETL_CONSTEXPR const_iterator begin() constETL_CONSTEXPR const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the array.--- + +--- + +```cpp +ETL_CONSTEXPR iterator end() +``` +```cpp +ETL_CONSTEXPR const_iterator end() constETL_CONSTEXPR const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the array.--- + +--- + +```cpp +ETL_CONSTEXPR iterator rbegin() +``` +```cpp +ETL_CONSTEXPR const_reverse_iterator rbegin() const +``` +```cpp +ETL_CONSTEXPR const_reverse_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the array.--- + +--- + +```cpp +ETL_CONSTEXPR iterator rend() +``` +```cpp +ETL_CONSTEXPR const_reverse_iterator rend() constETL_CONSTEXPR const_reverse_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the array.---Capacity + +--- + +```cpp +ETL_CONSTEXPR size_t size() const +``` +**Description** +Returns the size of the view.--- + +--- + +```cpp +ETL_CONSTEXPR size_t max_size() const +``` +**Description** +Returns the maximum possible size of the view.---Non-member functions + +## Lexicographically comparisons + +`operator ==` +**Returns** +`true` if the contents of the array views are equal, otherwise `false`. + +`operator !=` +**Returns** +`true` if the contents of the array views are not equal, otherwise `false`. + +`operator <` +**Returns** +`true` if the contents of the lhs are lexicographically less than the +contents of the rhs, otherwise `false`. + +`operator <=` +**Returns** +`true` if the contents of the lhs are lexicographically less than or equal to the +contents of the rhs, otherwise `false`. + +`operator >` +**Returns** +`true` if the contents of the lhs are lexicographically greater than the +contents of the rhs, otherwise `false`. + +`operator >=` +**Returns** +`true` if the contents of the lhs are lexicographically greater than or equal to the +contents of the rhs, otherwise `false` + +## Swap +```cpp +template +void swap(etl::array_wrapper& lhs, + etl::array_wrapper& rhs) +``` +**Description** +Swaps the array contents of two arrays. + +## Hash +There is a specialisation for `etl::hash` for `array_wrapper`. + +## Macros +A macro is defined to ease the use of the class. + +```cpp +ETL_ARRAY_WRAPPER(type, array); +``` + +**Example** + +```cpp +// The address of the array MUST be deducible at compile time. +int cdata = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + +typedef ETL_ARRAY_WRAPPER(int, cdata) Data; + +// All instances of 'Data' access the SAME array.Data data; +void Print(Data data) +{ + Data::const_iterator itr = data.begin(); + + while (itr != data.end()) + { + std::cout << *itr++ << " "; + } +} + +Print(data); // Prints "1 2 3 4 5 6 7 8 9 10" + +size_t hashvalue = etl::hash()(data); + +// Using indexes +int firstElement = data[Data::FRONT]; + +int lastElement = data[Data::BACK]; + +// Using forward indexes +for (int i = Data::BEGIN; i < Data::END; ++i) +{ + std::cout << data[i] << " "; +} + +// Using reverse indexes +for (int i = Data::RBEGIN; i < Data::REND; --i) +{ + std::cout << data[i] << " "; +} +``` diff --git a/docs/containers/Views/multi-range.md b/docs/containers/Views/multi-range.md new file mode 100644 index 00000000..20d97950 --- /dev/null +++ b/docs/containers/Views/multi-range.md @@ -0,0 +1,291 @@ +--- +title: "multi_range" +--- + +A lightweight, chainable range system that simulates nested loops over multiple ranges, with customisable stepping and end conditions. + +`etl::multi_range` is a composable range-iteration helper that can chain multiple ranges to produce nested-loop style iteration. It lets you build “outer/inner” ranges and iterate across all combinations, while customizing stepping and termination logic. + +Each range is defined as an `etl::multi_range` which may be linked to create nested multiple ranges. + +```cpp +template +class multi_range +``` + +All multi_range classes derive from `imulti_range`. + +By default, each call to next() will invoke either the forward_step or reverse_step types. +If the type is an arithmetic or pointer type then the default stepper will be automatically selected, dependent on the first and last parameters. If not, the default will be `forward_step`. + +If a custom stepper for the type is required, then it may be defined in the constructor. + +By default, each call to `completed()` will invoke `not_equal_compare` against the terminating range value. If a custom incrementor for the type is required, then it may be defined in the constructor. + +## Types + +`value_type` +The type of the range. + +`const_reference` +The const reference type of the range. + +--- + +`step_type` +Pure abstract base. +Inherit from this to define custom step functionality. + +`forward_step` +A pre-defined step type that calls the type's `operator++()`. +This is the default step type if the type is arithmetic or random access iterator and the range is ascending, or the type is not an arithmetic or pointer. + +`forward_step_by` +A pre-defined step type that calls the type's `operator+=()`. +The constructor requires the step value to add. + +`reverse_step` +A pre-defined step type that calls the type's `operator--()`. +This is the default step type if the type is arithmetic or random access iterator and the range is descending. + +`reverse_step_by` +A pre-defined step type that calls the type's `operator-=()`. +The constructor requires the step value to subtract. + +--- + +`compare_type` +Pure abstract base. +Inherit from this to define custom compare functionality. + +`not_equal_compare` +A pre-defined step type that calls etl::not_equal_to. +This is the default compare type. + +`less_than_compare` +A pre-defined step type that calls `etl::less`. + +`greater_than_compare` +A pre-defined step type that calls `etl::greater`. + +## Constructor + +```cpp +multi_range(value_type start, + value_type last) +``` +**Description** +Initialises the loop where start is the initial value and last is the terminate value. + +--- + +```cpp +multi_range(value_type first, + value_type last, + step_type& stepper) +``` +**Description** +Initialises the loop where start is the initial value and last is the terminate value. +stepper will be called to increment the current range value. + +--- + +```cpp +multi_range(value_type first, + value_type last, + compare_type& compare) +``` +**Description** +Initialises the loop where start is the initial value and last is the terminate value. +compare will be called to compare with the terminating value. + +--- + +```cpp +multi_range(value_type first, + value_type last, + step_type& stepper, + compare_type& compare) +``` +**Description** +Initialises the loop where start is the initial value and last is the terminate value. +stepper will be called to increment the current range value. +compare will be called to compare with the terminate value. + +## Modifiers + +The nested ranges may be constructed in a variety of ways. + +```cpp +imulti_range& append(imulti_range& inner_ranges) +``` +**Description** +Appends inner loop(s) to the current range(s). +If the current range, **A**, is linked to ranges **B** & **C** in the order **A** -> **B** -> **C** and the new linked ranges are **D** -> **E**, +`A.append(D)` will result in **A** -> **B** -> **C** -> **D** -> **E**. + +--- + +```cpp +imulti_range& insert(imulti_range& inner_ranges) +``` +**Description** +Inserts inner range(s) after the current range. +If the current range, **A**, is linked to ranges **B** & **C** in the order **A** -> **B** -> **C** and the new linked ranges are **D** -> **E**, +`A.insert(D)` will result in **A** -> **D** -> **E** -> **B** -> **C**. + +--- + +```cpp +void detach() +``` +**Description** +Unlinks this range from its inner ranges. + +--- + +```cpp +void detach_all() +``` +**Description** +Unlinks this range and all its inner ranges from each other. + +## Access + +```cpp +const_reference value() const; +``` +**Description** +Gets a const reference to the current value + +--- + +```cpp +const_reference begin() const; +``` +**Description** +Gets a const reference to the first value + +--- + +```cpp +const_reference end() const; +``` +**Description** +Gets a const reference to the terminate value + +--- + +```cpp +bool completed() const +``` +**Description** +Returns true if the range, and all of its inner ranges, have completed. + +--- + +```cpp +size_t number_of_ranges() const +``` +**Description** +Returns the number of linked ranges, starting from this. +For linked ranges **A** -> **B** -> **C** -> **D** -> **E**, `B.number_of_ranges()` returns `4`. + +--- + +```cpp +size_t number_of_iterations() +``` +**Description** +Returns the total number of iterations for all linked ranges, starting from this. +For linked ranges **A** -> **B** -> **C** -> **D** -> **E**, and a range size of `5` for each one, +`B.number_of_iterations()` returns `625` (`5 * 5 * 5 * 5`). + +This function is not const as it must simulate the running of all of the nested ranges. + +## Operations + +```cpp +void start() +``` +**Description** +Resets the range, and all its linked inner ranges to the starting conditions, with each range reset to its begin value. + +--- + +```cpp +void next() +``` +**Description** +Moves to the next iteration of the nested range. + +--- + +## Example + +```cpp +using Iterator = std::forward_list::const_iterator; + +// Less Than compare type +using LessThanCompare = etl::multi_range::less_than_compare; + +// Decrementing step type +using DecrementPtr = etl::multi_range::reverse_step; + +using Outer = etl::multi_range; // Incrementing int +using Middle = etl::multi_range; // Decrementing const short* +using Inner = etl::multi_range; // Incrementing const_iterator + +const short data[4] = { 0, 1, 2, 3 }; + +std::forward_list strings = +{ + "zero", "one", "two", "three" +}; + +LessThanCompare lessThan; +DecrementPtr decrementPtr; + +// Setup the loops. +Outer outer(0, 4, lessThan); +Middle middle(data + 3, data - 1, decrementPtr); +Inner inner(strings.begin(), strings.end()); + +outer.append(middle).append(inner); + +size_t n_outer_loops = outer.number_of_loops(); // == 3 +size_t n_middle_loops = middle.number_of_loops(); // == 2 +size_t n_inner_loops = inner.number_of_loops(); // == 1 + +size_t n_outer_iterations = outer.number_of_iterations(); // == 64 +size_t n_middle_iterations = middle.number_of_iterations(); // == 16 +size_t n_inner_iterations = inner.number_of_iterations(); // == 4 + +// Create const references to the loop values. +const int& value_outer = outer.value(); +const short*& value_middle = middle.value(); +const Iterator& value_inner = inner.value(); + +// Iterate through the nested loops. +int i = 0; + +for (outer.start(); !outer.completed(); outer.next()) +{ + std::cout << "Iteration " << i++ << " : " + << "Outer = " << value_outer << " : " + << "Middle = " << *value_middle << " : " + << "Inner = " << *value_inner + << "\n"; +} + +// Just iterate through the two nested loops. +i = 0; + +for (middle.start(); !middle.completed(); middle.next()) +{ + std::cout << "Iteration " << i++ << " : " + << "Middle = " << *value_middle << " : " + << "Inner = " << *value_inner + << "\n"; +} +``` diff --git a/docs/containers/Views/multi-span.md b/docs/containers/Views/multi-span.md new file mode 100644 index 00000000..0c2fd2ed --- /dev/null +++ b/docs/containers/Views/multi-span.md @@ -0,0 +1,189 @@ +--- +title: "multi_span" +--- + +{{< callout >}} + Header: `multi_span.h` +{{< /callout >}} + +This class implements a span of a range of spans. +Allows implementation of Scatter/Gather to multiple buffers or ports. +Iterating through the `multi_span` will iterate through the collection of spans consecutively. +The list of spans must be in a contiguous list, such as an array or vector. + +```cpp +etl::multi_span +``` +Where `T` is the element type of the spans. + +## Member types + +```cpp +element_type T +value_type remove_cv::type +size_type size_t +difference_type ptrdiff_t +reference value_type& +const_reference const value_type& +pointer value_type* +const_pointer const value_type* +iterator Forward iterator <20.39.5 + Bidirectional iterator >=20.39.5 +const_iterator Constant Forward iterator <20.39.5 + Constant bidirectional iterator >=20.39.5 +reverse_iterator ETL_OR_STD::reverse_iterator +const_reverse_iterator ETL_OR_STD::reverse_iterator + +span_type etl::span +span_list_type etl::span +``` + +## Constructors + +ETL_CONSTEXPR multi_span(span_list_type span_list) +**Description** +Construct from a span of spans. + +--- + +template +ETL_CONSTEXPR multi_span(TContainer& a) ETL_NOEXCEPT +**Description** +Construct from a container of spans. + +--- + +template +ETL_CONSTEXPR multi_span(const TContainer& a) ETL_NOEXCEPT +**Description** +Construct from a const container of spans. + +--- + +template +ETL_CONSTEXPR multi_span(TIterator begin, TIterator end) +**Description** +Construct from a range of spans. + +--- + +template +ETL_CONSTEXPR multi_span(TIterator begin, size_t length) +**Description** +Construct from a range of spans. + +--- + +ETL_CONSTEXPR multi_span(const multi_span& other) +**Description** +Copy constructor. + +## Access + +```cpp +ETL_CONSTEXPR14 multi_span& operator =(const multi_span& other) ETL_NOEXCEPT +``` +**Description** +Assign from a other `multi_span`. + +## Iterators + +```cpp +ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the beginning of the span. + +--- + +```cpp +ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the end of the span. + +--- + +```cpp +ETL_CONSTEXPR iterator cbegin() const ETL_NOEXCEPT +``` +**Description** +Returns a const iterator to the beginning of the span. +From: `20.39.5` + +--- + +```cpp +ETL_CONSTEXPR iterator cend() const ETL_NOEXCEPT +``` +**Description** +Returns a const iterator to the end of the span. +From: `20.39.5` + +--- + +```cpp +ETL_CONSTEXPR iterator rbegin() const ETL_NOEXCEPT +``` +**Description** +Returns a reverse iterator to the beginning of the span. +From: `20.39.5` + +--- + +```cpp +ETL_CONSTEXPR iterator rend() const ETL_NOEXCEPT +``` +**Description** +Returns a reverse iterator to the end of the span. +From: `20.39.5` + +--- + +```cpp +ETL_CONSTEXPR iterator crbegin() const ETL_NOEXCEPT +``` +**Description** +Returns a const reverse iterator to the beginning of the span. +From: `20.39.5` + +--- + +```cpp +ETL_CONSTEXPR iterator crend() const ETL_NOEXCEPT +``` +**Description** +Returns a const reverse iterator to the end of the span. +From: `20.39.5` + +## Capacity + +```cpp +ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT +``` +**Description** +Returns true if the size of the multi_span is zero, otherwise false. + +--- + +```cpp +ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT +``` +**Description** +Returns the size of the multi_span. + +--- + +```cpp +ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT +``` +**Description** +Returns the size of the multi_span in bytes. + +--- + +```cpp +ETL_CONSTEXPR size_t size_spans() const ETL_NOEXCEPT +``` +**Description** +Returns the number of the spans. diff --git a/docs/containers/Views/poly-span.md b/docs/containers/Views/poly-span.md new file mode 100644 index 00000000..376c35ef --- /dev/null +++ b/docs/containers/Views/poly-span.md @@ -0,0 +1,361 @@ +--- +title: "poly_span" +--- + +{{< callout >}} + Header: `poly_span.h` + From: `20.31.0` +{{< /callout >}} + +Polymorphic span. +This class implements a view in to a contiguous range through a base type. + +```cpp +etl::poly_span +``` + +## Template deduction guides +C++17 + +```cpp +template +poly_span(const TIterator begin, const TIterator end) + ->poly_span, etl::dynamic_extent>; +``` + +```cpp +template +poly_span(const TIterator begin, const TSize size) + ->poly_span, etl::dynamic_extent>; +``` + +```cpp +template +poly_span(T(&)[N]) + -> poly_span; +``` + +```cpp +template +poly_span(etl::array&) + -> poly_span; +``` + +```cpp +template +poly_span(const etl::array&) + -> poly_span; +``` + +```cpp +template +poly_span(std::array&) + ->poly_span; +``` + +```cpp +template +poly_span(const std::array&) + ->poly_span; +``` + +## Member types + +```cpp +element_type T +value_type remove_cv::type +size_type size_t +difference_type ptrdiff_t +reference value_type& +const_reference const value_type& +pointer value_type* +const_pointer const value_type* +iterator Random access iterator +reverse_iterator ETL_OR_STD::reverse_iterator +``` + +## Constructors + +```cpp +ETL_CONSTEXPR poly_span() ETL_NOEXCEPT +``` + +--- + +```cpp +template +ETL_CONSTEXPR poly_span(const TIterator begin, const TSize size) ETL_NOEXCEPT +``` +**Description** +Static asserts if `etl::iterator_traits::iterator_category` is not `random_access_iterator_tag` +or `etl::iterator_traits::value_type` is not the same as, or not derived from `TBase`. + +--- + +```cpp +template +ETL_CONSTEXPR poly_span(const TIterator begin, const TIterator end) +``` +**Description** +Static asserts if `etl::iterator_traits::iterator_category` is not `random_access_iterator_tag` +or `etl::iterator_traits::value_type` is not the same as, or not derived from `TBase`. + +--- + +```cpp +template +ETL_CONSTEXPR poly_span(U(&begin_)[N]) ETL_NOEXCEPT +``` +**Description** +Static asserts if `N` is greater than `Extent` or `etl::iterator_traits::value_type` is not the same as, or not derived from `TBase`. + +--- + +```cpp +template +ETL_CONSTEXPR poly_span(etl::array& a) ETL_NOEXCEPT +``` +**Description** +Static asserts if `N` is greater than `Extent` or `etl::iterator_traits::value_type` is not the same as, or not derived from `TBase`. + +--- + +```cpp +template +ETL_CONSTEXPR poly_span(const etl::array& a) ETL_NOEXCEPT +``` +**Description** +Static asserts if `N` is greater than `Extent` or `etl::iterator_traits::value_type` is not the same as, or not derived from `TBase`. + +--- + +```cpp +template +ETL_CONSTEXPR poly_span(std::array& a) ETL_NOEXCEPT +``` +**Description** +Enabled if `ETL_USING_CPP11` and `ETL_USING_STL` are `true`. +Static asserts if `N` is greater than `Extent` or `etl::iterator_traits::value_type` is not the same as, or not derived from `TBase`. + +--- + +```cpp +template +ETL_CONSTEXPR poly_span(const std::array& a) ETL_NOEXCEPT +``` +**Description** +Enabled if `ETL_USING_CPP11` and `ETL_USING_STL` are `true`. +Static asserts if `N` is greater than `Extent` or `etl::iterator_traits::value_type` is not the same as, or not derived from `TBase`. + +--- + +```cpp +ETL_CONSTEXPR poly_span(const poly_span& other) +``` +**Description** +Copy constructor. + +## Access + +```cpp +ETL_CONSTEXPR reference operator[](size_t i) const +``` +**Description** +Returns a reference to the indexed element. +Index out of range results in undefined behaviour. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT +``` +**Description** +Returns a reference to the first element. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT +``` +**Description** +Returns a reference to the last element. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR pointer data() const ETL_NOEXCEPT +``` +**Description** +Returns a pointer to the first element. + +--- + +```cpp +ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT +``` +**Description** +Assign from a other span + +--- + +```cpp +template +ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT +``` +**Description** +Assign from a other span. + +--- + +```cpp +template +ETL_NODISCARD ETL_CONSTEXPR etl::poly_span first() const +``` +**Description** +Returns a span consisting of the first `COUNT` elements of the current span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR etl::poly_span last(size_t count) const +``` +**Description** +Returns a span consisting of the last count elements of the current span. + +--- + +```cpp +template +ETL_NODISCARD ETL_CONSTEXPR etl::poly_span last() const +``` +**Description** +Returns a span consisting of the last `COUNT` elements of the current span + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR etl::poly_span first(size_t count) const +``` +**Description** +Returns a span consisting of the first count elements of the current span. + +--- + +```cpp +template +ETL_NODISCARD ETL_CONSTEXPR etl::poly_span subspan() const +``` +**Description** +Returns a subspan consisting of the range starting at `OFFSET` for `COUNT` elements of the current span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR etl::poly_span subspan(size_t offset, size_t count = etl::dynamic_extent) const +``` +**Description** +Returns a subspan consisting of the range starting at `offset` for `count` elements of the current span. + +## Iterators + +```cpp +ETL_NODISCARD ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the beginning of the span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the end of the span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR iterator rbegin() const ETL_NOEXCEPT +``` +**Description** +Returns a reverse iterator to the beginning of the span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR iterator rend() const ETL_NOEXCEPT +``` +**Description** +Returns a reverse iterator to the end of the span. + +## Capacity + +```cpp +ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT +``` +**Description** +Returns true if the size of the span is zero, otherwise false. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT +``` +**Description** +Returns the size of the span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT +``` +**Description** +Returns the size of the span in bytes. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR size_t size_of_element() const ETL_NOEXCEPT +``` +**Description** +Returns the size of the elements pointed to by the span, in bytes. + +## Non-member functions + +### Hash +There is a specialisation of `etl::hash` for `etl::poly_span`. + +--- + +### Example +```cpp +struct Base +{ + virtual ~Base() {} + virtual void Print() const = 0; +}; + +struct Derived : Base +{ + Derived(int i_) + : i(i_) + { + } + + void Print() const override + { + std::cout << "Derived " << i << "\n"; + } + + int i; +}; + +etl::array data{ Derived(1), Derived(2), Derived(3), Derived(4) }; + +etl::poly_span ps{ data }; + +for (const Base& b : ps) +{ + b.Print(); +} +``` diff --git a/docs/containers/Views/span.md b/docs/containers/Views/span.md new file mode 100644 index 00000000..8fb131f7 --- /dev/null +++ b/docs/containers/Views/span.md @@ -0,0 +1,410 @@ +--- +title: "span" +--- + +{{< callout >}} + Header: `span.h` + Similar to: `std::span` +{{< /callout >}} + +This class implements a view in to a range of a C array, `etl::array`, `std::array`, `etl::vector` and `std::vector`. +It will support construction from any class that supports `data()` and `size()` member functions as well as plain C arrays. + +From: `20.34.0` +The ETL's span adds the ability to access circular iterators that will loop through the span when the beginning or end is reached. + +```cpp +etl::span +``` + +## Template deduction guides +C++17 + +```cpp +template +span(const TIterator begin, const TIterator end) + ->span, etl::dynamic_extent>; +``` + +```cpp +template +span(const TIterator begin, const TSize size) + ->span, etl::dynamic_extent>; +``` + +```cpp +template +span(T(&)[N]) + -> span; +``` + +```cpp +template +span(etl::array&) + -> span; +``` + +```cpp +template +span(const etl::array&) + -> span; +``` + +```cpp +template +span(std::array&) + ->span; +``` + +```cpp +template +span(const std::array&) + ->span; +``` + +### Examples +```cpp +etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + +etl::span span1{ data }; +etl::span span2{ data.begin(), data.end() }; +etl::span span3{ data.begin(), data.size() }; +etl::span span4{ span1 }; + +int c_array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; +etl::span span5{ c_array }; +``` + +## Member types + +```cpp +element_type T +value_type remove_cv::type +size_type size_t +difference_type ptrdiff_t +reference value_type& +const_reference const value_type& +pointer value_type* +const_pointer const value_type* +iterator A random access iterator +reverse_iterator A reverse random access iterator +circular_iterator A circular random access iterator 20.34.0 +circular_reverse_iterator A reverse circular random access iterator 20.34.0 +``` + +## Constructors + +```cpp +ETL_CONSTEXPR span() +``` +**Description** +Default constructor. + +--- + +```cpp +template +ETL_CONSTEXPR span(TIterator begin, TIterator end) +``` +**Description** +Construct from an iterator or pointer range. + +--- + +```cpp +template +ETL_CONSTEXPR span(TIterator begin, TSize size) +``` +**Description** +Construct from a start and size + +--- + +```cpp +template +ETL_CONSTEXPR explicit span(element_type(&begin)[ARRAY_SIZE]) +``` +**Description** +Construct from a compile time sized C array. + +--- + +```cpp +template +ETL_CONSTEXPR span(etl::array& a) ETL_NOEXCEPT +``` +**Description** +Construct from an ETL array. + +--- + +```cpp +template +ETL_CONSTEXPR span(const etl::array& a) ETL_NOEXCEPT +``` +**Description** +Construct from a const ETL array. + +--- + +```cpp +template +ETL_CONSTEXPR span(std::array& a) ETL_NOEXCEPT +``` +**Description** +Enabled if `ETL_USING_CPP11` and `ETL_USING_STL` are `true`. +Construct from an STL array. + +--- + +```cpp +template +ETL_CONSTEXPR span(const std::array& a) ETL_NOEXCEPT +``` +**Description** +Enabled if `ETL_USING_CPP11` and `ETL_USING_STL` are `true`. +Construct from a const STL array. + +--- + +```cpp +ETL_CONSTEXPR span(const span& other) ETL_NOEXCEPT +``` +**Description** +Copy constructor. + +--- + +```cpp +template +ETL_CONSTEXPR span(const etl::span& other) ETL_NOEXCEPT +``` + +## Access + +```cpp +ETL_CONSTEXPR reference operator[](size_t i) const +``` +**Description** +Returns a reference to the indexed element. +Index out of range results in undefined behaviour. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT +``` +**Description** +Returns a reference to the first element. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT +``` +**Description** +Returns a reference to the last element. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR pointer data() const ETL_NOEXCEPT +``` +**Description** +Returns a pointer to the first element. + +--- + +```cpp +ETL_CONSTEXPR14 span& operator =(const span& other) ETL_NOEXCEPT +``` +**Description** +Assign from a other span + +--- + +```cpp +template +ETL_NODISCARD ETL_CONSTEXPR etl::span first() const +``` +**Description** +Returns a span consisting of the first `COUNT` elements of the current span + +--- + +```cpp +template +ETL_NODISCARD ETL_CONSTEXPR etl::span last() const +``` +**Description** +Returns a span consisting of the last `COUNT` elements of the current span + +--- + +```cpp +template +ETL_NODISCARD ETL_CONSTEXPR etl::span subspan() const +``` +**Description** +Returns a subspan consisting of the range starting at `OFFSET` for `COUNT` elements of the current span + +## Iterators + +```cpp +ETL_NODISCARD ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the beginning of the span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR circular_iterator begin_circular() const ETL_NOEXCEPT +``` +**Description** +Returns a circular iterator to the beginning of the span. +From: `20.34.0` + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the end of the span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR iterator rbegin() const ETL_NOEXCEPT +``` +**Description** +Returns a reverse iterator to the beginning of the span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR reverse_circular_iterator rbegin_circular() const ETL_NOEXCEPT +``` +**Description** +Returns a reverse circular iterator to the beginning of the span. +From: `20.34.0` + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR iterator rend() const ETL_NOEXCEPT +``` +**Description** +Returns a reverse iterator to the end of the span. + +## Capacity + +```cpp +ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT +``` +**Description** +Returns `true` if the size of the span is zero, otherwise `false`. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT +``` +**Description** +Returns the size of the span. + +--- + +```cpp +ETL_NODISCARD ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT +``` +**Description** +Returns the size of the span in bytes. + +## Non-member functions + +```cpp +template +ETL_NODISCARD +ETL_CONSTEXPR +bool operator ==(const etl::span& lhs, const etl::span& rhs) ETL_NOEXCEPT +``` +**Description** +Compare two spans for equality. +Returns true if they both point to the same range of data. +From: `20.35.12` + +--- + +```cpp +template +ETL_NODISCARD +ETL_CONSTEXPR +bool operator !=(const etl::span& lhs, const etl::span& rhs) ETL_NOEXCEPT +``` +**Description** +Compare two spans for inequality. +Returns true if they don't both point to the same range of data. +From: `20.35.12` + +--- + +```cpp +template +bool equal(const etl::span& lhs, const etl::span& rhs) +``` +**Description** +Equality function. +Performs a comparision of the range values. +Returns `true` if one of the following are `true` +1. Both spans are empty. +2. They both point to the same range of data. +3. The values in the two ranges are equal. + +From: `20.35.12` + +## Hash +There is a specialisation of etl::hash for etl::span + +### Example + +**Iterating through a span and subspan.** + +```cpp +etl::array data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; +using View = etl::span; +View view(data.begin() + 2, data.end() - 2); + +void Print(const View& view) +{ + for (size_t i = 0; i < view.size(); ++i) + { + std::cout << view[i] << " "; + } +} + +Print(view); // Prints "3 4 5 6 7 8" + +auto subview = view.subspan<2, 3>(); + +Print(subview); // Prints "5 6 7" + +size_t hashvalue = etl::hash()(view); +``` + +**Looping a span.** + +```cpp +etl::array data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; +using View = etl::span; +View view(data.begin(), data.end()); + +View::circular_iterator itr = view.begin_circular(); + +// Loop through the data for 1000 iterations. +for (int i; i < 1000; ++i) +{ + Print(*itr++); +} +``` diff --git a/docs/containers/_index.md b/docs/containers/_index.md new file mode 100644 index 00000000..20c8c138 --- /dev/null +++ b/docs/containers/_index.md @@ -0,0 +1,66 @@ +--- +title: "Containers" +weight: 100 +--- + +## Containers +The library defines a set of containers that have been specially tailored for embedded systems. They have a maximum capacity fixed at compile time and make no calls to `malloc`/`free` or `new`/`delete`. They are completely deterministic. + +Most container types have been designed to mimic, as far as possible, those found in the STL. Some do not have direct STL equivalents. + +As the storage for all of the container types is allocated as a contiguous block, they are extremely cache friendly. + +**Note:** +Unlike the STL, the ETL's `vector` really *is* a container and actually *does* contains `bool`. +If you require a compact Boolean container then `etl::bitset` may be more appropriate. + +## Intrusive containers +There are intrusive versions of certain containers. These do not store copies of the inserted values, but link to the original objects. Certain types of intrusive container require that the stored object derives from an intrusive link. + +Most intrusive containers do not have a maximum fixed capacity. +See here for more information. + +To eliminate code bloat, most container templates utilise 'hoisting' where functionality, independent of the size and/or type, is separated out in to base classes. + +For example, `vector` and `vector` will share code from `ivector`. +`vector`, `vector` and `vector` will all share code from `vector_base`. + +The `i` prefixed container types may be used as size independent pointer or reference types for all sizes of thederived type. + +```cpp +etl::vector vector1; +etl::vector vector2; + +etl::ivector* pvector; + +pvector = &vector1;pvector->push_back(3); +pvector = &vector2;pvector->push_back(4); +``` + +## Move semantics and rvalue references +The following containers support rvalue references and move semantics. + +`vector` +`deque` +`list` +`forward_list` +`flat_set` +`flat_multiset` +`flat_map` +`flat_multimap` + +*This list may be out of date*. + +## Differences from the STL containers +As the containers have a fixed capacity, most also implement `full()` and `available()` member functions. + +Most of the containers allocate their storage from an internal instance of `etl::pool`. +Because of this the containers have a certain set of attributes that differ from the standard library. +- The storage for all containers is contiguous, thereby enhancing cache hits. +- No heap memory is used; no OS or user supplied memory management is required. +- Non-static containers declared locally within functions will store their contents on the stack. +- Copying or swapping a container is not a low cost action, as all of the contents will be copied. + +## Notes +Although the containers utilise inheritance, like the STL containers, they are not intended to be used +polymorphically, unless enabled by a compile time macros `ETL_POLYMORPHIC_XXX`. diff --git a/docs/containers/arrays/_index.md b/docs/containers/arrays/_index.md new file mode 100644 index 00000000..f82dabdd --- /dev/null +++ b/docs/containers/arrays/_index.md @@ -0,0 +1,6 @@ +--- +title: "Arrays" +weight: 100 +--- + +Array like containers. \ No newline at end of file diff --git a/docs/containers/arrays/array.md b/docs/containers/arrays/array.md new file mode 100644 index 00000000..e2cda55d --- /dev/null +++ b/docs/containers/arrays/array.md @@ -0,0 +1,316 @@ +--- +title: "array" +weight: 1 +--- + +{{< callout >}} + Header: `array.h` + Since: All versions + Similar to: [std::array](https://en.cppreference.com/w/cpp/container/array.html) +{{< /callout >}} + +A fixed capacity array. +Adds additional members functions, `assign`, `insert` & `erase`. + +```cpp +etl::array +``` + +See also: +[array_view]({{< relref "array-view" >}}) +[multi_array]({{< relref "multi-array" >}}) + +## Template deduction guides +**C++17 and above** + +```cpp +template +etl::array(T...) +``` + +### Example +```cpp +etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; +``` +Defines data as an array of 'int', of length '10', containing the supplied data. + +## Make template +**C++11 and above** + +```cpp +template +constexpr auto make_array(TValues&&... values) +``` + +### Example +```cpp +auto data = etl::make_array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); +``` + +## Member types + +`value_type` +`size_type` +`difference_type` +`reference` +`const_reference` +`pointer` +`const_pointer` +`iterator` +`const_iterator` +`reverse_iterator` +`const_reverse_iterator` + +`etl::array` iterators are random access. + +## Static Constants + +```cpp +SIZE +``` +**Description** +The size of the array. + +## Constructor + +```cpp +etl::array data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; +``` +**Description** +Default or copy constructs each element. +Can be initialised like a C array. + +## Element access +```cpp +T& at(size_t i) +const T& at(size_t i) const +``` +**Description** +Returns a reference or const reference to the indexed element. Emits an etl::array_out_of_range if the index is not in range. +If asserts or exceptions are not enabled then an out of range index results in undefined behaviour. + +--- + +```cpp +T& operator[](size_t i) +const T& operator[](size_t i) const +``` +**Description** +Returns a reference or const reference to the indexed element. +An out of range index results in undefined behaviour. + +--- + +```cpp +T& front() +const T& front() const +``` +**Description** +Returns a reference or const reference to the first element. + +--- + +```cpp +T& back() +const T& back() const +``` +**Description** +Returns a reference or const reference to the last element. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the array. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the array. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the array. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the array. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns true if the size of the array is zero, otherwise false. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the array. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the array. + +## Modifiers + +```cpp +void fill(T value) +``` +**Description** +Fills the array with value. + +## ETL Extensions + +```cpp +template +void assign(TIterator first, const TIterator last) +``` + +```cpp +template +void assign(TIterator first, const TIterator last, parameter_t value) +``` + +**Description** +Assigns a range of values to the array. The second form set uninitialised elements to value. +If the range is larger than the array then the extra data is ignored. +If the range is smaller than the array then the unused array elements are left unmodified. + +--- + +```cpp +iterator insert_at(size_t position, parameter_t value) +iterator insert(const_iterator position, parameter_t value) +``` + +**Description** +Inserts a value into the array at the specified position, shifting elements to make room. +Elements may be truncated if they are shifted off the end of the array. + +--- + +```cpp +template +iterator insert_at(size_t position, TIterator first, const TIterator last) +``` + +**Description** +`position` is not checked for validity. + +--- + +```cpp +template +iterator insert(const_iterator position, TIterator first, const TIterator last) +``` + +**Description** +Inserts a range of values into the array at the specified position, shifting elements to make room. +Elements may be truncated if they are shifted off the end of the array. +The range may be larger than the capacity of the array. Excess elements will be ignored. + +--- + +```cpp +iterator erase_at(size_t position) +iterator erase_at(size_t position, parameter_t value) +iterator erase(const_iterator position) +iterator erase(const_iterator position, parameter_t value) +``` + +**Description** +Erases an element at the specified position, shifting elements into the space. +The value parameter variants initialise the unused elements with value, while the others leave them unchanged. +position is not checked for valid range. + +--- + +```cpp +iterator erase_range(size_t first, size_t last) +iterator erase_range(size_t first, size_t last, parameter_t value) +iterator erase(const_iterator first, const_iterator last) +iterator erase(const_iterator first, const_iterator last, parameter_t value) +``` + +**Description** +Erases a range, shifting elements into the space. +The value parameter variants initialise the unused elements with value, while the others leave them unchanged. +first/last are not checked for valid range. + +## Non-member functions +**Lexicographically comparisons** +```cpp +operator == +``` +**Description** +`true` if the contents of the lists are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the lists are not equal, otherwise `false`. + +--- + +```cpp +operator < +``` +**Description** +`true` if the contents of the lhs are lexicographically less than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator <= +``` +**Description** +`true` if the contents of the lhs are lexicographically less than or equal to the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator > +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator >= +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than or equal to the contents of the rhs, otherwise `false`. diff --git a/docs/containers/arrays/multi-array.md b/docs/containers/arrays/multi-array.md new file mode 100644 index 00000000..e7a4462b --- /dev/null +++ b/docs/containers/arrays/multi-array.md @@ -0,0 +1,39 @@ +--- +title: "multi_array" +weight: 2 +--- + +{{< callout >}} + Header: `multi_array.h` +{{< /callout >}} + +A fixed capacity multi-dimensional array. + +For C++11 or greater only. + +```cpp +etl::multi_array +``` + +See also: +[array]({{< relref "array" >}}) +[array_view]({{< relref "array-view" >}}) + +## Description + +The `etl::multi_array` class is defined as a recursive variadic template. +It defines a multi-dimensional array class based on nested etl::array definitions. + +## Example + +```cpp +etl::multi_array +``` + +is equivalent to + +```cpp +etl::array, 3>, 2> +``` + +Each dimension of an `etl::multi_array` supports all of the members of an `etl::array`. diff --git a/docs/containers/binary/_index.md b/docs/containers/binary/_index.md new file mode 100644 index 00000000..43f202a7 --- /dev/null +++ b/docs/containers/binary/_index.md @@ -0,0 +1,6 @@ +--- +title: "Binary" +weight: 100 +--- + +Binary like containers. \ No newline at end of file diff --git a/docs/containers/binary/bitset.md b/docs/containers/binary/bitset.md new file mode 100644 index 00000000..7a9c6329 --- /dev/null +++ b/docs/containers/binary/bitset.md @@ -0,0 +1,420 @@ +--- +title: "bitset" +--- + +{{< callout >}} + Header: `bitset.h` + Since: 20.33.0 + Similar to: [std::bitset](https://en.cppreference.com/w/cpp/utility/bitset.html) +{{< /callout >}} + +This is the new default bitset implementation, from 20.33.0 onwards. +For the older version, see [etl::bitset (legacy)](). + +A fixed capacity bitset. +Has a number of extensions over `std::bitset`. Can be considered similar to an array of `bool`. + +Internally defined buffers +```cpp +etl::bitset +etl::bitset +``` + +Externally defined buffers from `20.34.0` +```cpp +etl::bitset_ext +etl::bitset_ext +``` + +The template parameters will determine whether the bitset uses a common implementation or one of four fixed sized +implementations. + +Note: `etl::ibitset` is no longer a reference type for any size `etl::bitset`. + +--- + +`etl::bitset` and `etl::bitset_ext` on their own will use `unsigned char` as the underlying element type and the operations will be implemented by the generic protected member functions in `etl::ibitset`. + +--- + +```cpp +etl::bitset +``` +```cpp +etl::bitset_ext +``` +Specifying a type for `TElement` will override the default element type and define it as the *unsigned* type of `TElement`. + +**Specialisations for maximum efficiency** + +There are specialisations for when the required number of bits matches the number of bits in the element type. +These specialisations are considerably faster and more efficient. + +```cpp +etl::bitset<8, uint8_t> +etl::bitset<16, uint16_t> +etl::bitset<32, uint32_t> +etl::bitset<8, uint64_t> +``` + +`any()`, `none()` and `all()` are overloaded in these specialisations to allow a mask to be specified, so that a bitset that requires less bits than the element type may still use the most efficient implementation. + +```cpp +etl::bitset<8, uint8_t> bst; // But only want to use 6 bits. +bool any = bst.any(0x3F); // Check the lower 6 bits. +``` + +## Types + +| Type | | +| - | - | +|`span_type` | A mutable span type. | +|`const_span_type`| A non-mutable span type. | +|`element_type` | The type used as the internal storage for a bitset. By default, this is unsigned char. | +|`buffer_type` | The type used as the to define the external buffer. Defined in etl::bitset_ext only. 20.34.0 | + +## Constants + +All `npos` values are equivalent. +```cpp +etl::bitset_constants::npos +``` +```cpp +etl::bitset<>::npos +``` +```cpp +template +etl::bitset::npos +``` +`Number_Of_Elements` +`Bits_Per_Element` +`Allocated_Bits` +`All_Set_Element` +`All_Clear_Element` + +From: 20.38.11 +`Storage_Model` `etl::bitset_storage_model::Single` or `etl::bitset_storage_model::Multi` + +## Constructors + +The initial state of the bitset is all clear (`false`). + +```cpp +etl::bitset(); +etl::bitset(unsigned long value); +etl::bitset(const char* str); +etl::bitset(const wchar_t* str); +etl::bitset(const char16_t* str); +etl::bitset(const char32_t* str); +``` +**Description** +The bitset is either default constructed, initialised with a numeric value, or a text string of zeros and ones. + +--- + +```cpp +etl::bitset_ext(element_type* pbuffer); +etl::bitset_ext(unsigned long value, element_type* pbuffer); +etl::bitset_ext(const char* str, element_type* pbuffer); +etl::bitset_ext(const wchar_t* str, element_type* pbuffer); +etl::bitset_ext(const char16_t* str, element_type* pbuffer); +etl::bitset_ext(const char32_t* str, element_type* pbuffer); +``` +**Description** +The bitset is either default constructed, initialised with a numeric value, or a text string of zeros and ones. +A pointer to the external must b supplied that is large enough to hold the bitset. +The buffer may be defined as follows:- +```cpp +using Bitset = etl::bitset_ext<32>; + +Bitset::element_type buffer[Bitset::Number_Of_Elements]; +``` +From: 20.34.0 + +--- + +```cpp +etl::bitset_ext(buffer_type& buffer); +etl::bitset_ext(unsigned long value, buffer_type& buffer); +etl::bitset_ext(const char* str, buffer_type& buffer); +etl::bitset_ext(const wchar_t* str, buffer_type& buffer); +etl::bitset_ext(const char16_t* str, buffer_type& buffer); +etl::bitset_ext(const char32_t* str, buffer_type& buffer); +``` +**Description** +The bitset is either default constructed, initialised with a numeric value, or a text string of zeros and ones. +A n external must b supplied that is large enough to hold the bitset. +The buffer may be defined as follows:- +```cpp +using Bitset = etl::bitset_ext<32>; + +Bitset::buffer_type buffer; +``` +From: 20.34.0 + +## Modifiers + +```cpp +etl::bitset& set(); +``` +**Description** +Set all bits. + +--- + +```cpp +etl::bitset& set(element_type value); +``` +**Description** +20.34.0 +Set the bits to value. +Valid when the bitset width matches the element type width. + +--- + +```cpp +etl::bitset& set(const char* str); +etl::bitset& set(const wchar_t* str); +etl::bitset& set(const char16_t* str); +etl::bitset& set(const char32_t* str); +``` +**Description** +Set with a text string of `0` and `1` characters. + +--- + +```cpp +etl::bitset& set(size_t position, bool value = true); +``` +**Description** +Set a position to a one or zero, default one. + +--- + +```cpp +etl::bitset& reset(); +``` +**Description** +Reset all bits. + +--- + +```cpp +etl::bitset& reset(size_t position); +``` +**Description** +Set a position to a zero. + +--- + +```cpp +etl::bitset& from_string(const char*); +etl::bitset& from_string(const wchar_t*); +etl::bitset& from_string(const char16_t*); +etl::bitset& from_string(const char32_t*); +``` +**Description** +Alias of set. +The bitset is built from a string of `0` and `1` characters. + +## Access + +```cpp +template +T value() const +``` +**Description** +Returns the value corresponding to the bitset. +`T` specifies the integral type to convert to. + +--- + +```cpp +unsigned long to_ulong() const +unsigned long long to_ullong() const +``` +**Description** +Functions for compatibility with the STL. +Calls value() or value(). + +If the type is too small to contain the bitset size, a compile time error will result. + +--- + +```cpp +template +TString to_string(typename TString::value_type zero = typename TString::value_type('0'), + typename TString::value_type one = typename TString::value_type('1')) const +``` +Returns the value as a string of `0` and `1` characters. +If the string type is not large enough to contain the digits then an `etl::bitset_string_too_small` is emitted. + +--- + +```cpp +span_type span() +const_span_type span() const +``` +**Description** +Returns an `etl::span` of the underlying binary data. +The span is ordered LSB to MSB. + +--- + +```cpp +template +ETL_CONSTEXPR14 +T extract(size_t position, size_t length = etl::integral_limits::bits) const +``` +**Description** +Extract an integral value from an arbitrary position and length. +Run time position and length. + +--- + +```cpp +template ::bits> +ETL_CONSTEXPR14 +T extract() const +``` +**Description** +Extract an integral value from an arbitrary position and length. +Compile time position and length. +From: 20.38.11 +For C++11 and above + +--- + +```cpp +template +T extract() const +``` +**Description** +Extract an integral value from an arbitrary position and length. +Compile time position and length. +20.38.11 +For C++98/03 + +## Bit access + +```cpp +bool operator[](size_t position) const +``` +**Description** +Returns the boolean state of the indexed bit. +position is not checked for validity. + +--- + +```cpp +size_t count() const +``` +**Description** +Returns the number of set bits. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the number of bits supported by this bitset. + +--- + +```cpp +bool test(size_t position) const +``` +**Description** +Returns the boolean state of the indexed bit. +position is not checked for validity. + +--- + +```cpp +bool any() const +``` +**Description** +Returns true if any of the bits are set, otherwise false. + +```cpp +bool any(element_type mask) const +``` +**Description** +Only enabled for bitsets that fit within one element. +Returns true if any of the bits are set, after the mask has been applied, otherwise false. +Valid when the bitset width matches the element type width. +20.34.0 + +--- + +```cpp +bool none() const +``` +**Description** +Returns true if none of the bits are set, otherwise false. + +```cpp +bool none(element_type mask) const +``` +**Description** +Only enabled for bitsets that fit within one element. +Returns true if none of the bits are set, after the mask has been applied, otherwise false. +Valid when the bitset width matches the element type width. +20.34.0 + +--- + +```cpp +bool all() const +``` +**Description** +Returns true if al of the bits are set, otherwise false. + +```cpp +bool all(element_type mask) const +``` +**Description** +Only enabled for bitsets that fit within one element. +Returns true if al of the bits are set, after the mask has been applied, otherwise false. +Valid when the bitset width matches the element type width. +20.34.0 + +--- + +```cpp +size_t find_first(bool state) const +``` +**Description** +Returns the position of the first bit in the specified state. If not found then returns bitset<>::npos. + +--- + +```cpp +size_t find_next(bool state, size_t position) const +``` +**Description** +Returns the position of the next bit in the specified state, starting from position. If not found then returns bitset<>::npos. +position is not checked for validity. + +## Bit operations + +```cpp +bitset& operator &= (const bitset& rhs); +bitset& operator |= (const bitset& rhs); +bitset& operator ^= (const bitset& rhs); +bitset& operator <<= (size_t shift); +bitset& operator >>= (size_t shift); +bool operator == (const bitset& rhs); +bool operator != (const bitset& rhs); +``` + +## Non-member functions + +```cpp +void swap(etl::bitset& lhs, etl::bitset& rhs) +``` +**Description** +Swaps the contents of the two bitsets. +The bitsets must be the same size. + diff --git a/docs/containers/binary/bloom-filter.md b/docs/containers/binary/bloom-filter.md new file mode 100644 index 00000000..828b0313 --- /dev/null +++ b/docs/containers/binary/bloom-filter.md @@ -0,0 +1,106 @@ +--- +title: "bloom_filter" +--- + +{{< callout >}} + Header: `bloom_filter.h` + Since: All versions +{{< /callout >}} + +```cpp +etl::bloom_filter +``` + +A Bloom filter that supports up to three hash functions. `Thash2` & `Thash3` are optional. + +The width specified is the desired width in bits. +The class may use more if the underlying bitset naturally has spare capacity. +i.e. A bloom filter with a specified capacity of 195 bits will be rounded up to 200 bits as the bitset has a block size of 8. + +## Constructor + +The initial state of the Bloom filter is clear. + +```cpp +bloom_filter(); +``` + +## Operations + +```cpp +void clear() +``` +**Description** +Clears the filter of all entries. + +--- + +```cpp +void add(parameter_t key) +``` +**Description** +Adds a key to the filter, where parameter_t is derived from the first hash argument type. + +--- + +```cpp +bool exists(parameter_t key) const +``` +**Description** +Checks to see if a key may exist in the filter, where parameter_t is derived from the first hash argument type. + +--- + +```cpp +size_t usage() const +``` +**Description** +Returns the usage of the filter in percent. +Equal to `100 * count() / width()` + +--- + +```cpp +bool count() const +``` +**Description** +Returns the number of elements in use in the filter. + +--- + +```cpp +bool width() const +``` +**Description** +Returns the width of the filter. +Equal to the template parameter WIDTH. + +## Example + +```cpp +#include "bloom_filter.h" +#include "fnv-1.h" +#include "string.h" + +struct hash_t +{ + typedef const char* argument_type; + + size_t operator ()(argument_type text) const + { + return etl::fnv_1a_32(text, text + strlen(text)); + } +}; + +etl::bloom_filter<64, hash_t> bloom; + +bloom.add("Hello"); +bloom.add("World"); +bloom.add("the"); + +bool test; + +test = bloom.exists("Hello"); // Returns true +test = bloom.exists("You"); // Returns false +test = bloom.exists("you"); // Returns true (false positive) +``` diff --git a/docs/containers/lists/_index.md b/docs/containers/lists/_index.md new file mode 100644 index 00000000..deeebe4f --- /dev/null +++ b/docs/containers/lists/_index.md @@ -0,0 +1,6 @@ +--- +title: "Lists" +weight: 100 +--- + +List like containers. \ No newline at end of file diff --git a/docs/containers/lists/forward-list.md b/docs/containers/lists/forward-list.md new file mode 100644 index 00000000..b0b358bd --- /dev/null +++ b/docs/containers/lists/forward-list.md @@ -0,0 +1,533 @@ +--- +title: "forward_list" +weight: 3 +--- + +{{< callout >}} + Header: `forward_list.h` + Similar to: `std::forward_list` +{{< /callout >}} + +A fixed capacity forward list. + +```cpp +etl::forward_list +etl::forward_list_ext +``` + +Inherits from `etl::iforward_list`. +`etl::iforward_list` may be used as a size independent pointer or reference type for any `etl::forward_list` instance. + +**Note:** Does not support the member function swap. + +## Shared Pools + +`etl::forward_list_ext` +This template may share pools with another `etl::forward_list` of the same type. +The list is initialised with the pool either at construction time or a call to `set_pool(etl::ipool& pool)`. +When pools are shared there are a few side effects that must be noted. + +`size()` and `empty()` will be O(N) complexity. For a normal `etl::forward_list` they are O(1). + +Destruction of the container will always be O(N) regardless of whether the type store is trivially destructible or not. + +`max_size()` will return the potential maximum size of the list. The actual maximum size will dependent of how many elements the other lists sharing the pool have allocated. + +Pool must be declared with the list's `pool_type`. + +### Example +```cpp +// The element type +struct Point { int x; int y; }; + +// The list type +using List = etl::forward_list_ext; + +// The shared pool +etl::pool pool; +``` + +## Template deduction guides +**C++17 and above** + +```cpp +template +etl::forward_list(T...) +``` + +### Example +```cpp +etl::forward_list data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; +``` + +Defines data as an `forward_list` of int, of length 10, containing the supplied data. + +## Make template +**C++11 and above** +```cpp +template + constexpr auto make_forward_list(TValues&&... values) +``` + +### Example +```cpp +auto data = etl::make_forward_list(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); +``` + +## Member types + +```cpp +value_type T +size_type std::size_t +difference_type std::ptrdiff_t +reference value_type& +const_reference const value_type& +pointer value_type* +const_pointer const value_type* +iterator Bi-directional iterator +const_iterator Constant bi-directional iterator +``` + +## Constructors + +```cpp +etl::forward_list() +``` + +--- + +```cpp +etl::forward_list(size_t initialSize, parameter_t value = T()) +``` + +--- + +```cpp +template +etl::forward_list(TIterator begin, TIterator end) +``` + +Raises an `etl::forward_list_iterator` if the iterators are invalid. Raises an `etl::forward_list_full` if the list becomes full. +If asserts or exceptions are disabled then undefined behaviour occurs. + +## For shared pool lists +```cpp +etl::forward_list(etl::pool& pool) +``` + +--- + +```cpp +etl::forward_list(size_t initialSize, parameter_t value, etl::pool& pool) +``` + +--- + +```cpp +template +etl::forward_list(TIterator begin, TIterator end, etl::pool& pool) +``` + +Raises an `etl::forward_list_iterator` if the iterators are invalid. If asserts or exceptions are disabled then undefined behaviour occurs. + +## Copy constructor +**Implicit pool** +Uses the pool from other. +```cpp +etl::forward_list(etl::forward_list& other) +``` + +**Explicit pool** +```cpp +etl::forward_list(etl::forward_list& other, etl::pool& pool) +``` + +## Element access + +```cpp +T& front() +const T& front() const +``` +**Description** +Returns a reference or const reference to the first element. +Undefined behaviour if the list is empty. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the forward list. +Returns end() if the list is empty. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the forward list. + +--- + +```cpp +iterator before_begin() +const_iterator before_begin() const +const_iterator cbefore_begin() const +``` +**Description** +Returns an iterator to before the beginning of the forward list. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns `true` if the size of the forward list is zero, otherwise `false`. + +--- + +```cpp +bool full() const +``` +**Description** +Returns `true` if the size of the forward list is SIZE, otherwise `false`. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the forward list. + +--- + +```cpp +size_t available() const +``` +**Description** +Returns the remaining available capacity in the forward list. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the forward list . + +## Modifiers + +```cpp +template +void assign(TIterator begin, TIterator end) + +void assign(size_t n, parameter_t value) +``` +**Description** +Fills the forward list with the values. +Raises an `etl::forward_list_iterator` if the iterators are invalid. +Raises an `etl::forward_list_full` if the list becomes full. +If asserts or exceptions are disabled then undefined behaviour occurs. + +--- + +```cpp +void push_front(parameter_t value) +``` +**Description** +Pushes a value to the front of the forward list. If the forward list is full and ETL_CHECK_PUSH_POP is defined then raises an etl::forward_list_full error, otherwise undefined behaviour occurs. + +--- + +```cpp +emplace_front +``` +**Description** +Constructs an item at the front of the the list 'in place'. +If the forward list is full and `ETL_CHECK_PUSH_POP` is defined then raises an `etl::forward_list_full` error, otherwise undefined behaviour occurs. + +### C++03 +```cpp +template +void emplace_front(const T1& value1) + +template +void emplace_front(const T1& value1, const T2& value2) + +template +void emplace_front(const T1& value1, const T2& value2, + const T3& value3) + +template +void emplace_front(const T1& value1, const T2& value2, + const T3& value3, const T4& value4) +``` +Before: `20.35.0` + +## C++11 and above + +```cpp +template +void emplace_front(Args&& ... args) +``` +**Description** +Constructs an item at the front of the the list 'in place'. +If the forward list is full and `ETL_CHECK_PUSH_POP` is defined then raises an `etl::forward_list_full` error, otherwise undefined behaviour occurs. + +### C++03 +```cpp +template +reference emplace_front(const T1& value1) + +template +reference emplace_front(const T1& value1, const T2& value2) + +template +reference emplace_front(const T1& value1, const T2& value2, + const T3& value3) + +template +reference emplace_front(const T1& value1, const T2& value2, + const T3& value3, const T4& value4) +``` +From 20.35.10 +--- + +### C++11 and above +```cpp +template +reference emplace_front(Args&& …args) +``` + +--- + +```cpp +void pop_front() +``` +**Description** +Pop a value from the front of the forward list. +If the forward list is empty and `ETL_CHECK_PUSH_POP` is defined then raises an `etl::forward_list_empty` error, otherwise undefined behaviour occurs. + +--- + +```cpp +template +void insert_after(iterator position, TIterator begin, TIterator end) +``` +**Description** +Inserts the range [`begin`, `end`) into the forward list after the specified position. +Before: `20.20.0` + +--- + +```cpp +iterator insert_after(iterator position, parameter_t value) +void insert_after(iterator position, size_t n, parameter_t value) +``` +**Description** +Inserts `value` in to the forward list after the specified position. + +--- + +```cpp +template +iterator insert_after(const_iterator position, TIterator begin, TIterator end) +``` +**Description** +Inserts the range [`begin`, `end`) into the forward list after the specified position. +Since: `20.20.0` + +--- + +```cpp +iterator insert_after(const_iterator position, parameter_t value) +``` +**Description** +Inserts `value` in to the forward list after the specified position. + +--- + +```cpp +iterator insert_after(const_iterator position, size_t n, parameter_t value) +``` +Inserts values in to the forward list after the specified position. +If the forward list is full then raises an `etl::forward_list_full error`. +If asserts or exceptions are disabled then undefined behaviour occurs. + +--- + +```cpp +iterator erase_after(iterator position) +``` +Erases elements after the specified position. +Before: `20.20.0` + +--- + +```cpp +iterator erase_after(iterator position, const_iterator end) +``` +**Description** +Erases the range (`position`, `end`) +Before: `20.20.0` + +--- + +```cpp +iterator erase_after(const_iterator position) +``` +**Description** +Erases elements after the specified position. +Since: `20.20.0` + +--- + +```cpp +iterator erase_after(const_iterator position, const_iterator end) +``` +**Description** +Erases the range (`position`, `end`) +Since: `20.20.0` + +--- + +```cpp +void resize(size_t n) +``` +**Description** +Resizes the forward list. +If the new size is larger then the first assigns default constructed values. +If n is larger than the capacity then raises an `etl::forward_list_full error`, if asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +void resize(size_t n, parameter_t value) +``` +**Description** +Resizes the forward list. +If the new size is larger then the first assigns the supplied value. +If n is larger than the capacity then raises an `etl::forward_list_full error`, if asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +void clear() +``` +**Description** +Clears the forward list to a size of zero. + +## Operations + +```cpp +void remove(const T& value) +``` +**Description** +Removes from the container all the elements that compare equal to value. + +--- + +```cpp +template +void remove_if(TPredicate predicate) +``` +**Description** +Removes from the container all the elements that satisfy predicate. + +--- + +```cpp +void unique() +``` +**Description** +Removes all but the first element from every group of consecutive elements. + +--- + +```cpp +template +void unique(TPredicate predicate) +``` +**Description** +Removes all but the first element from every group of consecutive elements that satisfy the binary predicate. + +--- + +```cpp +void sort() +``` +**Description** +Sorts using the `<` operator. + +--- + +```cpp +template +void sort(TCompare compare) +``` +**Description** +Sorts using the supplied `compare` function. + +--- + +```cpp +void reverse() +``` +**Description** +Reverses the order of the container. + +## Non-member functions + +```cpp +operator == +``` +**Return** +`true` if the contents of the lists are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Return** +`true` if the contents of the lists are not equal, otherwise `false`. + +--- + +```cpp +operator < +``` +**Return** +`true` if the contents of the lhs are lexicographically less than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator <= +``` +**Return** +`true` if the contents of the lhs are lexicographically less than or equal to the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator > +``` +**Return** +`true` if the contents of the lhs are lexicographically greater than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator >= +``` +**Return** +`true` if the contents of the lhs are lexicographically greater than or equal to the contents of the rhs, otherwise `false`. diff --git a/docs/containers/lists/intrusive-forward-list.md b/docs/containers/lists/intrusive-forward-list.md new file mode 100644 index 00000000..81566090 --- /dev/null +++ b/docs/containers/lists/intrusive-forward-list.md @@ -0,0 +1,341 @@ +--- +title: "intrusive_forward_list" +weight: 4 +--- + +{{< callout type="info">}} + Header: `intrusive_forward_list.h` + Similar to: `std::forward_list` +{{< /callout >}} + +An intrusive forward list.https://www.messenger.com/t/837634551/ + +```cpp +template +etl::intrusive_forward_list +``` + +`TValue` is the type that contains the actual values. It is derived from `Tlink`. `Tlink` is the link type for this list. +See Intrusive links. + +Before `20.37.0` the default link type was `etl::forward_link<0>`. + +## Member types + +```cpp +link_type TLink +value_type TValue +pointer value_type* +const_pointer const value_type* +reference value_type& +const_reference const value_type& +size_type size_t +``` + +## Constructors + +```pcc +etl::intrusive_forward_list(); +``` +**Description** +Default constructor. + +--- + +```cpp +template +etl::intrusive_forward_list(TIterator begin, TIterator end); +``` +**Description** +Creates the list from the range [`begin`, `end`) of node links. + +--- + +```cpp +template +intrusive_forward_list(TLink& first, TLinks&... links); +```cpp +**Description** +Creates the list from node link references. + +## Element access + +```cpp +TValue& front() +const T& front() const +``` +**Description** +Returns a reference or const reference to the first element. + +--- + +```cpp +TValue& back() +const T& back() const +``` +**Description** +Returns a reference or const reference to the last element. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the list. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the list. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the list. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the list. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns true if the size of the list is zero, otherwise false. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the list. + +## Modifiers + +```cpp +template +void assign(TIterator begin, TIterator end); +``` +**Description** +Fills the list with the values. + +--- + +```cpp +void push_front(value_type& value); +``` +**Description** +Pushes a value to the front of the list. + +--- + +```cpp +void pop_front(); +``` +**Description** +Pop a value from the front of the list. +Emits an `etl::intrusive_forward_list_empty` if the list is empty. +If asserts or exceptions are disabled then undefined behaviour occurs. + +--- + +```cpp +template +void insert_after(iterator position, TIterator begin, TIterator end); +``` +**Description** + +--- + +```cpp +iterator insert_after(iterator position, value_type& value); +``` +**Description** +Inserts values in to the list. +position is not checked for validity. + +--- + +```cpp +template +iterator erase_after(TIterator begin, TIterator end); +``` +**Description** +Erases values in the range [`begin`, `end`). +Iterators are not checked for validity. + +--- + +```cpp +iterator erase_after(iterator position); +``` +**Description** +Erases values in the list. +Iterators are not checked for validity. + +--- + +```cpp +void clear() +``` +**Description** +Clears the list to a size of zero. No elements are destructed. + +--- + +```cpp +void splice_after(iterator position, list_type& list); +void splice_after(iterator position, list_type& list, iterator isource); +void splice_after(iterator position, list_type& list, iterator begin_, iterator end_); +``` +**Description** +Splices elements from a list into this list. +Iterators are not checked for validity. + +--- + +```cpp +void merge(list_type& list); +``` +**Description** +Merges the sorted elements of 'list' into this list. Merges are stable. +If a debug compile and asserts or exceptions are enabled than an etl::intrusive_list_unsorted is emitted if either list is unsorted, otherwise undefined behaviour occurs. + +--- + +```cpp +template +void merge(list_type& list, Tcompare compare) +``` +**Description** +Merges the sorted elements of list into this list. Comparison functor is supplied in compare. Merges are stable. +If a debug compile and asserts or exceptions are enabled than an etl::intrusive_list_unsorted is emitted if either list is unsorted, otherwise undefined behaviour occurs. + +## Operations + +```cpp +void remove(const T& value); +``` +**Description** +Removes from the container all the elements that compare equal to value. + +--- + +```cpp +template +void remove_if(TPredicate predicate); +``` +**Description** +Removes from the container all the elements that satisfy predicate. + +--- + +```cpp +void unique(); +``` +**Description** +Removes all but the first element from every group of consecutive elements. + +--- + +```cpp +template +void unique(TPredicate predicate); +``` +**Description** +Removes all but the first element from every group of consecutive elements that satisfy the binary `predicate`. + +--- + +```cpp +void sort(); +``` +**Description** +Sorts using the < operator. + +--- + +```cpp +template +void sort(TCompare compare); +``` +**Description** +Sorts using the supplied `compare` function. + +--- + +```cpp +void reverse(); +``` +**Description** +Reverses the order of the list. + +## Non-member functions + +```cpp +operator == +``` +**Description** +`true` if the contents of the lists are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the lists are not equal, otherwise `false`. + +--- + +```cpp +operator < +``` +**Description** +`true` if the contents of the lhs are lexicographically less than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator <= +``` +**Description** +`true` if the contents of the lhs are lexicographically less than or equal to the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator > +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator >= +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than or equal to the contents of the rhs, otherwise `false`. diff --git a/docs/containers/lists/intrusive-list.md b/docs/containers/lists/intrusive-list.md new file mode 100644 index 00000000..f0d4cf71 --- /dev/null +++ b/docs/containers/lists/intrusive-list.md @@ -0,0 +1,357 @@ +--- +title: "intrusive_list" +weight: 2 +--- + +{{< callout type="info">}} + Header: `intrusive_list.h` + Similar to: `std::list` +{{< /callout >}} + +An intrusive list. + +```cpp +template +etl::intrusive_list +``` + +`TValue` is the type that contains the actual values. It is derived from `Tlink`. `Tlink` is the link type for this list. +See Intrusive links. + +Before `20.37.0` the default link type was `etl::bidirectional_link<0>`. + +## Member types + +```cpp +link_type TLink +value_type TValue +pointer value_type* +const_pointer const value_type* +reference value_type& +const_reference const value_type& +size_type size_t +``` + +## Constructors + +```cpp +etl::intrusive_list() +``` +Default constructor. + +--- + +```cpp +template +etl::intrusive_list(TIterator begin, TIterator end) +``` +**Description** +Creates the list from the range [`begin`, `end`) of node links. + +--- + +```cpp +template +intrusive_list(TLink& first, TLinks&... links)) +``` +**Description** +Creates the list from node link references. + +## Element access + +```cpp +TValue& front() +const T& front() const +``` +**Description** +Returns a reference or const reference to the first element. + +--- + +```cpp +TValue& back() +const T& back() const +``` +**Description** +Returns a reference or const reference to the last element. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the list. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the list. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the list. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the list. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns `true` if the size of the list is zero, otherwise `false`. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the list. + +## Modifiers + +```cpp +template +void assign(TIterator begin, TIterator end)) +``` +**Description** +Fills the list with the values. + +--- + +```cpp +void push_front(value_type& value)) +``` +**Description** +Pushes a value to the front of the list. + +--- + +```cpp +void push_back(value_type& value)) +``` +**Description** +Pushes a value to the back of the list. + +--- + +```cpp +void pop_front()) +``` +**Description** +Pop a value from the front of the list. +Emits an `etl::intrusive_list_empty` if the list is empty. +If asserts or exceptions are disabled then undefined behaviour occurs. + +--- + +```cpp +void pop_back()) +``` +**Description** +Pop a value from the back of the list. +Emits an `etl::intrusive_list_empty` if the list is empty. +If asserts or exceptions are disabled then undefined behaviour occurs. + +--- + +```cpp +template +void insert(iterator position, TIterator begin, TIterator end)) +``` +**Description** + +--- + +```cpp +iterator insert(iterator position, value_type& value)) +``` +**Description** +Inserts values in to the list. +position is not checked for validity. + +--- + +```cpp +template +iterator erase(TIterator begin, TIterator end)) +``` +**Description** +Erases the range [`begin`, `end`). + +--- + +```cpp +iterator erase(iterator position)) +``` +**Description** +Erases values in the list. +Iterators are not checked for validity. + +--- + +```cpp +void clear()) +``` +**Description** +Clears the list to a size of zero. No elements are destructed. + +--- + +```cpp +void splice(iterator position, list_type& list)) +void splice(iterator position, list_type& list, iterator isource)) +void splice(iterator position, list_type& list, iterator begin_, iterator end_)) +``` +**Description** +Splices elements from a list into this list. +Iterators are not checked for validity. + +--- + +```cpp +void merge(list_type& list)) +``` +**Description** +Merges the sorted elements of 'list' into this list. Merges are stable. +If a debug compile and asserts or exceptions are enabled than an etl::intrusive_list_unsorted is emitted if either list is unsorted, otherwise undefined behaviour occurs. + +--- + +```cpp +template +void merge(list_type& list, Tcompare compare)) +``` +**Description** +Merges the sorted elements of list into this list. Comparison functor is supplied in compare. Merges are stable. +If a debug compile and asserts or exceptions are enabled than an etl::intrusive_list_unsorted is emitted if either list is unsorted, otherwise undefined behaviour occurs. + +## Operations + +```cpp +void remove(const T& value)) +``` +**Description** +Removes from the container all the elements that compare equal to value. + +--- + +```cpp +template +void remove_if(TPredicate predicate)) +``` +**Description** +Removes from the container all the elements that satisfy predicate. + +--- + +```cpp +void unique()) +``` +**Description** +Removes all but the first element from every group of consecutive elements. + +--- + +```cpp +template +void unique(TPredicate predicate)) +``` +**Description** +Removes all but the first element from every group of consecutive elements that satisfy the binary predicate. + +--- + +```cpp +void sort()) +``` +**Description** +Sorts using the `<` operator. + +--- + +```cpp +template +void sort(TCompare compare)) +``` +**Description** +Uses the supplied `compare` function. + +--- + +```cpp +void reverse()) +``` +**Description** +Reverses the order of the list. + +## Non-member functions + +```cpp +operator == +``` +**Description** +`true` if the contents of the lists are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the lists are not equal, otherwise `false`. + +--- + +```cpp +operator < +``` +**Description** +`true` if the contents of the lhs are lexicographically less than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator <= +``` +**Description** +`true` if the contents of the lhs are lexicographically less than or equal to the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator > +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator >= +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than or equal to the contents of the rhs, otherwise `false`. diff --git a/docs/containers/lists/list.md b/docs/containers/lists/list.md new file mode 100644 index 00000000..8ae13fd3 --- /dev/null +++ b/docs/containers/lists/list.md @@ -0,0 +1,753 @@ +--- +title: "list" +weight: 1 +--- + +{{< callout >}} + Header: `list.h` + Similar to: `std::list` +{{< /callout >}} + +A fixed capacity bidirectional list. + +```cpp +etl::list +etl::list_ext +``` + +Inherits from `etl::ilist`. +`etl::ilist` may be used as a size independent pointer or reference type for any `etl::list` instance. + +{{< callout type="warning">}} + Does not support the member function `swap`. +{{< /callout >}} + +## Shared Pools + +```cpp +etl::list +``` +This template may share pools with another `etl::list` of the same type. +The list is initialised with the pool either at construction time or a call to `set_pool(etl::ipool& pool)`. +When pools are shared there are a few side effects that must be noted. + +`size()` and `empty()` will have O(N) complexity. +For a normal `etl::list` they are O(1). + +Destruction of the container will always be O(N) regardless of whether the type store is trivially destructible or not. + +`max_size()` will return the potential maximum size of the list. The actual maximum size will dependent of how many elements the other lists sharing the pool have allocated. + +The pool must be declared with the list's `pool_type`. + +### Example +```cpp +// The element type +struct Point { int x; int y; }; + +// The list type +using List = etl::list_ext; + +// The shared pool +etl::pool pool; +``` + +## Template deduction guides +**C++17 and above** + +```cpp +template +etl::list(T...) +``` + +### Example +```cpp +etl::list data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; +``` +Defines data as an list of `int`, of length `10`, containing the supplied data. + +## Make template +**C++11 and above** +```cpp +template +constexpr auto make_list(TValues&&... values) +``` + +### Example +```cpp +auto data = etl::make_list(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); +``` + +## Member types + +```cpp +value_type T +size_type std::size_t +difference_type std::ptrdiff_t +reference value_type& +const_reference const value_type& +rvalue_reference value_type&& +pointer value_type* +const_pointer const value_type* +iterator Bi-directional iterator +const_iterator Constant bi-directional iterator +reverse_iterator ETL_OR_STD::reverse_iterator +const_reverse_iterator ETL_OR_STD::reverse_iterator +``` + +## Constructors + +```cpp +etl::list() +``` + +--- + +```cpp +etl::list(size_t initialSize, parameter_t value = T()) +``` + +--- + +```cpp +etl::list(const etl::list&) +``` + +--- + +```cpp +etl::list(etl::list&&) +``` + +--- + +```cpp +template +etl::list(TIterator begin, TIterator end) +``` +**Description** +Emits an `etl::list_iterator` if the iterators are invalid. If asserts or exceptions are disabled then undefined behaviour occurs. + +## For shared pool lists + +```cpp +etl::list(etl::pool& pool) +``` + +```cpp +etl::list(size_t initialSize, parameter_t value, etl::pool& pool) +``` + +```cpp +template +etl::list(TIterator begin, TIterator end, etl::pool& pool) +``` +**Description** +Emits an `etl::list_iterator` if the iterators are invalid. If asserts or exceptions are disabled then undefined behaviour occurs. + +### Copy constructor +**Implicit pool** +Uses the pool from other. +```cpp +etl::list(etl::list& other) +``` + +**Explicit pool** +```cpp +etl::list(etl::list& other, etl::pool& pool) +``` + +### Initialisation + +if the list is sharing pools then a `set_pool(etl::pool&)` is available. +If a pool has already been set then the list is first cleared before updating to the new pool. + +The pool instance can be retrieved by call `get_pool()` + +## Element access + +```cpp +T& front() +const T& front() const +``` +**Description** +Returns a reference or const reference to the first element. +Undefined behaviour if the list is empty. + +--- + +```cpp +T& back() +const T& back() const +``` +**Description** +Returns a reference or const reference to the last element. +Undefined behaviour if the list is empty. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the list. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the list. + +--- + +```cpp +reverse_iterator rbegin() +const_reverse_iterator rbegin() const +const_reverse_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the list. + +--- + +```cpp +reverse_iterator rend() +const_reverse_iterator rend() const +const_reverse_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the list. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns true if the size of the list is zero, otherwise false. + +--- + +```cpp +bool full() const +``` +**Description** +Returns true if the size of the list is SIZE, otherwise false. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the list. + +--- + +```cpp +size_t available() const +``` +**Description** +Returns the remaining available capacity in the list. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the list. + +## Modifiers + +```cpp +template +void assign(TIterator begin, TIterator end) +``` +**Description** +Assigns from a range of values. + +--- + +```cpp +void assign(size_t n, parameter_t value) +``` +**Description** +Fills the list with the values. + +--- + +```cpp +void push_front(const T& value) +void push_front(T&& value) +``` +**Description** +Pushes a value to the front of the list. +If the list is full then emits an `etl::list_full error`. + +--- + +```cpp +emplace_front +``` + +### C++03 + +```cpp +template +void emplace_front(const T1& value1) + +template +void emplace_front(const T1& value1, const T2& value2) + +template +void emplace_front(const T1& value1, const T2& value2, + const T3& value3) + +template +void emplace_front(const T1& value1, const T2& value2, + const T3& value3, const T4& value4) +``` +**Description** +Emplaces a value at the front, constructed using the supplied arguments. +Before: `20.35.10` + +```cpp +template +reference emplace_front(const T1& value1) + +template +reference emplace_front(const T1& value1, const T2& value2) + +template +reference emplace_front(const T1& value1, const T2& value2, + const T3& value3) + +template +reference emplace_front(const T1& value1, const T2& value2, + const T3& value3, const T4& value4) +``` +**Description** +Emplaces a value at the front, constructed using the supplied arguments. +Since: `20.35.10` + +### C++11 and above +```cpp +template +reference emplace_front(Args&& …args) +``` +**Description** +Emplaces a value at the front, constructed using the supplied arguments. + +--- + +```cpp +void push_back(const T& value); +void push_back(T&& value); +``` +**Description** +Pushes a value to the back of the list. +If the list is full and `ETL_CHECK_PUSH_POP` is defined then emits an `etl::list_full` error, otherwise undefined behaviour occurs. + +--- + +```cpp +emplace_back +``` +**Description** +Emplaces a value at the back, constructed using the supplied arguments. + +**C++03** +```cpp +template +void emplace_back(const T1& value1) + +template +void emplace_back(const T1& value1, const T2& value2) + +template +void emplace_back(const T1& value1, const T2& value2, + const T3& value3) + +template +void emplace_back(const T1& value1, const T2& value2, + const T3& value3, const T4& value4) +``` +Before: `20.35.10` + +```cpp +template +reference emplace_back(const T1& value1) + +template +reference emplace_back(const T1& value1, const T2& value2) + +template +reference emplace_back(const T1& value1, const T2& value2, + const T3& value3) + +template +reference emplace_back(const T1& value1, const T2& value2, + const T3& value3, const T4& value4) +``` +Since: `20.35.10` + +### C++11 and above +```cpp +template +reference emplace_back(Args&& ... args) +``` +**Description** +Emplaces a value at the back, constructed using the supplied arguments. +From: `20.35.10` + +--- + +**C++11 and above** +```cpp +template +reference emplace_back(Args&& ... args) +``` +**Description** +Emplaces a value at the back, constructed using the supplied arguments. +From: `20.35.10` + +--- + +```cpp +void pop_front() +``` +**Description** +Pop a value from the front of the list. +If the list is empty and `ETL_CHECK_PUSH_POP` is defined then emits an `etl::list_empty` error, otherwise undefined behaviour occurs. + +--- + +```cpp +void pop_back() +``` +**Description** +Pop a value from the back of the list. +If the list is empty and `ETL_CHECK_PUSH_POP` is defined then emits an `etl::list_empty` error, otherwise undefined behaviour occurs. + +--- + +```cpp +template +void insert(iterator position, TIterator begin, TIterator end) +``` +**Description** +Before: `20.20.0` + +--- + +```cpp +iterator insert(iterator position, parameter_t value); +void insert(iterator position, size_t n, parameter_t value) +``` + +```cpp +template +iterator insert(const_iterator position, TIterator begin, TIterator end) +``` +**Description** +Since `20.20.0` + +--- + +```cpp +iterator insert(const_iterator position, parameter_t value) +iterator insert(const_iterator position, size_t n, parameter_t value) +``` +**Description** +Inserts values in to the list. If the list is full then emits an `etl::list_full` error. + +--- + +```cpp +emplace +``` +**Description** +Constructs an item at the insert point in the list 'in place'. + +### C++03 +```cpp +void emplace(iterator position, const T1& value1) + +void emplace(iterator position, const T1& value1, const T2& value2) + +void emplace(iterator position, const T1& value1, const T2& value2, const T3& value3) + +void emplace(iterator position, const T1& value1, const T2& value2, const T3& value3, const T4& value4) +``` +Before: `20.20.0` +```cpp +iterator emplace(const_iterator position, const T1& value1) + +iterator emplace(const_iterator position, const T1& value1, const T2& value2) + +iterator emplace(const_iterator position, const T1& value1, const T2& value2, const T3& value3) + +iterator emplace(const_iterator position, const T1& value1, const T2& value2, const T3& value3, const T4& value4) +``` +**Description** +From: `20.20.0` + +### C++11 +```cpp +void emplace(iterator position, Args&& ... args) +``` +**Description** +Constructs an item at the insert point in the the list 'in place'. +Before: `20.20.0` + +```cpp +void emplace(const_iterator position, Args&& ... args) +``` +**Description** +Constructs an item at the insert point in the the list 'in place'. +From: `20.20.0` + +--- + +```cpp +template +iterator erase(TIterator begin, TIterator end) +``` + +--- + +```cpp +iterator erase(iterator position) +``` +**Description** +Before: `20.20.0` + +--- + +```cpp +iterator erase(iterator position) +iterator erase(const_iterator position) +``` +**Description** +Erases values in the list. +Before: `20.21.0` + +--- + +```cpp +void resize(size_t n); +void resize(size_t n, parameter_t value) +``` +**Description** +Resizes the list. If the new size is larger then the first assigns default constructed values, the second assigns the supplied value. +If `n` is larger than the capacity then emits an `etl::list_full` error, if asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +void clear(); +``` +**Description** +Clears the list to a size of zero. + +--- + +```cpp +void splice(iterator to, etl::ilist& other) +void splice(iterator to, etl::ilist&& other) +``` +**Description** +Moves the elements in list other to before the position to. +The operation performs copies between the different lists. + +--- + +```cpp +void splice(iterator to, etl::ilist& other, iterator from) +void splice(iterator to, etl::ilist&& other, iterator from) +``` +**Description** +Moves the element at position from in list other to before the position to. +The operation is fast when spicing within the same list, otherwise performs copies between different lists. +If from is not valid then undefined behaviour occurs. + +--- + +```cpp +void splice(iterator to, etl::ilist& other, iterator first, iterator last) +void splice(iterator to, etl::ilist&& other, iterator first, iterator last) +``` +**Description** +Moves the elements in the range first to one before last in list other to before the position to. +The operation is fast when spicing within the same list, otherwise performs copies between different lists. + +--- + +```cpp +void merge(etl::ilist& other) +void merge(etl::ilist&& other) +``` +**Description** +Merges the elements in list other to this list. +The lists must be sorted. If a debug compile and asserts or exceptions are enabled than an etl::list_unsorted is emitted if either list is unsorted, otherwise undefined behaviour occurs. + +--- + +```cpp +template +void merge(etl::ilist& other, TCompare compare) +``` + +--- + +```cpp +template +void merge(etl::ilist&& other, TCompare compare) +``` +**Description** +Merges the elements in list other to this list using the supplied comparison function to determine order. +The lists must already be sorted according to the compare function. +If a debug compile and asserts or exceptions are enabled than an etl::list_unsorted is emitted if either list is unsorted, otherwise undefined behaviour occurs. + +## Operations + +```cpp +void remove(const T& value) +``` +**Description** +Removes from the container all the elements that compare equal to value. + +--- + +```cpp +template +void remove_if(TPredicate predicate) +``` +**Description** +Removes from the container all the elements that satisfy predicate. + +--- + +```cpp +void unique() +``` +**Description** +Removes all but the first element from every group of consecutive elements. + +--- + +```cpp +template +void unique(TPredicate predicate) +``` +**Description** +Removes all but the first element from every group of consecutive elements that satisfy the binary predicate. + +--- + +```cpp +void sort() +``` +**Description** +Sorts using the `<` operator. + +```cpp +template +void sort(TCompare compare) +``` +**Description** +Sorts using the supplied compare function. + +--- + +```cpp +void reverse() +``` +**Description** +Reverses the order of the list. + +## Non-member functions + +```cpp +operator == +``` +**Description** +`true` if the contents of the lists are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the lists are not equal, otherwise `false`. + +--- + +```cpp +operator < +``` +**Description** +`true` if the contents of the lhs are lexicographically less than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator <= +``` +**Description** +`true` if the contents of the lhs are lexicographically less than or equal to the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator > +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator >= +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than or equal to the contents of the rhs, otherwise `false`. + + +## Shared pool example + +```cpp +// The element type. +struct Point { int x; int y; }; + +// The list type +using List = etl::list_ext; + +// The shared pool. Maximum of 10 items. +etl::pool pool; + +// The vector of lists with shared pools. +etl::vector vector_of_lists(3, List(pool)); + +// Make some data. +Point point = { 1, 2 }; + +// Push one to each list. +vector_of_lists[0].push_back(point); +vector_of_lists[1].push_back(point); +vector_of_lists[2].push_back(point); + +size_t available = 0; + +available = vector_of_lists[0].available(); // Reports '7' +available = vector_of_lists[1].available(); // Reports '7' +available = vector_of_lists[2].available(); // Reports '7' +``` diff --git a/docs/containers/maps/_index.md b/docs/containers/maps/_index.md new file mode 100644 index 00000000..9f9818f3 --- /dev/null +++ b/docs/containers/maps/_index.md @@ -0,0 +1,6 @@ +--- +title: "Maps" +weight: 100 +--- + +Map like containers. \ No newline at end of file diff --git a/docs/containers/maps/const-map.md b/docs/containers/maps/const-map.md new file mode 100644 index 00000000..2679776b --- /dev/null +++ b/docs/containers/maps/const-map.md @@ -0,0 +1,211 @@ +--- +title: "const_map / const_map_ext" +--- + +{{< callout >}} + Header: `const_map.h` + Since: TBC + Similar to: [std::map](https://en.cppreference.com/w/cpp/container/map.html) +{{< /callout >}} + +A fixed capacity read-only map based on a sorted array. +The containers are designed to be able to be constexpr for C++14 and up. + +The interface is most similar to `std::map`. +Uses etl::less as the default key comparison method. +```cpp +etl::const_map +etl::const_map_ext +``` + +Inherits from `etl::iconst_map` +`etl::iconst_map` may be used as a Size independent pointer or reference type for any `etl::const_map` instance. +Both the key type and mapped type must be default constructible. + +## Template deduction guides +**C++17 and above** + +```cpp +template +etl::const_map(TPairs...) +``` + +**Example** +```cpp +constexpr etl::const_map data{ etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7} }; +``` +Defines data as an `const_map` of `int`/`int` pairs, of length 4, containing the supplied data. + +--- + +```cpp +template +etl::const_map_ext(TPairs...) +``` + +**Example** +```cpp +constexpr etl::pair values[]{ etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7} }; + +constexpr etl::const_map_ext data{ values }; +``` +Defines data as an `const_map` of `int`/`int` pairs, of length 4, containing the supplied data. + +```cpp +constexpr values[]{ etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7} }; +constexpr etl::span, 4> span{ values }; +constexpr etl::const_map_ext data{ span }; +``` +Defines data as an `const_map` of `int`/`int` pairs, of length 4, containing the supplied data. + +## Member types + +| Type | Maps to | Description | +| ----------------- | --------------------------------- | ---------------------------------------------------------------- | +| `key_type` | TKey | Must be default constructible. | +| `mapped_type` | TMapped | Must be default constructible. | +| `value_type` | pair | The type is either std::pair (default) or etl::pair (ETL_NO_STL) | +| `size_type` | std::size_t | | +| `difference_type` | std::ptrdiff_t | | +| `const_reference` | const T& | | +| `const_pointer` | const T* | | +|` const_iterator` | | Constant random access iterator | + +## Constructor +```cpp +template +ETL_CONSTEXPR14 explicit const_map(TElements&&... elements) ETL_NOEXCEPT +``` +Construct a const_map from a variadic list of elements. +Static asserts if the elements are not of type `value_type`. +Static asserts if the number of elements is greater than the capacity of the `const_map`. + +## Element access +```cpp +ETL_CONSTEXPR14 const TMapped& at(key_parameter_t key) const ETL_NOEXCEPT +``` +**Description** +Returns a const reference to the indexed element. + +```cpp +ETL_CONSTEXPR14 const TMapped& operator[](key_parameter_t key) const ETL_NOEXCEPT +``` +**Description** +Returns a const reference to the indexed element. + +## Iterators +```cpp +const_iterator begin() const ETL_NOEXCEPT +const_iterator cbegin() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the beginning of the map. + +```cpp +const_iterator end() const ETL_NOEXCEPT +const_iterator cend() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the end of the map. + +## Capacity +```cpp +ETL_CONSTEXPR14 bool empty() const ETL_NOEXCEPT +``` +**Description** +Returns `true` if the size of the map is zero, otherwise `false`. + +```cpp +ETL_CONSTEXPR14 bool full() const ETL_NOEXCEPT +``` +**Description** +Returns `true` if the size of the lookup is size, otherwise `false`. + +```cpp +ETL_CONSTEXPR14 size_t size() const ETL_NOEXCEPT +``` +**Description** +Returns the size of the lookup. + +```cpp +ETL_CONSTEXPR14 size_t max_size() const ETL_NOEXCEPT +``` +**Description** +Returns the maximum possible Size of the map. + +## Status +```cpp +ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT +``` +**Description** +Check that the elements are valid for a map. +The elements must be sorted and contain no duplicates. + +## Search +```cpp +ETL_CONSTEXPR14 const_iterator find(const key_type& key) const ETL_NOEXCEPT +``` +```cpp +ETL_CONSTEXPR14 const_iterator lower_bound(const key_type& key) const ETL_NOEXCEPT +``` +```cpp +ETL_CONSTEXPR14 const_iterator upper_bound(const key_type& key) const ETL_NOEXCEPT +``` +```cpp +ETL_CONSTEXPR14 pair equal_range(const key_type& key) const ETL_NOEXCEPT +``` +**Description** +The return type is either std::pair (default) or etl::pair (ETL_NO_STL) + +```cpp +ETL_CONSTEXPR14 bool contains(const key_type& k) const ETL_NOEXCEPT +``` +**Description** +Check if the container contains the key. + +--- + +**For comparators that define is_transparent.** + +```cpp +template +ETL_CONSTEXPR14 const_iterator find(const K& key) const ETL_NOEXCEPT +``` +```cpp +template +ETL_CONSTEXPR14 const_iterator lower_bound(const K& key) const ETL_NOEXCEPT +``` +```cpp +template +ETL_CONSTEXPR14 const_iterator upper_bound(const K& key) const ETL_NOEXCEPT +``` +```cpp +template +ETL_CONSTEXPR14 pair equal_range(const K& key) const ETL_NOEXCEPT +``` +```cpp +template +ETL_CONSTEXPR14 bool contains(const K& k) const ETL_NOEXCEPT +``` +**Description** +Check if the container contains the key. + +## Non-member functions + +**Lexicographically comparisons** +| Operator | Description | +| -------- | ----------------------------------------------------------------------------------- | +| `==` | `true` if the contents of the maps are equal, otherwise `false`. | +| `!=` | `true` if the contents of the maps are not equal, otherwise `false`. | +| `<` | `true` if the contents of the lhs is less-than the rhs, otherwise `false`. | +| `<=` | `true` if the contents of the lhs is less-than-equal the rhs, otherwise `false`. | +| `>` | `true` if the contents of the lhs is greater-than the rhs, otherwise `false`. | +| `>=` | `true` if the contents of the lhs is greater-than-equal the rhs, otherwise `false`. | + +## Technical stuff + +The const map is implemented as a sorted array key/value pairs. + diff --git a/docs/containers/maps/const-multimap.md b/docs/containers/maps/const-multimap.md new file mode 100644 index 00000000..19867bd4 --- /dev/null +++ b/docs/containers/maps/const-multimap.md @@ -0,0 +1,235 @@ +--- +title: "const_multimap / const_multimap_ext" +--- + +{{< callout >}} + Header: `const_multimap.h` + Since: TBC + Similar to: [std::multimap](https://en.cppreference.com/w/cpp/container/multimap.html) +{{< /callout >}} + +A fixed capacity read-only multimap based on a sorted array. +The containers are designed to be able to be constexpr for C++14 and up. + +The interface is most similar to `std::multimap`. +Uses `etl::less` as the default key comparison method. + +```cpp +etl::const_multimap +etl::const_multimap_ext +``` + +Inherits from `etl::iconst_multimap`. +`etl::iconst_multimap` may be used as a size independent pointer or reference type for any `etl::const_map` instance. +Both the key type and mapped type must be default constructible. + +## Template deduction guides +**C++17 and above** +```cpp +template +etl::const_multimap(TPairs...) +``` + +**Example** +```cpp +constexpr etl::const_multimap data{ etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7} }; +``` +Defines data as an const_multimap of `int`/`int` pairs, of length 4, containing the supplied data. + +```cpp +template +etl::const_multimap_ext(TPairs...) +``` + +**Example** +```cpp +constexpr etl::pair values[]{ etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7} }; +constexpr etl::const_multimap_ext data{ values }; +``` +Defines data as an const_multimap of `int`/`int` pairs, of length 4, containing the supplied data. +```cpp +constexpr values[]{ etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7} }; +constexpr etl::span, 4> span{ values }; +constexpr etl::const_multimap_ext data{ span }; +``` +Defines data as an const_multimap of `int`/`int` pairs, of length 4, containing the supplied data. + +## Member types + +| Type | Maps to | Description | +| ----------------- | --------------------------------- | ---------------------------------------------------------------- | +| `key_type` | TKey | Must be default constructible. | +| `mapped_type` | TMapped | Must be default constructible. | +| `value_type` | pair | The type is either std::pair (default) or etl::pair (ETL_NO_STL) | +| `size_type` | std::size_t | | +| `difference_type` | std::ptrdiff_t | | +| `const_reference` | const T& | | +| `const_pointer` | const T* | | +|` const_iterator` | | Constant random access iterator | + +## Constructor + +```cpp +template +ETL_CONSTEXPR14 explicit const_multimap(TElements&&... elements) ETL_NOEXCEPT +``` +**Description** +Constructs a const_multimap from a variadic list of elements. +Static asserts if the elements are not of type `value_type`. +Static asserts if the number of elements is greater than the capacity of the `const_multimap`. + +## Iterators + +```cpp +const_iterator begin() const ETL_NOEXCEPT +const_iterator cbegin() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the beginning of the multimap. + +```cpp +const_iterator end() const ETL_NOEXCEPT +const_iterator cend() const ETL_NOEXCEPT +``` +**Description** +Returns an iterator to the end of the multimap. + +## Capacity + +```cpp +ETL_CONSTEXPR14 bool empty() const ETL_NOEXCEPT +``` +**Description** +Returns true if the size of the multimap is zero, otherwise false. + +```cpp +ETL_CONSTEXPR14 bool full() const ETL_NOEXCEPT +``` +**Description** +Returns true if the size of the lookup is size, otherwise false. + +```cpp +ETL_CONSTEXPR14 size_t size() const ETL_NOEXCEPT +``` +**Description** +Returns the size of the lookup. + +```cpp +ETL_CONSTEXPR14 size_t max_size() const ETL_NOEXCEPT +``` +**Description** +Returns the maximum possible Size of the multimap. + +## Status +```cpp +ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT +``` +**Description** +Check that the elements are valid for a multimap. +The elements must be sorted. + +## Search + +```cpp +ETL_CONSTEXPR14 const_iterator find(const key_type& key) const ETL_NOEXCEPT +``` +```cpp +ETL_CONSTEXPR14 const_iterator lower_bound(const key_type& key) const ETL_NOEXCEPT +``` +```cpp +ETL_CONSTEXPR14 const_iterator upper_bound(const key_type& key) const ETL_NOEXCEPT +``` +```cpp +ETL_CONSTEXPR14 pair equal_range(const key_type& key) const ETL_NOEXCEPT +``` +**Description** +The return type is either `std::pair` (default) or `etl::pair` (ETL_NO_STL) + +```cpp +ETL_CONSTEXPR14 bool contains(const key_type& k) const ETL_NOEXCEPT +``` +**Description** +Checks if the container contains the key. + +--- + +**For comparators that define is_transparent.** + +```cpp +template +ETL_CONSTEXPR14 const_iterator find(const K& key) const ETL_NOEXCEPT +``` +```cpp +template +ETL_CONSTEXPR14 const_iterator lower_bound(const K& key) const ETL_NOEXCEPT +``` +```cpp +template +ETL_CONSTEXPR14 const_iterator upper_bound(const K& key) const ETL_NOEXCEPT +``` +```cpp +template +ETL_CONSTEXPR14 pair equal_range(const K& key) const ETL_NOEXCEPT +``` +```cpp +template +ETL_CONSTEXPR14 bool contains(const K& k) const ETL_NOEXCEPT +``` +**Description** +Checks if the container contains the key. + +## Non-member functions + +**Lexicographically comparisons** +```cpp +operator == +``` +**Description** +`true` if the contents of the lists are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the lists are not equal, otherwise `false`. + +--- + +```cpp +operator < +``` +**Description** +`true` if the contents of the lhs are lexicographically less than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator <= +``` +**Description** +`true` if the contents of the lhs are lexicographically less than or equal to the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator > +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than the contents of the rhs, otherwise `false`. + +--- + +```cpp +operator >= +``` +**Description** +`true` if the contents of the lhs are lexicographically greater than or equal to the contents of the rhs, otherwise `false`. + +## Technical stuff + +The const multimap is implemented as a sorted array key/value pairs. diff --git a/docs/containers/maps/flat-map.md b/docs/containers/maps/flat-map.md new file mode 100644 index 00000000..dd1d1850 --- /dev/null +++ b/docs/containers/maps/flat-map.md @@ -0,0 +1,500 @@ +--- +title: "flat_map" +--- + +{{< callout type="info">}} + Header: `flat_map.h` + Similar to: `std::map` +{{< /callout >}} + +A fixed capacity map based on a sorted vector. +The container is an associative lookup table with O(N) insertion and erase, and O(log N) search. +This container is best used for tables that are occasionally updated and spend most of their time being searched. +Uses `etl::less` as the default key comparison method. + +```cpp +etl::flat_map +``` + +Inherits from `etl::iflat_map`. +`etl::iflat_map` may be used as a size independent pointer or reference type for any `etl::flat_map` instance. + +## Template deduction guides +C++17 and above + +```cpp +template +etl::flat_map(TPairs...) +``` + +### Example +```cpp +etl::flat_map data{ etl::pair{0, 1}, etl::pair{2, 3}, etl::pair{4, 5}, etl::pair{6, 7} }; +``` +Defines data as an `flat_map` of `int`/`int` pairs, of length 4, containing the supplied data. + +## make_flat_map +C++11 and above +```cpp +template , + typename... TPairs> +constexpr auto make_flat_map(TValues&&... values) +``` + +### Example +```cpp +auto data = etl::make_flat_map(etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7}); +``` + +## Member types + +```cpp +key_type TKey +mapped_type TMapped +value_type pair + The type is either std::pair (default) or etl::pair (ETL_NO_STL) +size_type std::size_t +difference_type std::ptrdiff_t +reference T& +const_reference const T& +rvalue_reference T&& +pointer T* +const_pointer const T* +iterator Random access iterator +const_iterator Constant random access iterator +reverse_iterator reverse_iterator +const_reverse_iterator reverse_iterator +``` + +## Static Constants + +`MAX_SIZE` The maximum size of the flat map. + +## Constructors + +```cpp +etl::flat_map() +``` +**Description** +Default constructor. + +--- + +```cpp +etl::flat_map(const flat_map& other) +``` +**Description** +Copy constructor. + +--- + +```cpp +etl::flat_map(flat_map&& other) +``` +**Description** +Move constructor. + +--- + +```cpp +template +etl::flat_map(TIterator begin, TIterator end); +``` +**Description** +Construct from the range [`begin`, `end`). + +## Element access + +```cpp +TMapped& at(const_key_reference key) +const TMapped& at(const_key_reference key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Emits an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +TMapped& operator[](const_key_reference key) +const TMapped& operator[](const_key_reference key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +If the key is not in the table then a new entry is created. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the map. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the map. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the map. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the map. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns `true` if the size of the map is zero, otherwise `false`. + +--- + +```cpp +bool full() const +``` +**Description** +Returns `true` if the size of the lookup is `SIZE`, otherwise `false`. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the lookup. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the map. + +--- + +```cpp +size_t available() const +``` +**Description** +Returns the remaining available capacity in the map. + +## Modifiers + +```cpp +flat_map& operator = (const flat_map& rhs) +flat_map& operator = (flat_map&& rhs) +``` +**Description** +Copies or moves the data from another flat map. + +--- + +```cpp +pair insert(const value_type& value) +pair insert(value_type&& value) +iterator insert(iterator position, const value_type& value) +iterator insert(iterator position, value_type&& value) +``` +**Description** +Inserts a value into the map. + +```cpp +template +void insert(TIterator first, TIterator last) +``` +**Description** +Inserts values in to the map. +If the map is full then emits an `etl::flat_map_full`. If asserts or exceptions are not enabled then undefined behaviour occurs. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +```cpp +pair emplace((const value_type& value)) +pair emplace(const key_type& key, const mapped_type& value) +``` +**Description** +Inserts key/value pairs into the map by constructing directly into storage. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +**C++03** +The emplace functions differ from that of std::map in that, due to C++03 not supporting 'perfect forwarding', the values for constructing mapped types must be listed as parameters and not nested in a 'mapped' value parameter. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +```cpp +template +pair emplace(const key_type& key, const T1& value1) +``` +**Description** +Emplaces a value constructed from `key` and 1 argument into the map. + +```cpp +template +pair emplace(const key_type& key, const T1& value1, const T2& value2) +``` +**Description** +Emplaces a value constructed from `key` and 2 arguments into the map. + +```cpp +template +pair emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3) +``` +**Description** +Emplaces a value constructed from `key` and 3 arguments into the map. + +```cpp +template +pair emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3, const T4& value4) +``` +**Description** +Emplaces a value constructed from `key` and 4 arguments into the map. + +--- + +**C++11** +```cpp +template +pair emplace(const key_type& key, Args&& ... args) +``` +**Description** +Emplaces a value constructed from the `key` and arguments into the map. + +--- + +```cpp +size_t erase(key_value_parameter_t key) +void erase(iterator i_element) +void erase(iterator first, iterator last) +``` +**Description** +Erase elements from the map. + +--- + +```cpp +iterator erase(const_iterator i_element) +iterator erase(const_iteratorfirst, const_iteratorlast) +``` +**Description** +Erase elements from the map. +From: `20.20.0` + +--- + +```cpp +template +size_t erase(K&& key) +``` +**Description** +Erases values in the map. +Returns an iterator to the next element in the map. +Iterator parameters are not checked for validity. +From: `20.21.0` + +--- + +```cpp +void clear(); +``` +**Description** +Clears the map to a size of zero. + +## Search + +```cpp +iterator find(key_value_parameter_t key) +const_iterator find(key_value_parameter_t key) const +``` +**Description** +Searches for an element with the key `key`. +Returns an iterator to the element, or `end()` if not found. + +```cpp +iterator lower_bound(key_value_parameter_t key) +const_iterator lower_bound(key_value_parameter_t key) const +``` +**Description** +Searches for an element with the key not less than `key`. +Returns an iterator to the element, or `end()` if not found. + +```cpp +iterator upper_bound(key_value_parameter_t key) +const_iterator upper_bound(key_value_parameter_t key) const +``` +**Description** +Searches for an element with the key greater than `key`. +Returns an iterator to the element, or `end()` if not found. + +```cpp +pair equal_range(key_value_parameter_t key) +pair equal_range(key_value_parameter_t key) const +``` +**Description** +Returns the range of elements with a key equal to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +**For comparators that define is_transparent.** + +```cpp +template +iterator find(const K& key) +``` +**Description** +Searches for an element with the key `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +```cpp +template +const_iterator find(const K& key) const +``` +**Description** +Searches for an element with the key `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +--- + +```cpp +template +iterator lower_bound(const K& key) +``` +**Description** +Searches for an element with the key not less than `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +```cpp +template +const_iterator lower_bound(const K& key) const +``` +**Description** +Searches for an element with the key not less than `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +--- + +```cpp +template +iterator upper_bound(const K& key) +``` +**Description** +Searches for an element with the key greater than `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +```cpp +template +const_iterator upper_bound(const K& key) const +``` +**Description** +Searches for an element with the key greater than `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +--- + +```cpp +template +pair equal_range(const K& key) +``` +**Description** +Returns the range of elements with a key equal to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) +From: `20.21.0` +Since: C++11 + +```cpp +template +pair equal_range(const K& key) const +``` +**Description** +Returns the range of elements with a key equal to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) +From: `20.21.0` +Since: C++11 + +--- + +```cpp +bool contains(key_value_parameter_t key) const +``` +Check if the container contains the key. +From: `20.21.0` + + +--- + +```cpp +template +bool contains(const K& k) const +``` +Check if the container contains the key. +For comparators that define `is_transparent`. +From: `20.21.0` +Since: C++11 + +## Non-member functions + +**Lexicographically comparisons** + +```cpp +operator == +``` +`true` if the contents of the maps are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +`true` if the contents of the maps are not equal, otherwise `false`. + +## Technical stuff + +Flat maps are usually implemented internally as a sorted vector of key/value pairs. Whilst this makes searching fast, it can have a detrimental effect when items are inserted into a container that stores complex, non-trivial keys or values. +As inserting requires that all of the items to the right of the insert position must be shifted this can become an expensive operation for larger containers. + +To improve insertion performance ETL flat maps are implemented as vectors of pointers to key/value pairs, sorted by key value. An insertion will involve a copy of a range of pointers; an operation that can be very fast. + +The downside is that access to an item via an iterator will involve one indirection and the overhead of the container will be one pointer per item. A normal flat map implementation does not have this overhead. diff --git a/docs/containers/maps/flat-multimap.md b/docs/containers/maps/flat-multimap.md new file mode 100644 index 00000000..b6f6832d --- /dev/null +++ b/docs/containers/maps/flat-multimap.md @@ -0,0 +1,500 @@ +--- +title: "flat_multimap" +--- + +{{< callout type="info">}} + Header: `flat_multimap.h` + Similar to: `std::multimap` +{{< /callout >}} + +A fixed capacity multimap based on a sorted vector. +The container is an associative lookup table with O(N) insertion and erase, and O(log N) search. +This container is best used for tables that are occasionally updated and spend most of their time being searched. +Uses `etl::less` as the default key comparison method. + +```cpp +etl::flat_multimap +``` + +Inherits from `etl::iflat_map`. +`etl::iflat_map` may be used as a size independent pointer or reference type for any `etl::flat_multimap` instance. + +## Template deduction guides +C++17 and above + +```cpp +template +etl::flat_multimap(TPairs...) +``` + +### Example +```cpp +etl::flat_multimap data{ etl::pair{0, 1}, etl::pair{2, 3}, etl::pair{4, 5}, etl::pair{6, 7} }; +``` +Defines data as an `flat_multimap` of `int`/`int` pairs, of length 4, containing the supplied data. + +## make_flat_map +C++11 and above +```cpp +template , + typename... TPairs> +constexpr auto make_flat_map(TValues&&... values) +``` + +### Example +```cpp +auto data = etl::make_flat_map(etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7}); +``` + +## Member types + +```cpp +key_type TKey +mapped_type TMapped +value_type pair + The type is either std::pair (default) or etl::pair (ETL_NO_STL) +size_type std::size_t +difference_type std::ptrdiff_t +reference T& +const_reference const T& +rvalue_reference T&& +pointer T* +const_pointer const T* +iterator Random access iterator +const_iterator Constant random access iterator +reverse_iterator reverse_iterator +const_reverse_iterator reverse_iterator +``` + +## Static Constants + +`MAX_SIZE` The maximum size of the flat map. + +## Constructors + +```cpp +etl::flat_multimap() +``` +**Description** +Default constructor. + +--- + +```cpp +etl::flat_multimap(const flat_multimap& other) +``` +**Description** +Copy constructor. + +--- + +```cpp +etl::flat_multimap(flat_multimap&& other) +``` +**Description** +Move constructor. + +--- + +```cpp +template +etl::flat_multimap(TIterator begin, TIterator end); +``` +**Description** +Construct from the range [`begin`, `end`). + +## Element access + +```cpp +TMapped& at(const_key_reference key) +const TMapped& at(const_key_reference key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Emits an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +TMapped& operator[](const_key_reference key) +const TMapped& operator[](const_key_reference key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +If the key is not in the table then a new entry is created. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the map. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the map. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the map. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the map. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns `true` if the size of the map is zero, otherwise `false`. + +--- + +```cpp +bool full() const +``` +**Description** +Returns `true` if the size of the lookup is `SIZE`, otherwise `false`. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the lookup. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the map. + +--- + +```cpp +size_t available() const +``` +**Description** +Returns the remaining available capacity in the map. + +## Modifiers + +```cpp +flat_multimap& operator = (const flat_multimap& rhs) +flat_multimap& operator = (flat_multimap&& rhs) +``` +**Description** +Copies or moves the data from another flat map. + +--- + +```cpp +pair insert(const value_type& value) +pair insert(value_type&& value) +iterator insert(iterator position, const value_type& value) +iterator insert(iterator position, value_type&& value) +``` +**Description** +Inserts a value into the map. + +```cpp +template +void insert(TIterator first, TIterator last) +``` +**Description** +Inserts values in to the map. +If the map is full then emits an `etl::flat_map_full`. If asserts or exceptions are not enabled then undefined behaviour occurs. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +```cpp +pair emplace((const value_type& value)) +pair emplace(const key_type& key, const mapped_type& value) +``` +**Description** +Inserts key/value pairs into the map by constructing directly into storage. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +**C++03** +The emplace functions differ from that of std::map in that, due to C++03 not supporting 'perfect forwarding', the values for constructing mapped types must be listed as parameters and not nested in a 'mapped' value parameter. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +```cpp +template +pair emplace(const key_type& key, const T1& value1) +``` +**Description** +Emplaces a value constructed from `key` and 1 argument into the map. + +```cpp +template +pair emplace(const key_type& key, const T1& value1, const T2& value2) +``` +**Description** +Emplaces a value constructed from `key` and 2 arguments into the map. + +```cpp +template +pair emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3) +``` +**Description** +Emplaces a value constructed from `key` and 3 arguments into the map. + +```cpp +template +pair emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3, const T4& value4) +``` +**Description** +Emplaces a value constructed from `key` and 4 arguments into the map. + +--- + +**C++11** +```cpp +template +pair emplace(const key_type& key, Args&& ... args) +``` +**Description** +Emplaces a value constructed from the `key` and arguments into the map. + +--- + +```cpp +size_t erase(key_value_parameter_t key) +void erase(iterator i_element) +void erase(iterator first, iterator last) +``` +**Description** +Erase elements from the map. + +--- + +```cpp +iterator erase(const_iterator i_element) +iterator erase(const_iteratorfirst, const_iteratorlast) +``` +**Description** +Erase elements from the map. +From: `20.20.0` + +--- + +```cpp +template +size_t erase(K&& key) +``` +**Description** +Erases values in the map. +Returns an iterator to the next element in the map. +Iterator parameters are not checked for validity. +From: `20.21.0` + +--- + +```cpp +void clear(); +``` +**Description** +Clears the map to a size of zero. + +## Search + +```cpp +iterator find(key_value_parameter_t key) +const_iterator find(key_value_parameter_t key) const +``` +**Description** +Searches for an element with the key `key`. +Returns an iterator to the element, or `end()` if not found. + +```cpp +iterator lower_bound(key_value_parameter_t key) +const_iterator lower_bound(key_value_parameter_t key) const +``` +**Description** +Searches for an element with the key not less than `key`. +Returns an iterator to the element, or `end()` if not found. + +```cpp +iterator upper_bound(key_value_parameter_t key) +const_iterator upper_bound(key_value_parameter_t key) const +``` +**Description** +Searches for an element with the key greater than `key`. +Returns an iterator to the element, or `end()` if not found. + +```cpp +pair equal_range(key_value_parameter_t key) +pair equal_range(key_value_parameter_t key) const +``` +**Description** +Returns the range of elements with a key equal to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +**For comparators that define is_transparent.** + +```cpp +template +iterator find(const K& key) +``` +**Description** +Searches for an element with the key `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +```cpp +template +const_iterator find(const K& key) const +``` +**Description** +Searches for an element with the key `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +--- + +```cpp +template +iterator lower_bound(const K& key) +``` +**Description** +Searches for an element with the key not less than `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +```cpp +template +const_iterator lower_bound(const K& key) const +``` +**Description** +Searches for an element with the key not less than `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +--- + +```cpp +template +iterator upper_bound(const K& key) +``` +**Description** +Searches for an element with the key greater than `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +```cpp +template +const_iterator upper_bound(const K& key) const +``` +**Description** +Searches for an element with the key greater than `key`. +Returns an iterator to the element, or `end()` if not found. +From: `20.21.0` +Since: C++11 + +--- + +```cpp +template +pair equal_range(const K& key) +``` +**Description** +Returns the range of elements with a key equal to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) +From: `20.21.0` +Since: C++11 + +```cpp +template +pair equal_range(const K& key) const +``` +**Description** +Returns the range of elements with a key equal to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) +From: `20.21.0` +Since: C++11 + +--- + +```cpp +bool contains(key_value_parameter_t key) const +``` +Check if the container contains the key. +From: `20.21.0` + + +--- + +```cpp +template +bool contains(const K& k) const +``` +Check if the container contains the key. +For comparators that define `is_transparent`. +From: `20.21.0` +Since: C++11 + +## Non-member functions + +**Lexicographically comparisons** + +```cpp +operator == +``` +`true` if the contents of the maps are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +`true` if the contents of the maps are not equal, otherwise `false`. + +## Technical stuff + +Flat maps are usually implemented internally as a sorted vector of key/value pairs. Whilst this makes searching fast, it can have a detrimental effect when items are inserted into a container that stores complex, non-trivial keys or values. +As inserting requires that all of the items to the right of the insert position must be shifted this can become an expensive operation for larger containers. + +To improve insertion performance ETL flat maps are implemented as vectors of pointers to key/value pairs, sorted by key value. An insertion will involve a copy of a range of pointers; an operation that can be very fast. + +The downside is that access to an item via an iterator will involve one indirection and the overhead of the container will be one pointer per item. A normal flat map implementation does not have this overhead. diff --git a/docs/containers/maps/map.md b/docs/containers/maps/map.md new file mode 100644 index 00000000..5266d0d2 --- /dev/null +++ b/docs/containers/maps/map.md @@ -0,0 +1,425 @@ +--- +title: "map" +--- + +{{< callout type="info">}} + Header: `map.h` + Similar to: `std::map` +{{< /callout >}} + +A fixed capacity map. +Uses `std::less` as the default key comparison method. + +```cpp +etl::map +``` + +Inherits from `etl::imap`. +`etl::imap` may be used as a size independent pointer or reference type for any etl::map instance. + +## Template deduction guides +C++17 and above + +```cpp +template +etl::map(TPairs...) +``` + +### Example +```cpp +etl::map data{ etl::pair{0, 1}, etl::pair{2, 3}, etl::pair{4, 5}, etl::pair{6, 7} } +``` +Defines data as an map of `int`/`int` pairs, of length 4, containing the supplied data. + +## Make template +**C++11 and above** +```cpp +template , + typename... TPairs> +constexpr auto make_flat_map(TValues&&... values) +``` + +### Example +```cpp +auto data = etl::make_map(etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7}); +``` + +## Member types + +```cpp +key_type TKey +mapped_type TMapped +value_type etl or std::pair +size_type size_t +difference_type ptrdiff_t +reference value_type& +const_reference const value_type& +pointer value_type* +const_pointer const value_type* +iterator Random access iterator +const_iterator Constant random access iterator +reverse_iterator etl or std::reverse_iterator +const_reverse_iterator etl or std::reverse_iterator +``` + +## Constructor + +```cpp +etl::map(); +``` +**Description** +Default constructor. + + +```cpp +template +etl::map(TIterator begin, TIterator end); +``` +**Description** +Construct from the range [`begin`, `end`). + +## Element access + +```cpp +TMapped& at(key_parameter_t key) +const TMapped& at(key_parameter_t key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Asserts an `etl::map_out_of_range` if the key is not in the table. +If assert or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +TMapped& operator[](key_parameter_t key) +const TMapped& operator[](key_parameter_t key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +If the key does not exist then one is created using the default constructor. +If the map is full then asserts an `etl::map_full`. If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +iterator find(key_parameter_t key); +const_iterator find(key_parameter_t key) const +``` +**Description** +Searches the container for an element with a key equivalent to key and returns an iterator to it if found, otherwise it returns an iterator to `etl::map::end()`. + +--- + +```cpp +size_type count(key_parameter_t key) const +``` +**Description** +Count elements with a specific key. +Searches the container for elements with a key equivalent to key and returns the number of matches + +--- + +```cpp +iterator lower_bound(key_parameter_t key); +const_iterator lower_bound(key_parameter_t key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose `key` is not considered to go before key (i.e., either it is equivalent or goes after). + +--- + +```cpp +iterator upper_bound(key_parameter_t key); +const_iterator upper_bound(key_parameter_t key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is considered to go after `key`. + +--- + +```cpp +pair equal_range(key_parameter_t key) const +pair equal_range(key_parameter_t key) +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +**For comparators that define `is_transparent`.** + +```cpp +template +iterator find(const K& key) +``` +**Description** +Searches the container for an element with a key equivalent to key and returns an iterator to it if found, otherwise it returns an iterator to `etl::map::end()`. +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +const_iterator find(const K& key) const +``` +**Description** +Searches the container for an element with a key equivalent to `key` and returns a const iterator to it if found, otherwise it returns a const iterator to `etl::map::end()`. + +--- + +```cpp +template +iterator lower_bound(const K& key) +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is not considered to go before `key` (i.e., either it is equivalent or goes after). +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +const_iterator lower_bound(const K& key) const +``` +**Description** +Returns a const iterator pointing to the first element in the container whose key is not considered to go before `key` (i.e., either it is equivalent or goes after). +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +iterator upper_bound(const K& key) +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is considered to go after `key`. +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +const_iterator upper_bound(const K& key) const +``` +**Description** +Returns a const iterator pointing to the first element in the container whose key is considered to go after `key`. +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +pair equal_range(const K& key) +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +pair equal_range(const K& key) const +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +```cpp +bool contains(key_value_parameter_t key) const +``` +**Description** +Check if the container contains the key. +Since: `20.21.0` + +--- + +```cpp +template +bool contains(const K& k) const +``` +**Description** +Check if the container contains the key. +Since: `20.21.0` +C++11 or above. +For comparators that define is_transparent. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the map. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the map. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the map. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the map. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns true if the size of the map is zero, otherwise false. + +--- + +```cpp +bool full() const +``` +**Description** +Returns true if the size of the map is SIZE, otherwise false. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the map. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the map. + +--- + +```cpp +size_t available() const +``` +**Description** +Returns the remaining available capacity in the map. + +--- + +## Modifiers + +```cpp +template +void insert(TIterator begin, TIterator end) +``` +**Description** +Before: `20.20.0` +--- + + +```cpp +template +iterator insert(TIterator begin, TIterator end) +``` +**Description** +Since: `20.20.0` + +--- + +```cpp +iterator insert(mapped_parameter_t value) +``` +**Description** +Inserts values in to the map. +If the map is full then asserts an etl::map_full error. If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +template +iterator erase(TIterator begin, TIterator end) +``` +**Description** + +--- + +```cpp +iterator erase(TIterator element) +``` +**Description** +Erases values in the map. +Iterator are not checked for validity. + +--- + +```cpp +size_t erase(const key_type& key) +``` +**Description** + +--- + +20.21.0 +```cpp +template +size_t erase(K&& key) +``` +**Description** + +--- + +```cpp +void clear() +``` +**Description** +Clears the map to a size of zero. + +## Non-member functions + +```cpp +operator == +``` +**Description** +`true` if the contents of the maps are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the maps are not equal, otherwise `false`. diff --git a/docs/containers/maps/multimap.md b/docs/containers/maps/multimap.md new file mode 100644 index 00000000..96190528 --- /dev/null +++ b/docs/containers/maps/multimap.md @@ -0,0 +1,425 @@ +--- +title: "multimap" +--- + +{{< callout type="info">}} + Header: `multimap.h` + Similar to: `std::multimap` +{{< /callout >}} + +A fixed capacity multimap. +Uses `std::less` as the default key comparison method. + +```cpp +etl::multimap +``` + +Inherits from `etl::imap`. +`etl::imap` may be used as a size independent pointer or reference type for any etl::multimap instance. + +## Template deduction guides +C++17 and above + +```cpp +template +etl::multimap(TPairs...) +``` + +### Example +```cpp +etl::multimap data{ etl::pair{0, 1}, etl::pair{2, 3}, etl::pair{4, 5}, etl::pair{6, 7} } +``` +Defines data as an multimap of `int`/`int` pairs, of length 4, containing the supplied data. + +## Make template +**C++11 and above** +```cpp +template , + typename... TPairs> +constexpr auto make_flat_map(TValues&&... values) +``` + +### Example +```cpp +auto data = etl::make_map(etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7}); +``` + +## Member types + +```cpp +key_type TKey +mapped_type TMapped +value_type etl or std::pair +size_type size_t +difference_type ptrdiff_t +reference value_type& +const_reference const value_type& +pointer value_type* +const_pointer const value_type* +iterator Random access iterator +const_iterator Constant random access iterator +reverse_iterator etl or std::reverse_iterator +const_reverse_iterator etl or std::reverse_iterator +``` + +## Constructor + +```cpp +etl::multimap(); +``` +**Description** +Default constructor. + + +```cpp +template +etl::multimap(TIterator begin, TIterator end); +``` +**Description** +Construct from the range [`begin`, `end`). + +## Element access + +```cpp +TMapped& at(key_parameter_t key) +const TMapped& at(key_parameter_t key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Asserts an `etl::map_out_of_range` if the key is not in the table. +If assert or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +TMapped& operator[](key_parameter_t key) +const TMapped& operator[](key_parameter_t key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +If the key does not exist then one is created using the default constructor. +If the multimap is full then asserts an `etl::map_full`. If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +iterator find(key_parameter_t key); +const_iterator find(key_parameter_t key) const +``` +**Description** +Searches the container for an element with a key equivalent to key and returns an iterator to it if found, otherwise it returns an iterator to `etl::multimap::end()`. + +--- + +```cpp +size_type count(key_parameter_t key) const +``` +**Description** +Count elements with a specific key. +Searches the container for elements with a key equivalent to key and returns the number of matches + +--- + +```cpp +iterator lower_bound(key_parameter_t key); +const_iterator lower_bound(key_parameter_t key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose `key` is not considered to go before key (i.e., either it is equivalent or goes after). + +--- + +```cpp +iterator upper_bound(key_parameter_t key); +const_iterator upper_bound(key_parameter_t key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is considered to go after `key`. + +--- + +```cpp +pair equal_range(key_parameter_t key) const +pair equal_range(key_parameter_t key) +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +**For comparators that define `is_transparent`.** + +```cpp +template +iterator find(const K& key) +``` +**Description** +Searches the container for an element with a key equivalent to key and returns an iterator to it if found, otherwise it returns an iterator to `etl::multimap::end()`. +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +const_iterator find(const K& key) const +``` +**Description** +Searches the container for an element with a key equivalent to `key` and returns a const iterator to it if found, otherwise it returns a const iterator to `etl::multimap::end()`. + +--- + +```cpp +template +iterator lower_bound(const K& key) +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is not considered to go before `key` (i.e., either it is equivalent or goes after). +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +const_iterator lower_bound(const K& key) const +``` +**Description** +Returns a const iterator pointing to the first element in the container whose key is not considered to go before `key` (i.e., either it is equivalent or goes after). +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +iterator upper_bound(const K& key) +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is considered to go after `key`. +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +const_iterator upper_bound(const K& key) const +``` +**Description** +Returns a const iterator pointing to the first element in the container whose key is considered to go after `key`. +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +pair equal_range(const K& key) +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) +Since: `20.21.0` +C++11 or above. + +--- + +```cpp +template +pair equal_range(const K& key) const +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. +The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`) + +--- + +```cpp +bool contains(key_value_parameter_t key) const +``` +**Description** +Check if the container contains the key. +Since: `20.21.0` + +--- + +```cpp +template +bool contains(const K& k) const +``` +**Description** +Check if the container contains the key. +Since: `20.21.0` +C++11 or above. +For comparators that define is_transparent. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the multimap. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the multimap. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the multimap. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the multimap. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns true if the size of the multimap is zero, otherwise false. + +--- + +```cpp +bool full() const +``` +**Description** +Returns true if the size of the multimap is SIZE, otherwise false. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the multimap. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the multimap. + +--- + +```cpp +size_t available() const +``` +**Description** +Returns the remaining available capacity in the multimap. + +--- + +## Modifiers + +```cpp +template +void insert(TIterator begin, TIterator end) +``` +**Description** +Before: `20.20.0` +--- + + +```cpp +template +iterator insert(TIterator begin, TIterator end) +``` +**Description** +Since: `20.20.0` + +--- + +```cpp +iterator insert(mapped_parameter_t value) +``` +**Description** +Inserts values in to the multimap. +If the multimap is full then asserts an etl::map_full error. If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +template +iterator erase(TIterator begin, TIterator end) +``` +**Description** + +--- + +```cpp +iterator erase(TIterator element) +``` +**Description** +Erases values in the multimap. +Iterator are not checked for validity. + +--- + +```cpp +size_t erase(const key_type& key) +``` +**Description** + +--- + +20.21.0 +```cpp +template +size_t erase(K&& key) +``` +**Description** + +--- + +```cpp +void clear() +``` +**Description** +Clears the multimap to a size of zero. + +## Non-member functions + +```cpp +operator == +``` +**Description** +`true` if the contents of the maps are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the maps are not equal, otherwise `false`. diff --git a/docs/containers/maps/reference-flat-map.md b/docs/containers/maps/reference-flat-map.md new file mode 100644 index 00000000..738b7df4 --- /dev/null +++ b/docs/containers/maps/reference-flat-map.md @@ -0,0 +1,429 @@ +--- +title: "reference_flat_map" +--- + +{{< callout type="info">}} + Header: `reference_flat_map.h` + Similar to: `std::reference_flat_map` +{{< /callout >}} + +A fixed capacity reference map based on a sorted vector. +The container stores references to objects, rather than the objects themselves. +The container is an associative lookup table with O(N) insertion and erase, and O(log N) search. +This container is best used for tables that are occasionally updated and spend most of their time being searched. +Uses `etl::less` as the default key comparison method. + +```cpp +etl::reference_flat_map +``` + +Inherits from `etl::ireference_flat_map`. +`etl::ireference_flat_map` may be used as a size independent pointer or reference type for any `etl::reference_flat_map` instance. + +## Template deduction guides +C++17 and above + +```cpp +template +etl::reference_flat_map(TPairs...) +``` + +### Example + +```cpp +etl::reference_flat_map data{ etl::pair{0, 1}, etl::pair{2, 3}, etl::pair{4, 5}, etl::pair{6, 7} }; +``` +Defines data as an reference_flat_map of int, of length 4, containing the supplied data. + +## Make template +C++11 and above + +```cpp +template , + typename... TPairs> +constexpr auto make_reference_flat_map(TValues&&... values) +``` + +### Example +auto data = etl::make_reference_flat_map(etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7}); + +## Member types + +```cpp +key_type TKey +mapped_type TMapped +value_type pair +size_type size_t +difference_type ptrdiff_t +reference value_type& +const_reference const value_type& +pointer value_type* +const_pointer const value_type* +iterator Random access iterator +const_iterator Constant random access iterator +reverse_iterator ETL_OR_STD::reverse_iterator +const_reverse_iterator ETL_OR_STD::reverse_iterator +``` + +## Constructor + +```cpp +etl::reference_flat_map() +``` +**Description** +Default constructor. + +--- + +```cpp +etl::reference_flat_map(const flat_map& other) +``` +**Description** +Copy constructor. + +--- + +```cpp +template +etl::reference_flat_map(TIterator begin, TIterator end) +``` +**Description** +If the map is full then raises an `etl::reference_flat_map_full`. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +## Element access + +### at +```cpp +TMapped& at(const key_type& key) +const TMapped& at(const key_type& key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Raises an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +template +mapped_type& at(const K& key) +const mapped_type& at(const K& key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Raises an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### find + +```cpp +template +iterator find(const key_type& key) +const_iterator find(const key_type& key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Raises an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +template +iterator find(const K& key) +const_iterator find(const K& key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Raises an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### lower_bound + +```cpp +iterator lower_bound(const key_type& key) +const_iterator lower_bound(const key_type& key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is not considered to go before key (i.e., either it is equivalent or goes after). + +--- + +```cpp +template +iterator lower_bound(const K& key) +const_iterator lower_bound(const K& key) const +``` +Returns an iterator pointing to the first element in the container whose key is not considered to go before key (i.e., either it is equivalent or goes after). + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### upper_bound + +```cpp +iterator upper_bound(const key_type& key) +const_iterator upper_bound(const key_type& key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is considered to go after `key`. + +--- + +```cpp +template +iterator upper_bound(const K& key) +const_iterator upper_bound(const K& key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is considered to go after `key`. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### equal_range + +```cpp +pair equal_range(const key_type& key) +pair equal_range(const key_type& key) const +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. + +--- + +```cpp +template +pair equal_range(const K& key) +pair equal_range(const K& key) const +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### contains + +```cpp +bool contains(const value_type& key) const +``` +**Description** +Check if the container contains the key. +Since: `20.21.0` + +--- + +```cpp +template +bool contains(const K& k) const +``` +**Description** +Check if the container contains the key. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the map. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the map. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the map. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the map. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns `true` if the size of the map is zero, otherwise `false`. + +--- + +```cpp +bool full() const +``` +**Description** +Returns `true` if the size of the lookup is SIZE, otherwise `false`. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the lookup. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the map. + +--- + +```cpp +size_t available() const +``` +**Description** +Returns the remaining available capacity in the map. + +## Modifiers + +```cpp +reference_flat_map& operator = (const reference_flat_map& rhs) +``` +**Description** +Copies the data from another flat map. + +--- + +```cpp +pair insert(const value_type& value) +``` +**Description** +Inserts `value` into the map. + +--- + +```cpp +iterator insert(iterator position, const value_type& value) +``` +**Description** +Inserts `value` into the map at th esuggested `position`. + +--- + +```cpp +template +void insert(TIterator first, TIterator last) +``` +**Description** +Inserts values in to the map. If the map is full then raises an `etl::flat_map_full`. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +size_t erase(const key_type& key) +``` +**Description** +Erase the element with `key`. + +--- + +```cpp +void erase(iterator i_element) +``` +**Description** +Erase the element at `i_element`. + +--- + +```cpp +void erase(iterator first, iterator last) +``` +**Description** +Erase elements in the range [`first`, `last`). + +--- + +```cpp +template +size_t erase(K&& key) +``` +**Description** +Erases values in the map. +Since: `20.21.0` + +--- + +```cpp +void clear() +``` +**Description** +Clears the lookup to a size of zero. +Iterator are not checked for validity. + +## Non-member functions +Lexicographically comparisons + +```cpp +operator == +``` +**Description** +`true` if the contents of the maps are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the maps are not equal, otherwise `false`. + +## Technical stuff + +Reference flat maps are different from the normal version in that the elements are not copied, but linked directly. +This means that the lifetime of the element inserted must be as great as that of the map that contains it. +Unlike most other reference containers, the map has a finite capacity. + +Flat maps are usually implemented internally as a sorted vector of key/value pairs. Whilst this makes searching fast, it can have a detrimental effect when items are inserted into a container that stores complex, non-trivial keys or values. +As inserting requires that all of the items above the insert position must be shifted, this can become an expensive operation for larger containers. + +To improve insertion performance ETL reference flat maps are implemented as vectors of pointers to key/value pairs, sorted by key value. An insertion will involve a copy of a range of pointers; an operation that can be made very fast. + +The downside is that access to an item via an iterator will involve one indirection and the overhead of the container will be one pointer per item. A normal flat map implementation does not have this overhead. + diff --git a/docs/containers/maps/reference-flat-multimap.md b/docs/containers/maps/reference-flat-multimap.md new file mode 100644 index 00000000..f34bbb67 --- /dev/null +++ b/docs/containers/maps/reference-flat-multimap.md @@ -0,0 +1,433 @@ +--- +title: "reference_flat_multimap" +--- + +{{< callout type="info">}} + Header: `reference_flat_multimap.h` + Similar to: `std::reference_flat_multimap` +{{< /callout >}} + +A fixed capacity reference map based on a sorted vector. +The container stores references to objects, rather than the objects themselves. +The container is an associative lookup table with O(N) insertion and erase, and O(log N) search. +This container is best used for tables that are occasionally updated and spend most of their time being searched. +Uses `etl::less` as the default key comparison method. + +```cpp +etl::reference_flat_multimap +``` + +Inherits from `etl::ireference_flat_multimap`. +`etl::ireference_flat_multimap` may be used as a size independent pointer or reference type for any `etl::reference_flat_multimap` instance. + +## Template deduction guides +C++17 and above + +```cpp +template +etl::reference_flat_multimap(TPairs...) +``` + +### Example + +```cpp +etl::reference_flat_multimap data{ etl::pair{0, 1}, etl::pair{2, 3}, etl::pair{4, 5}, etl::pair{6, 7} }; +``` +Defines data as an reference_flat_multimap of int, of length 4, containing the supplied data. + +## Make template +C++11 and above + +```cpp +template , + typename... TPairs> +constexpr auto make_reference_flat_map(TValues&&... values) +``` + +### Example +auto data = etl::make_reference_flat_map(etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7}); + +## Member types + +```cpp +key_type TKey +mapped_type TMapped +value_type pair +size_type size_t +difference_type ptrdiff_t +reference value_type& +const_reference const value_type& +pointer value_type* +const_pointer const value_type* +iterator Random access iterator +const_iterator Constant random access iterator +reverse_iterator ETL_OR_STD::reverse_iterator +const_reverse_iterator ETL_OR_STD::reverse_iterator +``` + +## Constructor + +```cpp +etl::reference_flat_multimap() +``` +**Description** +Default constructor. + +--- + +```cpp +etl::reference_flat_multimap(const flat_map& other) +``` +**Description** +Copy constructor. + +--- + +```cpp +template +etl::reference_flat_multimap(TIterator begin, TIterator end) +``` +**Description** +If the map is full then raises an `etl::reference_flat_map_full`. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +## Element access + +### at +```cpp +TMapped& at(const key_type& key) +const TMapped& at(const key_type& key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Raises an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +template +mapped_type& at(const K& key) +const mapped_type& at(const K& key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Raises an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### find + +```cpp +template +iterator find(const key_type& key) +const_iterator find(const key_type& key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Raises an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +template +iterator find(const K& key) +const_iterator find(const K& key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Raises an `etl::flat_map_out_of_range` if the key is not in the table. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### lower_bound + +```cpp +iterator lower_bound(const key_type& key) +const_iterator lower_bound(const key_type& key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is not considered to go before key (i.e., either it is equivalent or goes after). + +--- + +```cpp +template +iterator lower_bound(const K& key) +const_iterator lower_bound(const K& key) const +``` +Returns an iterator pointing to the first element in the container whose key is not considered to go before key (i.e., either it is equivalent or goes after). + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### upper_bound + +```cpp +iterator upper_bound(const key_type& key) +const_iterator upper_bound(const key_type& key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is considered to go after `key`. + +--- + +```cpp +template +iterator upper_bound(const K& key) +const_iterator upper_bound(const K& key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is considered to go after `key`. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### equal_range + +```cpp +pair equal_range(const key_type& key) +pair equal_range(const key_type& key) const +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +--- + +```cpp +template +pair equal_range(const K& key) +pair equal_range(const K& key) const +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to `key`. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +### contains + +```cpp +bool contains(const value_type& key) const +``` +**Description** +Check if the container contains the key. +Since: `20.21.0` + +--- + +```cpp +template +bool contains(const K& k) const +``` +**Description** +Check if the container contains the key. + +C++11 or above. +For comparators that define `is_transparent`. +Since: `20.21.0` + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the map. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the map. + +--- + +```cpp +iterator rbegin() +const_iterator rbegin() const +const_iterator crbegin() const +``` +**Description** +Returns a reverse iterator to the beginning of the map. + +--- + +```cpp +iterator rend() +const_iterator rend() const +const_iterator crend() const +``` +**Description** +Returns a reverse iterator to the end of the map. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns `true` if the size of the map is zero, otherwise `false`. + +--- + +```cpp +bool full() const +``` +**Description** +Returns `true` if the size of the lookup is SIZE, otherwise `false`. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the lookup. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the map. + +--- + +```cpp +size_t available() const +``` +**Description** +Returns the remaining available capacity in the map. + +## Modifiers + +```cpp +reference_flat_multimap& operator = (const reference_flat_multimap& rhs) +``` +**Description** +Copies the data from another flat map. + +--- + +```cpp +pair insert(const value_type& value) +``` +**Description** +Inserts `value` into the map. + +--- + +```cpp +iterator insert(iterator position, const value_type& value) +``` +**Description** +Inserts `value` into the map at th esuggested `position`. + +--- + +```cpp +template +void insert(TIterator first, TIterator last) +``` +**Description** +Inserts values in to the map. If the map is full then raises an `etl::flat_map_full`. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +size_t erase(const key_type& key) +``` +**Description** +Erase the element with `key`. + +--- + +```cpp +void erase(iterator i_element) +``` +**Description** +Erase the element at `i_element`. + +--- + +```cpp +void erase(iterator first, iterator last) +``` +**Description** +Erase elements in the range [`first`, `last`). + +--- + +```cpp +template +size_t erase(K&& key) +``` +**Description** +Erases values in the map. +Since: `20.21.0` + +--- + +```cpp +void clear() +``` +**Description** +Clears the lookup to a size of zero. +Iterator are not checked for validity. + +## Non-member functions +Lexicographically comparisons + +```cpp +operator == +``` +**Description** +`true` if the contents of the maps are equal, otherwise `false`. + +--- + +```cpp +operator != +``` +**Description** +`true` if the contents of the maps are not equal, otherwise `false`. + +## Technical stuff + +Reference flat maps are different from the normal version in that the elements are not copied, but linked directly. +This means that the lifetime of the element inserted must be as great as that of the map that contains it. +Unlike most other reference containers, the map has a finite capacity. + +Flat maps are usually implemented internally as a sorted vector of key/value pairs. Whilst this makes searching fast, it can have a detrimental effect when items are inserted into a container that stores complex, non-trivial keys or values. +As inserting requires that all of the items above the insert position must be shifted, this can become an expensive operation for larger containers. + +To improve insertion performance ETL reference flat maps are implemented as vectors of pointers to key/value pairs, sorted by key value. An insertion will involve a copy of a range of pointers; an operation that can be made very fast. + +The downside is that access to an item via an iterator will involve one indirection and the overhead of the container will be one pointer per item. A normal flat map implementation does not have this overhead. + diff --git a/docs/containers/maps/unordered-map.md b/docs/containers/maps/unordered-map.md new file mode 100644 index 00000000..bf2810ad --- /dev/null +++ b/docs/containers/maps/unordered-map.md @@ -0,0 +1,375 @@ +--- +title: "unordered_map" +--- + +{{< callout type="info">}} + Header: `unordered_map.h` + Similar to: `std::unordered_map` +{{< /callout >}} + +A fixed capacity unordered map. +Uses `std::less` as the default key comparison method. + +This page just describes etl::unordered_map. + +```cpp +template , + typename TKeyEqual = etl::equal_to> +class unordered_map +``` + +Inherits from `iunordered_map`. +`etl::iunordered_map` may be used as a size independent pointer or reference type for any `etl::unordered_map` instance. + +## Template deduction guides +C++17 and above + +```cpp +template +etl::unordered_map(TPairs...) +``` + +### Example +```cpp +etl::unordered_map data{ etl::pair{0, 1}, etl::pair{2, 3}, etl::pair{4, 5}, etl::pair{6, 7} }; +``` +Defines data as an unordered map of `int`/`int` pairs, of length 4, containing the supplied data. + +## Make template +C++11 and above + +```cpp +template , + typename TKeyEqual = etl::equal_to + typename... TPairs> +constexpr auto make_unordered_map(TValues&&... values) +``` + +### Example +```cpp +auto data = etl::make_unordered_map(etl::pair{0, 1}, etl::pair{2, 3}, + etl::pair{4, 5}, etl::pair{6, 7}); +``` + +## Member types + +```cpp +value_type pair +key_type The type of the key value +mapped_type The type of the mapped value +hasher The type used to hash the key +key_equal The functor used to compare keys +reference A reference to a value_type +const_reference A reference to a const value_type +pointer A pointer to a value_type +const_pointer A pointer to a const value_type +size_type The type used for size information +iterator Random access iterator +const_iterator Constant random access iterator +local_iterator Iterator to a bucket +local_const_iterator A const iterator to a bucket +``` + +## Constructor + +```cpp +unordered_map() +``` +**Description** +Default constructor + +--- + +```cpp +unordered_map(const unordered_map& other) +``` +**Description** +Copy constructor + +--- + +```cpp +template +unordered_map(TIterator begin, TIterator end) +``` +**Description** +Construct from a range + +## Element access + +```cpp +mapped_type& at(key_parameter_t key) +const mapped_type& at(key_parameter_t key) const +``` +**Description** +Returns a reference or const reference to the indexed element. +Raises an `etl::unordered_map_out_of_range` if the key is not in the table. +If assert or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +mapped_type& operator[](key_parameter_t key) +``` +**Description** +Returns a reference to the indexed element. +If the key does not exist then one is created using the default constructor. +If the map is full then emits an `etl::unordered_map_full`. +If asserts or exceptions are not enabled then undefined behaviour occurs. + +--- + +```cpp +iterator find(key_parameter_t key); +const_iterator find (key_parameter_t key) const +``` +**Description** +Searches the container for an element with a key equivalent to key and returns an iterator to it if found, otherwise it returns an iterator to `etl::unordered_map::end()`. + +--- + +```cpp +bool contains(const_key_reference key) const +``` +**Description** +Check if the map contains the key. + +--- + +```cpp +template +bool contains(const K& key) const +``` +**Description** +Check if the map contains the key. +Enabled if the comparator is transparent. + +--- + +```cpp +size_type count(key_parameter_t key) const +``` +**Description** +Count elements with a specific key. +Searches the container for elements with a key equivalent to key and returns the number of matches + +--- + +```cpp +iterator lower_bound(key_parameter_t key) +const_iterator lower_bound(key_parameter_t key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is not considered to go before key (i.e., either it is equivalent or goes after). + +--- + +```cpp +iterator upper_bound(key_parameter_t key) +const_iterator upper_bound(key_parameter_t key) const +``` +**Description** +Returns an iterator pointing to the first element in the container whose key is considered to go after key. + +--- + +```cpp +pair equal_range(key_parameter_t key) +pair equal_range(key_parameter_t key) const +``` +**Description** +Returns the bounds of a range that includes all the elements in the container which have a key equivalent to key. + +## Iterators + +```cpp +iterator begin() +const_iterator begin() const +const_iterator cbegin() const +``` +**Description** +Returns an iterator to the beginning of the map. + +--- + +```cpp +iterator end() +const_iterator end() const +const_iterator cend() const +``` +**Description** +Returns an iterator to the end of the map. + +## Capacity + +```cpp +bool empty() const +``` +**Description** +Returns `true` if the size of the map is zero, otherwise `false`. + +--- + +```cpp +bool full() const +``` +**Description** +Returns `true` if the size of the map is `SIZE`, otherwise `false`. + +--- + +```cpp +size_t size() const +``` +**Description** +Returns the size of the map. + +--- + +```cpp +size_t max_size() const +``` +**Description** +Returns the maximum possible size of the map. + +--- + +```cpp +size_t available() const +``` +**Description** +Returns the remaining available capacity in the map. + +--- + +```cpp +size_type get_bucket_index(key_parameter_t key) const +``` +**Description** +Returns the bucket index for the key. + +--- + +```cpp +size_type bucket_size(key_parameter_t key) const +``` +**Description** +Returns the size of the bucket key. + +--- + +```cpp +size_type max_bucket_count() const +``` +**Description** +Returns the maximum number of the buckets the container can hold. + +--- + +```cpp +float load_factor() const +``` +**Description** +Returns the load factor = size / bucket_count + +--- + +```cpp +hasher hash_function() const +``` +**Description** +Returns the function that hashes the keys. + +--- + +```cpp +key_equal key_eq() const +``` +**Description** +Returns the function that compares the keys. + +## Modifiers + +```cpp +template +void assign(TIterator first, TIterator last) +``` +**Description** +Assigns elements from the range [`first`, `last`)]. +Clears the container before assigning. + +--- + +```cpp +pair insert(const value_type& key_value_pair) +iterator insert(const_iterator, const value_type& key_value_pair) +``` +**Description** +Assigns elements from the range [`first`, `last`)]. +Clears the container before assigning. + +--- + +```cpp +template