diff --git a/.clang-format b/.clang-format index 39cbfaf3..67f77eb5 100644 --- a/.clang-format +++ b/.clang-format @@ -1,57 +1,184 @@ --- -#------------------------------------ -# Configuration for clang-format v12 -#------------------------------------ +BasedOnStyle: LLVM +Standard: Auto # let the formatter accept any C++ standard -Language: Cpp +# ============================================================================= +# Indentation +# ============================================================================= +TabWidth: 2 +ContinuationIndentWidth: 2 +ConstructorInitializerIndentWidth: 2 +NamespaceIndentation: All # everything inside namespace is indented +IndentCaseLabels: true # case labels at switch-body indent level +IndentCaseBlocks: true # indent block inside case label +IndentExternBlock: Indent +IndentWrappedFunctionNames: true # keep function name at same indent as return type +IndentPPDirectives: BeforeHash # nested #if / #include get indented before the # +PPIndentWidth: 2 -BasedOnStyle: Chromium +# ============================================================================= +# Braces & line-break style +# ============================================================================= +BreakBeforeBraces: Allman +BreakConstructorInitializers: BeforeComma # colon on new line, commas lead +BreakInheritanceList: BeforeComma +BreakBeforeBinaryOperators: NonAssignment +BreakStringLiterals: false +AlwaysBreakTemplateDeclarations: Yes # template <…> always on its own line +BreakAfterAttributes: Always -SortIncludes: true -IncludeBlocks: Preserve +# ============================================================================= +# Short statements +# ============================================================================= +AllowShortBlocksOnASingleLine: Empty +AllowShortFunctionsOnASingleLine: Empty # only empty bodies: void f() {} +AllowShortCaseLabelsOnASingleLine: true # case X: stmt; break; on one line +AllowShortLoopsOnASingleLine: true +AllowShortLambdasOnASingleLine: Inline + +# ============================================================================= +# Empty lines +# ============================================================================= +KeepEmptyLinesAtTheStartOfBlocks: false +EmptyLineBeforeAccessModifier: Always # blank line before public:/private:/protected: +EmptyLineAfterAccessModifier: Always # blank line after public:/private:/protected: +InsertNewlineAtEOF: true + +# ============================================================================= +# Spacing +# ============================================================================= +SpacesInAngles: Leave # preserve C++03 "> >" vs C++11 ">>" +SpacesInContainerLiterals: false + +# ============================================================================= +# Alignment +# ============================================================================= +PointerAlignment: Left # T* ptr, const T& ref +ReferenceAlignment: Left +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignConsecutiveBitFields: true +AlignConsecutiveMacros: true # align macro bodies + +# ============================================================================= +# Line length and wrapping +# ============================================================================= +ColumnLimit: 150 +ReflowComments: true # preserve hand-formatted comment rulers +AlignEscapedNewlines: Left + +# ============================================================================= +# Includes +# ============================================================================= IncludeCategories: - Regex: '^(<|")(.*/)?platform\.h(>|")$' + Priority: -1 + - Regex: 'private' Priority: 1 - Regex: '.*' - Priority: 2 + Priority: 0 -BinPackParameters: false -BitFieldColonSpacing: Both +# ============================================================================= +# Arguments, parameters and constructor initialisers +# ============================================================================= +PackConstructorInitializers: Never # each initialiser on its own line -BreakBeforeBraces: Allman -BreakConstructorInitializers: BeforeComma +# ============================================================================= +# Namespaces and using declarations +# ============================================================================= +SortUsingDeclarations: Lexicographic -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: true -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: false +# ============================================================================= +# Macro-aware formatting +# ============================================================================= +# ETL-specific macros that should be treated as statement-level constructs +StatementMacros: + - ETL_DECLARE_DEBUG_COUNT + - ETL_INCREMENT_DEBUG_COUNT + - ETL_DECREMENT_DEBUG_COUNT + - ETL_ADD_DEBUG_COUNT + - ETL_STATIC_ASSERT + - ETL_ASSERT + - ETL_ASSERT_OR_RETURN + - ETL_ASSERT_OR_RETURN_VALUE + - ETL_ASSERT_FAIL + - ETL_ASSERT_FAIL_AND_RETURN + - ETL_ASSERT_FAIL_AND_RETURN_VALUE + - ETL_MOVE + - ETL_ENUM_CLASS + - ETL_ENUM_CLASS_TYPE + - ETL_IF_CONSTEXPR -AllowAllArgumentsOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: true +# Macros that behave like attributes or specifiers. +AttributeMacros: + - ETL_NORETURN + - ETL_FINAL + - ETL_OVERRIDE + - ETL_EXPLICIT + - ETL_DELETE + - ETL_CONSTANT + - ETL_CONSTEXPR + - ETL_CONSTEXPR11 + - ETL_CONSTEXPR14 + - ETL_CONSTEXPR17 + - ETL_CONSTEXPR20 + - ETL_CONSTEXPR23 + - ETL_CONSTEVAL + - ETL_NODISCARD + - ETL_NORETURN + - ETL_DEPRECATED + - ETL_DEPRECATED_REASON + - ETL_LIKELY + - ETL_UNLIKELY + - ETL_FALLTHROUGH + - ETL_MAYBE_UNUSED + - ETL_INLINE_VAR + - ETL_ASSUME + - ETL_LVALUE_REF_QUALIFIER + - ETL_RVALUE_REF_QUALIFIER + - ETL_NOEXCEPT + - ETL_NOEXCEPT_EXPR + - ETL_NOEXCEPT_IF + - ETL_NOEXCEPT_FROM -ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' -ConstructorInitializerIndentWidth: '2' +Macros: + - ETL_NORETURN=[[noreturn]] + - ETL_FINAL=final + - ETL_OVERRIDE=override + - ETL_EXPLICIT=explicit + - ETL_DELETE=delete + - ETL_CONSTANT=const + - ETL_CONSTEXPR=constexpr + - ETL_CONSTEXPR11=constexpr + - ETL_CONSTEXPR14=constexpr + - ETL_CONSTEXPR17=constexpr + - ETL_CONSTEXPR20=constexpr + - ETL_CONSTEXPR23=constexpr + - ETL_CONSTEVAL=consteval + - ETL_NODISCARD=[[nodiscard]] + - ETL_NORETURN=[[noreturn]] + - ETL_DEPRECATED=[[deprecated]] +# - ETL_DEPRECATED_REASON=[[deprecated(%0)]] # Hangs with clang-format 18 + - ETL_LIKELY=[[likely]] + - ETL_UNLIKELY=[[unlikely]] + - ETL_FALLTHROUGH=[[fallthrough]] + - ETL_MAYBE_UNUSED=[[maybe_unused]] + - ETL_INLINE_VAR=inline + - ETL_ASSUME=[[assume(&0)]] + - ETL_LVALUE_REF_QUALIFIER=& + - ETL_RVALUE_REF_QUALIFIER=&& + - ETL_NOEXCEPT=noexcept +# - ETL_NOEXCEPT_EXPR=noexcept(&0)) # Hangs with clang-format 18 +# - ETL_NOEXCEPT_IF=noexcept(&0) # Hangs with clang-format 18 +# - ETL_NOEXCEPT_FROM=noexcept(&0) # Hangs with clang-format 18 -NamespaceIndentation: All -IndentPPDirectives: BeforeHash -PointerAlignment: Left -ColumnLimit: '0' -ContinuationIndentWidth: '2' -UseTab: Never -TabWidth: '2' -IndentWidth: '2' -AccessModifierOffset : '-2' -IndentCaseLabels: false -Cpp11BracedListStyle: 'true' -AlignAfterOpenBracket: Align -AlignConsecutiveDeclarations: true +# Macros that behave like type names +TypenameMacros: + - ETL_OR_STD -#------------------------------------ -# Configurations not supported by clang-format v12 -#------------------------------------ -# BreakInheritanceList: AfterComma -# EmptyLineBeforeAccessModifier: Always -# EmptyLineAfterAccessModifier: Always -# ReferenceAlignment: Left - -... +# Do not reformat these macros — they contain DSL-like content +WhitespaceSensitiveMacros: + - ETL_ERROR_TEXT + - ETL_DECLARE_ENUM_TYPE + - ETL_ENUM_TYPE + - ETL_END_ENUM_TYPE diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 090b5302..f51b1a16 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,20 +1,61 @@ -ARG BASE_IMAGE_NAME="clang:latest" +ARG BASE_IMAGE_NAME="mcr.microsoft.com/devcontainers/cpp:2@sha256:a5eb5a1e9109af88bf82ebb0f71903608a68144851ed1e4b852e31b251ac59c6" FROM ${BASE_IMAGE_NAME} -ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="3.31.7" +ARG DEBIAN_SNAPSHOT="20260223T000000Z" -# Optionally install the cmake for vcpkg -COPY ./reinstall-cmake.sh /tmp/ +SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +ENV LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 \ + TZ=UTC + +RUN set -eux \ + && export DEBIAN_FRONTEND=noninteractive \ + && if [[ "${DEBIAN_SNAPSHOT}" != "none" ]]; then \ + snapshot_main="http://snapshot.debian.org/archive/debian/${DEBIAN_SNAPSHOT}"; \ + snapshot_security="http://snapshot.debian.org/archive/debian-security/${DEBIAN_SNAPSHOT}"; \ + if [[ -f /etc/apt/sources.list.d/debian.sources ]]; then \ + sed -ri "s|^URIs: https?://deb.debian.org/debian$|URIs: ${snapshot_main}|g" /etc/apt/sources.list.d/debian.sources; \ + sed -ri "s|^URIs: https?://deb.debian.org/debian-security$|URIs: ${snapshot_security}|g" /etc/apt/sources.list.d/debian.sources; \ + elif [[ -f /etc/apt/sources.list ]] || compgen -G "/etc/apt/sources.list.d/*.list" > /dev/null; then \ + for list_file in /etc/apt/sources.list /etc/apt/sources.list.d/*.list; do \ + [[ -f "${list_file}" ]] || continue; \ + sed -ri "s|https?://deb.debian.org/debian|${snapshot_main}|g" "${list_file}"; \ + sed -ri "s|https?://security.debian.org/debian-security|${snapshot_security}|g" "${list_file}"; \ + sed -ri "s|https?://deb.debian.org/debian-security|${snapshot_security}|g" "${list_file}"; \ + done; \ + else \ + echo "ERROR: DEBIAN_SNAPSHOT='${DEBIAN_SNAPSHOT}' is set, but no supported apt source files were found."; \ + echo "Expected /etc/apt/sources.list.d/debian.sources or one or more .list files under /etc/apt/."; \ + exit 1; \ + fi; \ + printf 'Acquire::Check-Valid-Until "false";\n' > /etc/apt/apt.conf.d/99snapshot; \ + fi \ + && apt-get update \ && apt-get -y install --no-install-recommends \ + python3-full \ + python3-pip \ git \ wget \ - python3-cogapp \ - && rm -rf /var/lib/apt/lists/* + 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 -RUN if [ "${REINSTALL_CMAKE_VERSION_FROM_SOURCE}" != "none" ]; then \ - chmod +x /tmp/reinstall-cmake.sh && /tmp/reinstall-cmake.sh ${REINSTALL_CMAKE_VERSION_FROM_SOURCE}; \ - fi \ - && rm -f /tmp/reinstall-cmake.sh +RUN set -eux \ + && echo "Pip version: " \ + && pip --version \ + && echo "Cogapp version: " \ + && pip show cogapp \ + && echo "Git version: " \ + && git --version \ + && echo "Wget version: " \ + && wget --version \ + && echo "Cmake version: " \ + && cmake --version \ + && echo "Make version: " \ + && make --version diff --git a/.devcontainer/clang10/devcontainer.json b/.devcontainer/clang10/devcontainer.json index d34b0411..d62c3ce3 100644 --- a/.devcontainer/clang10/devcontainer.json +++ b/.devcontainer/clang10/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:10" + "BASE_IMAGE_NAME": "silkeh/clang:10", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang11/devcontainer.json b/.devcontainer/clang11/devcontainer.json index 6727e497..e83ec9f4 100644 --- a/.devcontainer/clang11/devcontainer.json +++ b/.devcontainer/clang11/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:11" + "BASE_IMAGE_NAME": "silkeh/clang:11", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang12/devcontainer.json b/.devcontainer/clang12/devcontainer.json index 26ab72ca..6a6407cf 100644 --- a/.devcontainer/clang12/devcontainer.json +++ b/.devcontainer/clang12/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:12" + "BASE_IMAGE_NAME": "silkeh/clang:12", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang13/devcontainer.json b/.devcontainer/clang13/devcontainer.json index 309ced68..46197161 100644 --- a/.devcontainer/clang13/devcontainer.json +++ b/.devcontainer/clang13/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:13" + "BASE_IMAGE_NAME": "silkeh/clang:13", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang14/devcontainer.json b/.devcontainer/clang14/devcontainer.json index ecdf0ad9..13512eff 100644 --- a/.devcontainer/clang14/devcontainer.json +++ b/.devcontainer/clang14/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:14" + "BASE_IMAGE_NAME": "silkeh/clang:14", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang15/devcontainer.json b/.devcontainer/clang15/devcontainer.json index 35a1ccef..42051a63 100644 --- a/.devcontainer/clang15/devcontainer.json +++ b/.devcontainer/clang15/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:15" + "BASE_IMAGE_NAME": "silkeh/clang:15", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang16/devcontainer.json b/.devcontainer/clang16/devcontainer.json index aa9b25ee..8284ae3a 100644 --- a/.devcontainer/clang16/devcontainer.json +++ b/.devcontainer/clang16/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:16" + "BASE_IMAGE_NAME": "silkeh/clang:16", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang17/devcontainer.json b/.devcontainer/clang17/devcontainer.json index deb08dbb..ca9747fa 100644 --- a/.devcontainer/clang17/devcontainer.json +++ b/.devcontainer/clang17/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:17" + "BASE_IMAGE_NAME": "silkeh/clang:17", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang18/devcontainer.json b/.devcontainer/clang18/devcontainer.json index d7954145..5ff70469 100644 --- a/.devcontainer/clang18/devcontainer.json +++ b/.devcontainer/clang18/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:18-bullseye" + "BASE_IMAGE_NAME": "silkeh/clang:18-bullseye", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang19/devcontainer.json b/.devcontainer/clang19/devcontainer.json index 7c525acf..bc617a36 100644 --- a/.devcontainer/clang19/devcontainer.json +++ b/.devcontainer/clang19/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:19-bullseye" + "BASE_IMAGE_NAME": "silkeh/clang:19-bullseye", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang20/devcontainer.json b/.devcontainer/clang20/devcontainer.json index 0dadc10b..5522774f 100644 --- a/.devcontainer/clang20/devcontainer.json +++ b/.devcontainer/clang20/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:20-bullseye" + "BASE_IMAGE_NAME": "silkeh/clang:20-bullseye", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang21/devcontainer.json b/.devcontainer/clang21/devcontainer.json new file mode 100644 index 00000000..e09e5c3a --- /dev/null +++ b/.devcontainer/clang21/devcontainer.json @@ -0,0 +1,13 @@ +// 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": "Clang 21", + "build": { + "dockerfile": "../Dockerfile", + "args": { + "BASE_IMAGE_NAME": "silkeh/clang:21-bullseye", + "DEBIAN_SNAPSHOT": "none" + }, + "context": "../context" + } +} diff --git a/.devcontainer/clang7/devcontainer.json b/.devcontainer/clang7/devcontainer.json index 09a67efa..87d7c7e1 100644 --- a/.devcontainer/clang7/devcontainer.json +++ b/.devcontainer/clang7/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:7" + "BASE_IMAGE_NAME": "silkeh/clang:7", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang8/devcontainer.json b/.devcontainer/clang8/devcontainer.json index 99a853e5..c29c069c 100644 --- a/.devcontainer/clang8/devcontainer.json +++ b/.devcontainer/clang8/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:8" + "BASE_IMAGE_NAME": "silkeh/clang:8", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/clang9/devcontainer.json b/.devcontainer/clang9/devcontainer.json index b77d4f2b..308f8ba2 100644 --- a/.devcontainer/clang9/devcontainer.json +++ b/.devcontainer/clang9/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "silkeh/clang:9" + "BASE_IMAGE_NAME": "silkeh/clang:9", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 161faeec..5daf6034 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "./Dockerfile", "args": { - "BASE_IMAGE_NAME": "mcr.microsoft.com/devcontainers/cpp:debian-12" + "BASE_IMAGE_NAME": "mcr.microsoft.com/devcontainers/cpp:2@sha256:a5eb5a1e9109af88bf82ebb0f71903608a68144851ed1e4b852e31b251ac59c6", + "DEBIAN_SNAPSHOT": "20260223T000000Z" }, "context": "./context" } diff --git a/.devcontainer/gcc09/devcontainer.json b/.devcontainer/gcc09/devcontainer.json index ab5e64ee..d72b5f3c 100644 --- a/.devcontainer/gcc09/devcontainer.json +++ b/.devcontainer/gcc09/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "gcc:9" + "BASE_IMAGE_NAME": "gcc:9", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/gcc10/devcontainer.json b/.devcontainer/gcc10/devcontainer.json index 03bf117e..698402b8 100644 --- a/.devcontainer/gcc10/devcontainer.json +++ b/.devcontainer/gcc10/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "gcc:10" + "BASE_IMAGE_NAME": "gcc:10", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/gcc11/devcontainer.json b/.devcontainer/gcc11/devcontainer.json index 9d837fad..c8235db7 100644 --- a/.devcontainer/gcc11/devcontainer.json +++ b/.devcontainer/gcc11/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "gcc:11" + "BASE_IMAGE_NAME": "gcc:11", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/gcc12/devcontainer.json b/.devcontainer/gcc12/devcontainer.json index 9c07a79f..bee6541e 100644 --- a/.devcontainer/gcc12/devcontainer.json +++ b/.devcontainer/gcc12/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "gcc:12" + "BASE_IMAGE_NAME": "gcc:12", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/gcc13/devcontainer.json b/.devcontainer/gcc13/devcontainer.json index 4b9767e8..7434b808 100644 --- a/.devcontainer/gcc13/devcontainer.json +++ b/.devcontainer/gcc13/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "gcc:13" + "BASE_IMAGE_NAME": "gcc:13", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/gcc14/devcontainer.json b/.devcontainer/gcc14/devcontainer.json index 374ff299..33e043b9 100644 --- a/.devcontainer/gcc14/devcontainer.json +++ b/.devcontainer/gcc14/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "gcc:14" + "BASE_IMAGE_NAME": "gcc:14", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/gcc15/devcontainer.json b/.devcontainer/gcc15/devcontainer.json index 498a6fe8..143d5b16 100644 --- a/.devcontainer/gcc15/devcontainer.json +++ b/.devcontainer/gcc15/devcontainer.json @@ -5,7 +5,8 @@ "build": { "dockerfile": "../Dockerfile", "args": { - "BASE_IMAGE_NAME": "gcc:15" + "BASE_IMAGE_NAME": "gcc:15", + "DEBIAN_SNAPSHOT": "none" }, "context": "../context" } diff --git a/.devcontainer/s390x/Dockerfile b/.devcontainer/s390x/Dockerfile new file mode 100644 index 00000000..21a6289c --- /dev/null +++ b/.devcontainer/s390x/Dockerfile @@ -0,0 +1,40 @@ +# s390x Big-Endian Test Environment for ETL +# Uses QEMU user-mode emulation to run s390x binaries on x64 host +FROM debian:trixie + +# Avoid prompts from apt +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\ + qemu-user-static \ + qemu-user \ + binfmt-support \ + gcc-s390x-linux-gnu \ + g++-s390x-linux-gnu \ + cmake \ + make \ + ninja-build \ + git \ + wget \ + file \ + libc6:s390x \ + libstdc++6:s390x \ + && rm -rf /var/lib/apt/lists/* + +# Set working directory +WORKDIR /workspaces/etl + +# Verify QEMU and cross-compilation setup +RUN echo "=== Host Architecture ===" && \ + uname -m && \ + echo "" && \ + echo "=== s390x Cross Compiler ===" && \ + s390x-linux-gnu-gcc --version && \ + echo "" && \ + echo "=== QEMU s390x ===" && \ + qemu-s390x-static --version | head -n1 + +# Default command +CMD ["/bin/bash"] diff --git a/.devcontainer/s390x/devcontainer.json b/.devcontainer/s390x/devcontainer.json new file mode 100644 index 00000000..8b7f8235 --- /dev/null +++ b/.devcontainer/s390x/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": "s390x Big Endian (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/s390x/toolchain-s390x.cmake", + "-DBUILD_TESTS=ON", + "-DNO_STL=OFF", + "-DETL_CXX_STANDARD=17" + ], + "cmake.buildDirectory": "${workspaceFolder}/build-s390x", + "cmake.generator": "Ninja" + } + } + }, + "remoteUser": "root" +} diff --git a/.devcontainer/s390x/toolchain-s390x.cmake b/.devcontainer/s390x/toolchain-s390x.cmake new file mode 100644 index 00000000..706884d9 --- /dev/null +++ b/.devcontainer/s390x/toolchain-s390x.cmake @@ -0,0 +1,21 @@ +# CMake toolchain file for s390x cross-compilation +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR s390x) + +# Specify the cross compiler +set(CMAKE_C_COMPILER s390x-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER s390x-linux-gnu-g++) +set(CMAKE_AR s390x-linux-gnu-ar) +set(CMAKE_RANLIB s390x-linux-gnu-ranlib) +set(CMAKE_STRIP s390x-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-s390x-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries") diff --git a/.github/workflows/clang-format.yaml b/.github/workflows/clang-format.yaml new file mode 100644 index 00000000..083f265f --- /dev/null +++ b/.github/workflows/clang-format.yaml @@ -0,0 +1,43 @@ +name: clang-format + +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + clang-format: + name: clang-format + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install clang-format and git + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends git clang-format + clang-format --version + + - name: Run clang-format on added/changed files + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + BEFORE="origin/${{ github.base_ref }}" + elif [ "${{ github.event_name }}" = "push" ]; then + BEFORE="${{ github.event.before }}" + else + echo "Unsupported event: ${{ github.event_name }}" + echo "This is likely a bug in the workflow configuration. Please report it to the maintainers." + exit 1 + fi + + git diff --name-only -z --diff-filter=AMCR "$BEFORE"..HEAD -- \ + '*.c' '*.cc' '*.cxx' '*.cpp' \ + '*.h' '*.hh' '*.hpp' '*.hxx' \ + '*.ipp' '*.inl' \ + ':(exclude)include/etl/generators/*' \ + ':(exclude)include/etl/private/*_cpp03.h' \ + | xargs -0 --no-run-if-empty clang-format --Werror -n --style=file diff --git a/.github/workflows/clang-format_update.yaml b/.github/workflows/clang-format_update.yaml new file mode 100644 index 00000000..acaa3453 --- /dev/null +++ b/.github/workflows/clang-format_update.yaml @@ -0,0 +1,21 @@ +name: clang-format-update + +on: + workflow_dispatch: + +jobs: + clang-format: + runs-on: ubuntu-24.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install clang-format + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends clang-format + clang-format --version + + - name: Run clang-format + run: | + find . \( -name '*.cpp' -o -name '*.h' -o -name '*.c' \) | xargs clang-format --dry-run --Werror diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..79f9553e --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,72 @@ +name: coverage + +on: + push: + branches: [ master, pull-request/* ] + pull_request: + branches: [ master, pull-request/* ] + types: [opened, synchronize, reopened] + +# Allow only one concurrent deployment to GitHub Pages +concurrency: + group: coverage-${{ github.ref }} + cancel-in-progress: true + +# Grant GITHUB_TOKEN the minimum permissions needed at the workflow level +permissions: + contents: read + +jobs: + + coverage: + name: Generate Coverage Report + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y lcov llvm gcc g++ clang cmake + + - name: Build, test, and collect coverage + run: | + cd test + ./run-coverage.sh + + - name: Upload coverage report artifact + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: test/build-coverage/coverage/ + retention-days: 30 + + - name: Upload Pages artifact + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + uses: actions/upload-pages-artifact@v3 + with: + path: test/build-coverage/coverage/ + + deploy-pages: + name: Deploy to GitHub Pages + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + needs: coverage + runs-on: ubuntu-22.04 + + permissions: + pages: write + id-token: write + + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + +# GitHub Repository settings +# -> Settings -> Pages +# -> Source: gh actions diff --git a/.gitignore b/.gitignore index ced27dae..0d41e526 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ ## Personal ################# docs/html +hugo/public +hugo/.hugo_build.lock include/etl/html/ include/etl/latex/ test/vs2013/Debug diff --git a/.treefmt.toml b/.treefmt.toml new file mode 100644 index 00000000..0e6248a0 --- /dev/null +++ b/.treefmt.toml @@ -0,0 +1,45 @@ +[global] +excludes = [ + "**/Doxyfile", + "**/Makefile", + "*.*-format", + "*.S", + "*.cmm", + "*.css", + "*.dld", + "*.gdb", + "*.gif", + "*.gitignore", + "*.html", + "*.ini", + "*.josh", + "*.json", + "*.md", + "*.png", + "*.puml", + "*.py", + "*.rb", + "*.rst", + "*.s", + "*.sh", + "*.spec", + "*.toml", + "*.txt", + "*.yaml", + "*.yml", + "docker/**", + "temp/**", + "scripts/clang-format-wrapper", + "include/etl/generators/**", + "include/etl/private/*_cpp03.h", + "subprojects/**", + "test/UnitTest++/**", + "test/Deprecated/**", + "test/Performance/**", + "test/temp/**" +] + +[formatter.cpp] +command = "scripts/clang-format-wrapper" +options = [ "-i", "--style=file" ] +includes = [ "*.c", "*.cc", "*.cpp", "*.h", "*.hh", "*.hpp" ] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6231d084..2d7a3028 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,6 +6,7 @@ Thanks for considering a contribution! Here’s what you need to know before ope - If you are fixing a bug, add a unit test that *fails* before the bug fix is implemented. - Do not initiate a pull request until all of the units tests pass. See below for information on project files and test scripts. - Branches should be based on the branch `master`. If `development` has pending updates, I’ll rebase the PR against it before pulling.. +- For formatting help, you can use clang-format, or the convenience wrapper treefmt. See also [docs/source-formatting.md](docs/source-formatting.md) There is a project file for VS2022 for C++14, 17, 20, 23, and bash scripts that run the tests for C++11, 14, 17, 20, 23 under Linux with GCC and Clang. There are syntax-only check bash scripts that cover C++03, 11, 14, 17, 20, 23 under Linux with GCC and Clang. diff --git a/arduino/Embedded_Template_Library.h b/arduino/Embedded_Template_Library.h index 5959207e..aed4c865 100644 --- a/arduino/Embedded_Template_Library.h +++ b/arduino/Embedded_Template_Library.h @@ -2,79 +2,79 @@ #ifndef ETL_EMBEDDED_TEMPLATE_LIBRARY_INCLUDED #define ETL_EMBEDDED_TEMPLATE_LIBRARY_INCLUDED -#if defined(TEENSYDUINO) +#if defined(TEENSYDUINO) - #if defined(__AVR_ATmega32U4__) - #define ARDUINO_BOARD "Teensy 2.0" - #elif defined(__AVR_AT90USB1286__) - #define ARDUINO_BOARD "Teensy++ 2.0" - #elif defined(__MK20DX128__) - #define ARDUINO_BOARD "Teensy 3.0" - #elif defined(__MK20DX256__) - #define ARDUINO_BOARD "Teensy 3.2" // and Teensy 3.1 - #elif defined(__MKL26Z64__) - #define ARDUINO_BOARD "Teensy LC" - #elif defined(__MK64FX512__) - #define ARDUINO_BOARD "Teensy 3.5" - #elif defined(__MK66FX1M0__) - #define ARDUINO_BOARD "Teensy 3.6" - #else - #define ARDUINO_BOARD "Unknown" - #endif + #if defined(__AVR_ATmega32U4__) + #define ARDUINO_BOARD "Teensy 2.0" + #elif defined(__AVR_AT90USB1286__) + #define ARDUINO_BOARD "Teensy++ 2.0" + #elif defined(__MK20DX128__) + #define ARDUINO_BOARD "Teensy 3.0" + #elif defined(__MK20DX256__) + #define ARDUINO_BOARD "Teensy 3.2" // and Teensy 3.1 + #elif defined(__MKL26Z64__) + #define ARDUINO_BOARD "Teensy LC" + #elif defined(__MK64FX512__) + #define ARDUINO_BOARD "Teensy 3.5" + #elif defined(__MK66FX1M0__) + #define ARDUINO_BOARD "Teensy 3.6" + #else + #define ARDUINO_BOARD "Unknown" + #endif #else // --------------- Arduino ------------------ - #if defined(ARDUINO_AVR_ADK) - #define ARDUINO_BOARD "Mega Adk" - #elif defined(ARDUINO_AVR_BT) - #define ARDUINO_BOARD "Bt" - #elif defined(ARDUINO_AVR_DUEMILANOVE) - #define ARDUINO_BOARD "Duemilanove" - #elif defined(ARDUINO_AVR_ESPLORA) - #define ARDUINO_BOARD "Esplora" - #elif defined(ARDUINO_AVR_ETHERNET) - #define ARDUINO_BOARD "Ethernet" - #elif defined(ARDUINO_AVR_FIO) - #define ARDUINO_BOARD "Fio" - #elif defined(ARDUINO_AVR_GEMMA) - #define ARDUINO_BOARD "Gemma" - #elif defined(ARDUINO_AVR_LEONARDO) - #define ARDUINO_BOARD "Leonardo" - #elif defined(ARDUINO_AVR_LILYPAD) - #define ARDUINO_BOARD "Lilypad" - #elif defined(ARDUINO_AVR_LILYPAD_USB) - #define ARDUINO_BOARD "Lilypad Usb" - #elif defined(ARDUINO_AVR_MEGA) - #define ARDUINO_BOARD "Mega" - #elif defined(ARDUINO_AVR_MEGA2560) - #define ARDUINO_BOARD "Mega 2560" - #elif defined(ARDUINO_AVR_MICRO) - #define ARDUINO_BOARD "Micro" - #elif defined(ARDUINO_AVR_MINI) - #define ARDUINO_BOARD "Mini" - #elif defined(ARDUINO_AVR_NANO) - #define ARDUINO_BOARD "Nano" - #elif defined(ARDUINO_AVR_NG) - #define ARDUINO_BOARD "NG" - #elif defined(ARDUINO_AVR_PRO) - #define ARDUINO_BOARD "Pro" - #elif defined(ARDUINO_AVR_ROBOT_CONTROL) - #define ARDUINO_BOARD "Robot Ctrl" - #elif defined(ARDUINO_AVR_ROBOT_MOTOR) - #define ARDUINO_BOARD "Robot Motor" - #elif defined(ARDUINO_AVR_UNO) - #define ARDUINO_BOARD "Uno" - #elif defined(ARDUINO_AVR_YUN) - #define ARDUINO_BOARD "Yun" - #elif defined(ARDUINO_SAM_DUE) - #define ARDUINO_BOARD "Due" - #elif defined(ARDUINO_SAMD_ZERO) - #define ARDUINO_BOARD "Zero" - #elif defined(ARDUINO_ARC32_TOOLS) - #define ARDUINO_BOARD "101" - #else - #define ARDUINO_BOARD "Unknown" - #endif + #if defined(ARDUINO_AVR_ADK) + #define ARDUINO_BOARD "Mega Adk" + #elif defined(ARDUINO_AVR_BT) + #define ARDUINO_BOARD "Bt" + #elif defined(ARDUINO_AVR_DUEMILANOVE) + #define ARDUINO_BOARD "Duemilanove" + #elif defined(ARDUINO_AVR_ESPLORA) + #define ARDUINO_BOARD "Esplora" + #elif defined(ARDUINO_AVR_ETHERNET) + #define ARDUINO_BOARD "Ethernet" + #elif defined(ARDUINO_AVR_FIO) + #define ARDUINO_BOARD "Fio" + #elif defined(ARDUINO_AVR_GEMMA) + #define ARDUINO_BOARD "Gemma" + #elif defined(ARDUINO_AVR_LEONARDO) + #define ARDUINO_BOARD "Leonardo" + #elif defined(ARDUINO_AVR_LILYPAD) + #define ARDUINO_BOARD "Lilypad" + #elif defined(ARDUINO_AVR_LILYPAD_USB) + #define ARDUINO_BOARD "Lilypad Usb" + #elif defined(ARDUINO_AVR_MEGA) + #define ARDUINO_BOARD "Mega" + #elif defined(ARDUINO_AVR_MEGA2560) + #define ARDUINO_BOARD "Mega 2560" + #elif defined(ARDUINO_AVR_MICRO) + #define ARDUINO_BOARD "Micro" + #elif defined(ARDUINO_AVR_MINI) + #define ARDUINO_BOARD "Mini" + #elif defined(ARDUINO_AVR_NANO) + #define ARDUINO_BOARD "Nano" + #elif defined(ARDUINO_AVR_NG) + #define ARDUINO_BOARD "NG" + #elif defined(ARDUINO_AVR_PRO) + #define ARDUINO_BOARD "Pro" + #elif defined(ARDUINO_AVR_ROBOT_CONTROL) + #define ARDUINO_BOARD "Robot Ctrl" + #elif defined(ARDUINO_AVR_ROBOT_MOTOR) + #define ARDUINO_BOARD "Robot Motor" + #elif defined(ARDUINO_AVR_UNO) + #define ARDUINO_BOARD "Uno" + #elif defined(ARDUINO_AVR_YUN) + #define ARDUINO_BOARD "Yun" + #elif defined(ARDUINO_SAM_DUE) + #define ARDUINO_BOARD "Due" + #elif defined(ARDUINO_SAMD_ZERO) + #define ARDUINO_BOARD "Zero" + #elif defined(ARDUINO_ARC32_TOOLS) + #define ARDUINO_BOARD "101" + #else + #define ARDUINO_BOARD "Unknown" + #endif #endif #endif diff --git a/arduino/library-arduino.json b/arduino/library-arduino.json index b77c5717..44c7157f 100644 --- a/arduino/library-arduino.json +++ b/arduino/library-arduino.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library ETL", - "version": "20.46.2", + "version": "20.47.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/arduino/library-arduino.properties b/arduino/library-arduino.properties index c1a4af8f..1dba8aee 100644 --- a/arduino/library-arduino.properties +++ b/arduino/library-arduino.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.46.2 +version=20.47.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 00000000..6fac68f0 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,6 @@ +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..23e43ac5 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,7 @@ +--- +title: ETL documentation +--- + +## Pages + +* [Manchester](manchester.md) diff --git a/docs/manchester.md b/docs/manchester.md new file mode 100644 index 00000000..d73cb958 --- /dev/null +++ b/docs/manchester.md @@ -0,0 +1,259 @@ +--- +title: Manchester encoding and decoding +--- + +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. + +## See also + +[Manchester code](https://en.wikipedia.org/wiki/Manchester_code) + +## Features + +- Normal and inverted Manchester encoding +- Support for multiple encoding chunk sizes: 8-bit, 16-bit and 32-bit +- Span-based operations or chunk-based operations +- Constexpr functions for compile-time encoding/decoding +- Validation of encoded data +- Chunked span I/O uses little-endian byte order for multi-byte chunks, independent of host platform endianness + +## Algorithm background + +To encode the value `0b11001100` we must first duplicate all bits to create the value `0b1111000011110000`. We then perform an XOR of this value with the constant `0b1010101010101010` (`0xAAAA`) to obtain the Manchester coded value of `0b1010010110100101`. We have now replaced each `1` bit with the sequence `10` and each `0` bit with the sequence `01`. + +### 2. Bit duplication + +Bit duplication is achieved with the following steps. This is also called binary interleaving. The example shows encoding of an 8-bit value. + +| Step | High Byte | Low Byte | Operation | +|------|--------------------|--------------------|----------------------------| +| 0 | `_ _ _ _ _ _ _ _` | `A B C D E F G H` | input value (i) | +| 1 | `_ _ _ _ A B C D` | `_ _ _ _ E F G H` | `(i \| (i << 4)) & 0x0F0F` | +| 2 | `_ _ A B _ _ C D` | `_ _ E F _ _ G H` | `(i \| (i << 2)) & 0x3333` | +| 3 | `_ A _ B _ C _ D` | `_ E _ F _ G _ H` | `(i \| (i << 1)) & 0x5555` | +| 4 | `A A B B C C D D` | `E E F F G G H H` | `(i \| (i << 1))` | + +This process can be easily extended to 16-bit or 32-bit values by adding additional steps to the bit duplication. + +### 3. Manchester Decoding + +Manchester decoding is done in a similar, but reversed way. + +### 4. Error Detection + +Error detection in Manchester coded data is done by comparing 2 neighboring bits. If they are +equal, then there is an error in the encoded input data. + +Comparing all 8 bit pairs in a 16-bit word is done as follows. + +| Step | Binary Value | Operation | Description | +|------|--------------|-------------------|-----------------------------------------------------------------------------------------------| +| 1 | `11011000` | Original | First bit pair (lsb, 00) is invalid. Last bit pair is also invalid. Other bit pairs are valid | +| 2 | `01101100` | Shift right by 1 | Shift the original value right by one bit | +| 3 | `10110100` | XOR | XOR the original with the shifted value | +| 4 | `01010101` | Mask with 0x55 | Apply mask to isolate bit pairs | +| 5 | `00010100` | Result | If result is not equal to 0x55, there was an error in the input | + +## Analysis + +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 `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 + +```cpp +typedef manchester_base manchester; +``` + +Manchester encoder using normal encoding (no inversion). + +#### etl::manchester_inverted + +```cpp +typedef manchester_base manchester_inverted; +``` + +Manchester encoder using inverted encoding. + +### Encoding Functions + +#### Encode single value + +```cpp +template +static ETL_CONSTEXPR14 typename encoded::type encode(TDecoded decoded) +``` + +Encodes a single value using Manchester encoding. + +**Parameters:** + +- `decoded`: The value to encode (`uint8_t`, `uint16_t`, or `uint32_t`) + +**Returns:** + +- The Manchester encoded value (twice the bit width of input) + +**Example:** + +```cpp +uint16_t encoded = etl::manchester::encode(0x55); +``` + +#### Encode range + +```cpp +template +static ETL_CONSTEXPR14 void encode(etl::span decoded, + etl::span encoded) +``` + +Encodes a span of data using the specified chunk size. + +**Parameters:** + +- `decoded`: Source data to encode +- `encoded`: Destination for encoded data (must be twice the size of `decoded`) + +**Template Parameters:** + +- `TChunk`: Chunk size for encoding (`uint8_t`, `uint16_t` or `uint32_t`) + +**Example:** + +```cpp +std::array data = {0x12, 0x34, 0x56, 0x78}; +std::array encoded_data1{}; +std::array encoded_data2{}; + +// Encode with TChunk == uint8_t +etl::manchester::encode(data, encoded_data1); + +// Encode with TChunk == uint32_t +etl::manchester::encode(data, encoded_data2); +``` + +### Decoding Functions + +#### Decode single value + +```cpp +template +static ETL_CONSTEXPR14 typename decoded::type decode(TEncoded encoded) +``` + +Decodes a single Manchester encoded value. + +**Parameters:** + +- `encoded`: The encoded value to decode (`uint16_t`, `uint32_t`, or `uint64_t`) + +**Returns:** + +- The Manchester decoded value (half the bit width of input) + +**Example:** + +```cpp +uint8_t decoded = etl::manchester::decode(0x5A5A); +``` + +#### Decode range + +```cpp +template ::type> +static ETL_CONSTEXPR14 void decode(etl::span encoded, + etl::span decoded) +``` + +Decodes a span of Manchester encoded data. + +**Parameters:** + +- `encoded`: Source data to decode +- `decoded`: Destination for decoded data (must be half the size of `encoded`) + +**Template Parameters:** + +- `TChunk`: Chunk type for decoding (`uint16_t`, `uint32_t`, or `uint64_t`) + +**Example:** + +```cpp +std::array encoded = {/* ... */}; +std::array decoded1 {}; +std::array decoded2 {}; + +// Decode with TChunk == uint16_t +etl::manchester::decode(encoded, decoded1); + +// Decode with TChunk == uint64_t +etl::manchester::decode(encoded, decoded2); +``` + +### Validation Functions + +#### Single value + +```cpp +template +static ETL_CONSTEXPR14 bool is_valid(TChunk encoded) +``` + +Validates that a single value contains valid Manchester encoded data. + +**Parameters:** + +- `encoded`: The encoded value to validate + +**Returns:** + +- `true` if the value contains valid Manchester encoded data, `false` otherwise + +**Example:** + +```cpp +bool valid = etl::manchester::is_valid(0x5A5A); +``` + +#### Range + +```cpp +static ETL_CONSTEXPR14 bool is_valid(etl::span encoded) +``` + +Validates that a range contains valid Manchester encoded data. + +**Parameters:** + +- `encoded`: The range of encoded data to validate + +**Returns:** + +- `true` if all data is valid Manchester encoding, `false` otherwise + +**Example:** + +```cpp +std::array encoded_data = {/* ... */}; +bool valid = etl::manchester::is_valid(encoded_data); +``` + +## Supported Types + +### 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) + +### 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) diff --git a/docs/ranges.md b/docs/ranges.md new file mode 100644 index 00000000..9e6f55ee --- /dev/null +++ b/docs/ranges.md @@ -0,0 +1,328 @@ +# ETL C++17 Ranges Implementation + +## Overview + +The Embedded Template Library provides a C++17-compatible implementation of ranges, inspired by the C++20 ranges library. This implementation enables range-based algorithms and views for embedded and resource-constrained environments where full C++20 support may not be available. + +## Features + +- **Ranges**: Provides range types and iterator wrappers for composing operations over sequences. +- **Views**: Includes lightweight, composable views such as `filter_view`, `transform_view`, and `subrange`. +- **Algorithms**: Supports range-based algorithms compatible with ETL containers and standard containers. +- **Compatibility**: Designed for C++17, with minimal dependencies and no reliance on C++20 features. + +## Getting Started + +Include the main header in your project: + +```cpp +#include +``` + +### Example Usage + +#### Using Ranges + +```cpp +#include +#include +#include + +... + + etl::vector data = {6, 1, 3, 3, 2}; + etl::ranges::sort(data); + etl::ranges::for_each(data, [](const int& i){etl::print(" {}", i);}); +``` + +Output: +```text + 1 2 3 3 6 +``` + +#### Using Views + +```cpp +#include +#include +#include + +... + + etl::vector data = {1, 2, 3, 4, 5}; + auto even = [](int v) { return v % 2 == 0; }; + auto filtered = etl::ranges::filter_view(data, even); + etl::ranges::for_each(filtered, [](const int& i){etl::print(" {}", i);}); +``` + +Output: +```text + 2 4 +``` + +#### Transforming Elements + +```cpp +#include +#include +#include + +... + + etl::vector data = {1, 2, 3, 4, 5}; + auto squared = etl::ranges::transform_view(data, [](int v) { return v * v; }); + etl::ranges::for_each(squared, [](const int& i){etl::print(" {}", i);}); +``` + +Output: +```text + 1 4 9 16 25 +``` + +#### Composition + +Views can be composed using the pipe (`|`) operator, allowing you to chain multiple transformations in a readable, left-to-right style: + +```cpp +#include +#include +#include + +namespace views = etl::ranges::views; + +... + + etl::vector data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + + auto result = data + | views::filter([](const int& v) { return v % 2 == 0; }) + | views::transform([](const int& v) { return v * v; }); + + etl::ranges::for_each(result, [](const int& i){ etl::print(" {}", i); }); +``` + +Output: +```text + 4 16 36 64 100 +``` + +This first filters the even numbers and then squares them. Each `|` passes the result of the previous stage as input to the next view adaptor. + +## Supported Views + +All views are in the `etl::ranges` namespace. Corresponding range adaptor objects are available in `etl::ranges::views`. + +### Range Factories + +| View | `views::` adaptor | Description | +|---|---|---| +| `empty_view` | `views::empty` | A view with no elements. | +| `single_view` | `views::single` | A view containing exactly one element. | +| `iota_view` | `views::iota` | A view of sequentially increasing values. | +| `repeat_view` | `views::repeat` | A view that repeats a value a given number of times. | + +### Range Adaptors + +| View | `views::` adaptor | Description | +|---|---|---| +| `ref_view` | `views::ref` | A non-owning view that wraps a reference to a range. | +| `owning_view` | `views::owning` | A view that takes ownership of a range via move. | +| — | `views::all` | Returns the range itself (if already a view), a `ref_view`, or an `owning_view`. | +| `filter_view` | `views::filter` | Filters elements based on a predicate. | +| `transform_view` | `views::transform` | Applies a transformation to each element. | +| `as_rvalue_view` | `views::as_rvalue` | Casts each element to an rvalue reference. | +| `as_const_view` | `views::as_const` | Provides a const view of the elements. | +| `cache_latest_view` | `views::cache_latest` | Caches the most recently accessed element (avoids recomputation). | +| `reverse_view` | `views::reverse` | Reverses the order of elements. | +| `drop_view` | `views::drop` | Skips the first *n* elements. | +| `drop_while_view` | `views::drop_while` | Skips leading elements while a predicate is true. | +| `take_view` | `views::take` | Takes the first *n* elements. | +| `take_while_view` | `views::take_while` | Takes leading elements while a predicate is true. | +| `join_view` | `views::join` | Flattens a range of ranges into a single range. | +| `join_with_view` | `views::join_with` | Flattens a range of ranges, inserting a delimiter between each. | +| `split_view` | `views::split` | Splits a range into subranges around a delimiter pattern. | +| `lazy_split_view` | `views::lazy_split` | Lazily splits a range by a pattern (inner ranges discovered on iteration). | +| — | `views::counted` | Creates a view of *n* elements starting from an iterator. | +| `concat_view` | `views::concat` | Concatenates multiple ranges into a single view. | +| `zip_view` | `views::zip` | Zips multiple ranges into a view of tuples (length of shortest range). | +| `zip_transform_view` | `views::zip_transform` | Zips multiple ranges and applies a function to each tuple of elements. | +| `common_view` | `views::common` | Adapts a view so that its iterator and sentinel types are the same. | +| `enumerate_view` | `views::enumerate` | Pairs each element with its index, producing tuples of (index, value). | +| `elements_view` | `views::elements` | Extracts the *N*-th element from each tuple-like value. | +| `keys_view` | `views::keys` | Alias for `elements_view` with *N*=0 (extracts first element of pairs/tuples). | +| `values_view` | `views::values` | Alias for `elements_view` with *N*=1 (extracts second element of pairs/tuples). | +| `adjacent_view` | `views::adjacent` | Produces a view of tuples of *N* adjacent elements (sliding window of tuples). | +| — | `views::pairwise` | Alias for `views::adjacent<2>`. | +| `adjacent_transform_view` | `views::adjacent_transform` | Applies a function to each group of *N* adjacent elements. | +| — | `views::pairwise_transform` | Alias for `views::adjacent_transform<2>`. | +| `chunk_view` | `views::chunk` | Splits a range into non-overlapping chunks of a given size. | +| `slide_view` | `views::slide` | Produces overlapping subranges (sliding windows) of a given size. | +| `chunk_by_view` | `views::chunk_by` | Splits a range into subranges between adjacent elements where a predicate is false. | +| `stride_view` | `views::stride` | Yields every *N*-th element from the underlying range. | +| `cartesian_product_view` | `views::cartesian_product` | Produces the Cartesian product of multiple ranges as a view of tuples. | +| `to_input_view` | `views::to_input` | Downgrades iterator category to input iterator while preserving elements and order. | +| `subrange` | — | Represents a sub-range defined by an iterator–sentinel pair. | + +All views support range-based for-loop iteration and can be composed with the pipe (`|`) operator. + +## Supported Algorithms + +All algorithms are callable objects in the `etl::ranges` namespace. Each supports both an iterator-pair overload and a range overload (where applicable), and most accept optional projection and comparator arguments. + +### Non-modifying Sequence Operations + +| Algorithm | Description | +|---|---| +| `for_each` | Applies a function to each element in a range. | +| `for_each_n` | Applies a function to the first *n* elements. | +| `find` | Finds the first element equal to a value. | +| `find_if` | Finds the first element satisfying a predicate. | +| `find_if_not` | Finds the first element not satisfying a predicate. | +| `find_end` | Finds the last occurrence of a subsequence. | +| `find_first_of` | Finds the first element matching any in a second range. | +| `adjacent_find` | Finds the first pair of adjacent equal elements. | +| `count` | Counts elements equal to a value. | +| `count_if` | Counts elements satisfying a predicate. | +| `all_of` | Checks if all elements satisfy a predicate. | +| `any_of` | Checks if any element satisfies a predicate. | +| `none_of` | Checks if no elements satisfy a predicate. | +| `mismatch` | Finds the first position where two ranges differ. | +| `equal` | Checks if two ranges are equal. | +| `is_permutation` | Checks if one range is a permutation of another. | +| `search` | Searches for the first occurrence of a subsequence. | +| `search_n` | Searches for *n* consecutive copies of a value. | +| `starts_with` | Checks if a range starts with another range. | +| `ends_with` | Checks if a range ends with another range. | +| `lexicographical_compare` | Compares two ranges lexicographically. | + +### Fold Operations + +| Algorithm | Description | +|---|---| +| `fold_left` | Left-folds elements with a binary operation. | +| `fold_left_with_iter` | Left-folds, returning both the result and an iterator. | +| `fold_left_first` | Left-folds using the first element as the initial value. | +| `fold_left_first_with_iter` | Like `fold_left_first`, also returning an iterator. | +| `fold_right` | Right-folds elements with a binary operation. | +| `fold_right_last` | Right-folds using the last element as the initial value. | + +### Modifying Sequence Operations + +| Algorithm | Description | +|---|---| +| `copy` | Copies elements to a destination range. | +| `copy_n` | Copies *n* elements to a destination range. | +| `copy_if` | Copies elements satisfying a predicate. | +| `copy_backward` | Copies elements backwards to a destination range. | +| `move` | Moves elements to a destination range. | +| `move_backward` | Moves elements backwards to a destination range. | +| `swap_ranges` | Swaps elements between two ranges. | +| `replace` | Replaces elements equal to a value. | +| `replace_if` | Replaces elements satisfying a predicate. | +| `replace_copy` | Copies, replacing elements equal to a value. | +| `replace_copy_if` | Copies, replacing elements satisfying a predicate. | +| `remove` | Removes elements equal to a value. | +| `remove_if` | Removes elements satisfying a predicate. | +| `remove_copy` | Copies, omitting elements equal to a value. | +| `fill` | Fills a range with a value. | +| `fill_n` | Fills *n* elements with a value. | +| `generate` | Assigns each element the result of a generator function. | +| `generate_n` | Assigns *n* elements the result of a generator function. | +| `iota` | Fills a range with sequentially increasing values. | +| `unique` | Removes consecutive duplicate elements. | +| `unique_copy` | Copies, removing consecutive duplicates. | +| `transform` | Applies a transformation to each element. | +| `reverse` | Reverses the order of elements. | +| `reverse_copy` | Copies elements in reverse order. | +| `rotate` | Rotates elements in a range. | +| `rotate_copy` | Copies elements with rotation. | +| `shift_left` | Shifts elements to the left. | +| `shift_right` | Shifts elements to the right. | +| `shuffle` | Randomly reorders elements. | +| `sample` | Selects *n* random elements from a range. | + +### Sorting Operations + +| Algorithm | Description | +|---|---| +| `sort` | Sorts elements in a range. | +| `stable_sort` | Sorts elements preserving relative order of equivalent elements. | +| `partial_sort` | Partially sorts a range so that the first *n* elements are sorted. | +| `partial_sort_copy` | Copies and partially sorts elements. | +| `nth_element` | Partially sorts so that the *n*-th element is in its sorted position. | +| `is_sorted` | Checks if a range is sorted. | +| `is_sorted_until` | Finds the first unsorted element. | + +### Partitioning Operations + +| Algorithm | Description | +|---|---| +| `partition` | Partitions elements by a predicate. | +| `stable_partition` | Partitions elements, preserving relative order. | +| `is_partitioned` | Checks if a range is partitioned. | +| `partition_copy` | Copies elements into two ranges based on a predicate. | +| `partition_point` | Finds the partition point. | + +### Binary Search (on sorted ranges) + +| Algorithm | Description | +|---|---| +| `lower_bound` | Finds the first element not less than a value. | +| `upper_bound` | Finds the first element greater than a value. | +| `equal_range` | Returns the range of elements equal to a value. | +| `binary_search` | Checks if a sorted range contains a value. | + +### Set Operations (on sorted ranges) + +| Algorithm | Description | +|---|---| +| `includes` | Checks if one sorted range includes another. | +| `merge` | Merges two sorted ranges. | +| `inplace_merge` | Merges two consecutive sorted sub-ranges in place. | +| `set_union` | Computes the union of two sorted ranges. | +| `set_intersection` | Computes the intersection of two sorted ranges. | +| `set_difference` | Computes the difference of two sorted ranges. | +| `set_symmetric_difference` | Computes the symmetric difference of two sorted ranges. | + +### Heap Operations + +| Algorithm | Description | +|---|---| +| `make_heap` | Creates a heap from a range. | +| `push_heap` | Pushes an element onto a heap. | +| `pop_heap` | Pops the top element from a heap. | +| `sort_heap` | Sorts a heap into a sorted range. | +| `is_heap` | Checks if a range is a heap. | +| `is_heap_until` | Finds the first element that breaks the heap property. | + +### Min/Max Operations + +| Algorithm | Description | +|---|---| +| `min` | Returns the smaller of two values or the smallest in an initializer list. | +| `min_element` | Finds the smallest element in a range. | +| `max` | Returns the larger of two values or the largest in an initializer list. | +| `max_element` | Finds the largest element in a range. | +| `minmax` | Returns the smaller and larger of two values. | +| `minmax_element` | Finds both the smallest and largest elements in a range. | +| `clamp` | Clamps a value between a minimum and maximum. | + +### Permutation Operations + +| Algorithm | Description | +|---|---| +| `next_permutation` | Generates the next lexicographic permutation. | +| `prev_permutation` | Generates the previous lexicographic permutation. | + + +## Reference + +For reference to the STD implementation, see also: + +- Algorithms: https://en.cppreference.com/w/cpp/algorithm.html +- Ranges/Views: https://en.cppreference.com/w/cpp/ranges.html + +## Limitations + +- Not all C++20 range features are available due to limitation to C++17. Especially C++20 concepts are not used. +- Designed for ETL containers but can work with standard containers if compatible with ETL's iterator requirements. diff --git a/docs/source-formatting.md b/docs/source-formatting.md new file mode 100644 index 00000000..37c18c6e --- /dev/null +++ b/docs/source-formatting.md @@ -0,0 +1,100 @@ +# Source Formatting + +This project uses **clang-format** (version 18) to enforce a consistent coding style +for C and C++ source files. For convenience, **treefmt** is also configured as a +single-command wrapper that discovers and formats every file in the tree. + +--- + +## clang-format + +### Configuration file + +The formatting rules live in [`.clang-format`](../.clang-format) at the repository +root. The style is based on **LLVM**. + +See the `.clang-format` file itself for the complete list. + +### Version requirement + +clang-format **18** is required. +The helper script [`scripts/clang-format-wrapper`](../scripts/clang-format-wrapper) +automatically resolves the correct binary: it first looks for `clang-format-18` on +`PATH`, then falls back to `clang-format` and verifies that its major version is 18. +All other tooling in the repo calls this wrapper instead of `clang-format` directly. + +### Running clang-format manually + +Format every tracked source file in the repository: + +```bash +git ls-files -z \ + '*.c' '*.cc' '*.cpp' \ + '*.h' '*.hh' '*.hpp' \ + ':(exclude)include/etl/generators/*' \ + ':(exclude)include/etl/private/*_cpp03.h' | xargs -0 scripts/clang-format-wrapper -i --verbose --style=file +``` + +You can also format individual files directly: + +```bash +scripts/clang-format-wrapper -i --style=file path/to/file.cpp +``` + +--- + +## treefmt + +[treefmt](https://treefmt.com) is a language-agnostic source-tree formatter. +It reads a single configuration file and dispatches each file to the appropriate +formatter. In this project, it delegates all C/C++ formatting to the same +`clang-format-wrapper` described above. + +In comparison to calling clang-format directly, it brings a significant speedup. + +### Configuration file + +The configuration lives in [`.treefmt.toml`](../.treefmt.toml) at the repository root. + +### Installing treefmt + +treefmt is a standalone Go binary. Install it with any of: + +```bash +# Using the official install script +curl -fsSL https://raw.githubusercontent.com/numtide/treefmt/main/install.sh | bash + +# Or via Homebrew +brew install treefmt + +# Or via Nix +nix profile install nixpkgs#treefmt2 +``` + +See the [treefmt documentation](https://treefmt.com) for more options. + +### Running treefmt + +From the repository root: + +```bash +# Format everything +treefmt + +# Check formatting without modifying files (useful in CI) +treefmt --fail-on-change +``` + +--- + +## Excluded paths + +`.treefmt.toml` excludes generated files under +`include/etl/generators/`. Do **not** format those files manually via clang-format or treefmt. + +## Pre-commit + +Before submitting a PR / contribution, run `treefmt --fail-on-change` to catch +unformatted code before merge. + +Alternatively, a plain `treefmt` automatically fixes any issues. \ No newline at end of file diff --git a/examples/ArmTimerCallbacks - C++/RTE/Device/STM32F401RETx/system_stm32f4xx.c b/examples/ArmTimerCallbacks - C++/RTE/Device/STM32F401RETx/system_stm32f4xx.c index bca0633d..62183db5 100644 --- a/examples/ArmTimerCallbacks - C++/RTE/Device/STM32F401RETx/system_stm32f4xx.c +++ b/examples/ArmTimerCallbacks - C++/RTE/Device/STM32F401RETx/system_stm32f4xx.c @@ -1,176 +1,179 @@ /** - ****************************************************************************** - * @file system_stm32f4xx.c - * @author MCD Application Team - * @version V2.6.0 - * @date 04-November-2016 - * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. - * - * This file provides two functions and one global variable to be called from - * user application: - * - SystemInit(): This function is called at startup just after reset and - * before branch to main program. This call is made inside - * the "startup_stm32f4xx.s" file. - * - * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used - * by the user application to setup the SysTick - * timer or configure other parameters. - * - * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must - * be called whenever the core clock is changed - * during program execution. - * - * - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ + ****************************************************************************** + * @file system_stm32f4xx.c + * @author MCD Application Team + * @version V2.6.0 + * @date 04-November-2016 + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be + *used by the user application to setup the SysTick timer or configure other + *parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without + *modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *notice, this list of conditions and the following disclaimer in the + *documentation and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + *LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + *INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + *CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + *ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ /** @addtogroup CMSIS - * @{ - */ + * @{ + */ /** @addtogroup stm32f4xx_system - * @{ - */ - -/** @addtogroup STM32F4xx_System_Private_Includes - * @{ - */ + * @{ + */ +/** @addtogroup STM32F4xx_System_Private_Includes + * @{ + */ #include "stm32f4xx.h" -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ +#if !defined(HSE_VALUE) + #define HSE_VALUE \ + ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz \ + */ +#endif /* HSE_VALUE */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ +#if !defined(HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ /** - * @} - */ + * @} + */ /** @addtogroup STM32F4xx_System_Private_TypesDefinitions - * @{ - */ + * @{ + */ /** - * @} - */ + * @} + */ /** @addtogroup STM32F4xx_System_Private_Defines - * @{ - */ + * @{ + */ /************************* Miscellaneous Configuration ************************/ -/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */ -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ - || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) +/*!< Uncomment the following line if you need to use external SRAM or SDRAM as + * data memory */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) \ + || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) /* #define DATA_IN_ExtSRAM */ -#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\ - STM32F412Zx || STM32F412Vx */ - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || \ + STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) \ + || defined(STM32F479xx) /* #define DATA_IN_ExtSDRAM */ -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\ - STM32F479xx */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || \ + STM32F446xx || STM32F469xx || STM32F479xx */ /*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */ /* #define VECT_TAB_SRAM */ -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET \ + 0x00 /*!< Vector Table base offset field. \ + This value must be a multiple of 0x200. */ /******************************************************************************/ /** - * @} - */ + * @} + */ /** @addtogroup STM32F4xx_System_Private_Macros - * @{ - */ + * @{ + */ /** - * @} - */ + * @} + */ /** @addtogroup STM32F4xx_System_Private_Variables - * @{ - */ - /* This variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetHCLKFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - Note: If you use this function to configure the system clock; then there - is no need to call the 2 first functions listed above, since SystemCoreClock - variable is updated automatically. - */ -uint32_t SystemCoreClock = 16000000; + * @{ + */ +/* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock + frequency Note: If you use this function to configure the system clock; then + there is no need to call the 2 first functions listed above, since + SystemCoreClock variable is updated automatically. +*/ +uint32_t SystemCoreClock = 16000000; const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; /** - * @} - */ + * @} + */ /** @addtogroup STM32F4xx_System_Private_FunctionPrototypes - * @{ - */ + * @{ + */ -#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) - static void SystemInit_ExtMemCtl(void); +#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM) +static void SystemInit_ExtMemCtl(void); #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ /** - * @} - */ + * @} + */ /** @addtogroup STM32F4xx_System_Private_Functions - * @{ - */ + * @{ + */ /** - * @brief Setup the microcontroller system - * Initialize the FPU setting, vector table location and External memory - * configuration. - * @param None - * @retval None - */ + * @brief Setup the microcontroller system + * Initialize the FPU setting, vector table location and External memory + * configuration. + * @param None + * @retval None + */ void SystemInit(void) { - /* FPU settings ------------------------------------------------------------*/ - #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ - #endif +/* FPU settings ------------------------------------------------------------*/ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10 and CP11 Full Access */ +#endif /* Reset the RCC clock configuration to the default reset state ------------*/ /* Set HSION bit */ RCC->CR |= (uint32_t)0x00000001; @@ -190,8 +193,8 @@ void SystemInit(void) /* Disable all interrupts */ RCC->CIR = 0x00000000; -#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) - SystemInit_ExtMemCtl(); +#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM) + SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ /* Configure the Vector Table location add offset address ------------------*/ @@ -203,64 +206,62 @@ void SystemInit(void) } /** - * @brief Update SystemCoreClock variable according to Clock Register Values. - * The SystemCoreClock variable contains the core clock (HCLK), it can - * be used by the user application to setup the SysTick timer or configure - * other parameters. - * - * @note Each time the core clock (HCLK) changes, this function must be called - * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value - * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value - * depends on the application requirements), user has to ensure that HSE_VALUE - * is same as the real frequency of the crystal used. Otherwise, this function - * may have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * - * @param None - * @retval None - */ + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or + * configure other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any + * configuration based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the + * HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the + * HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the + * HSE_VALUE(**) or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file + * (default value 16 MHz) but the real value may vary depending on the + * variations in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file + * (its value depends on the application requirements), user has to ensure that + * HSE_VALUE is same as the real frequency of the crystal used. Otherwise, this + * function may have wrong result. + * + * - The result of this function could be not correct when using + * fractional value for HSE crystal. + * + * @param None + * @retval None + */ void SystemCoreClockUpdate(void) { uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; - + /* Get SYSCLK source -------------------------------------------------------*/ tmp = RCC->CFGR & RCC_CFGR_SWS; switch (tmp) { - case 0x00: /* HSI used as system clock source */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04: /* HSE used as system clock source */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08: /* PLL used as system clock source */ + case 0x00: /* HSI used as system clock source */ SystemCoreClock = HSI_VALUE; break; + case 0x04: /* HSE used as system clock source */ SystemCoreClock = HSE_VALUE; break; + case 0x08: /* PLL used as system clock source */ /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N SYSCLK = PLL_VCO / PLL_P - */ + */ pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; - pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; - + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + if (pllsource != 0) { /* HSE used as PLL clock source */ @@ -272,12 +273,10 @@ void SystemCoreClockUpdate(void) pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); } - pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; - SystemCoreClock = pllvco/pllp; - break; - default: - SystemCoreClock = HSI_VALUE; + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >> 16) + 1) * 2; + SystemCoreClock = pllvco / pllp; break; + default: SystemCoreClock = HSI_VALUE; break; } /* Compute HCLK frequency --------------------------------------------------*/ /* Get HCLK prescaler */ @@ -286,478 +285,486 @@ void SystemCoreClockUpdate(void) SystemCoreClock >>= tmp; } -#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM) -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) +#if defined(DATA_IN_ExtSRAM) && defined(DATA_IN_ExtSDRAM) + #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) /** - * @brief Setup the external memory controller. - * Called in startup_stm32f4xx.s before jump to main. - * This function configures the external memories (SRAM/SDRAM) - * This SRAM/SDRAM will be used as program data memory (including heap and stack). - * @param None - * @retval None - */ + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external memories (SRAM/SDRAM) + * This SRAM/SDRAM will be used as program data memory (including heap + * and stack). + * @param None + * @retval None + */ void SystemInit_ExtMemCtl(void) { __IO uint32_t tmp = 0x00; - register uint32_t tmpreg = 0, timeout = 0xFFFF; + register uint32_t tmpreg = 0, timeout = 0xFFFF; register __IO uint32_t index; - /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */ + /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock + */ RCC->AHB1ENR |= 0x000001F8; /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); - + /* Connect PDx pins to FMC Alternate function */ - GPIOD->AFR[0] = 0x00CCC0CC; - GPIOD->AFR[1] = 0xCCCCCCCC; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xAAAA0A8A; - /* Configure PDx pins speed to 100 MHz */ + GPIOD->AFR[0] = 0x00CCC0CC; + GPIOD->AFR[1] = 0xCCCCCCCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xAAAA0A8A; + /* Configure PDx pins speed to 100 MHz */ GPIOD->OSPEEDR = 0xFFFF0FCF; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; /* Connect PEx pins to FMC Alternate function */ - GPIOE->AFR[0] = 0xC00CC0CC; - GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xAAAA828A; - /* Configure PEx pins speed to 100 MHz */ + GPIOE->AFR[0] = 0xC00CC0CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA828A; + /* Configure PEx pins speed to 100 MHz */ GPIOE->OSPEEDR = 0xFFFFC3CF; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; - + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + /* Connect PFx pins to FMC Alternate function */ - GPIOF->AFR[0] = 0xCCCCCCCC; - GPIOF->AFR[1] = 0xCCCCCCCC; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xAA800AAA; - /* Configure PFx pins speed to 50 MHz */ + GPIOF->AFR[0] = 0xCCCCCCCC; + GPIOF->AFR[1] = 0xCCCCCCCC; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA800AAA; + /* Configure PFx pins speed to 50 MHz */ GPIOF->OSPEEDR = 0xAA800AAA; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; /* Connect PGx pins to FMC Alternate function */ - GPIOG->AFR[0] = 0xCCCCCCCC; - GPIOG->AFR[1] = 0xCCCCCCCC; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0xAAAAAAAA; - /* Configure PGx pins speed to 50 MHz */ + GPIOG->AFR[0] = 0xCCCCCCCC; + GPIOG->AFR[1] = 0xCCCCCCCC; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0xAAAAAAAA; + /* Configure PGx pins speed to 50 MHz */ GPIOG->OSPEEDR = 0xAAAAAAAA; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; - + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + /* Connect PHx pins to FMC Alternate function */ - GPIOH->AFR[0] = 0x00C0CC00; - GPIOH->AFR[1] = 0xCCCCCCCC; - /* Configure PHx pins in Alternate function mode */ - GPIOH->MODER = 0xAAAA08A0; - /* Configure PHx pins speed to 50 MHz */ + GPIOH->AFR[0] = 0x00C0CC00; + GPIOH->AFR[1] = 0xCCCCCCCC; + /* Configure PHx pins in Alternate function mode */ + GPIOH->MODER = 0xAAAA08A0; + /* Configure PHx pins speed to 50 MHz */ GPIOH->OSPEEDR = 0xAAAA08A0; - /* Configure PHx pins Output type to push-pull */ - GPIOH->OTYPER = 0x00000000; - /* No pull-up, pull-down for PHx pins */ - GPIOH->PUPDR = 0x00000000; - + /* Configure PHx pins Output type to push-pull */ + GPIOH->OTYPER = 0x00000000; + /* No pull-up, pull-down for PHx pins */ + GPIOH->PUPDR = 0x00000000; + /* Connect PIx pins to FMC Alternate function */ - GPIOI->AFR[0] = 0xCCCCCCCC; - GPIOI->AFR[1] = 0x00000CC0; - /* Configure PIx pins in Alternate function mode */ - GPIOI->MODER = 0x0028AAAA; - /* Configure PIx pins speed to 50 MHz */ + GPIOI->AFR[0] = 0xCCCCCCCC; + GPIOI->AFR[1] = 0x00000CC0; + /* Configure PIx pins in Alternate function mode */ + GPIOI->MODER = 0x0028AAAA; + /* Configure PIx pins speed to 50 MHz */ GPIOI->OSPEEDR = 0x0028AAAA; - /* Configure PIx pins Output type to push-pull */ - GPIOI->OTYPER = 0x00000000; - /* No pull-up, pull-down for PIx pins */ - GPIOI->PUPDR = 0x00000000; - -/*-- FMC Configuration -------------------------------------------------------*/ + /* Configure PIx pins Output type to push-pull */ + GPIOI->OTYPER = 0x00000000; + /* No pull-up, pull-down for PIx pins */ + GPIOI->PUPDR = 0x00000000; + + /*-- FMC Configuration + * -------------------------------------------------------*/ /* Enable the FMC interface clock */ RCC->AHB3ENR |= 0x00000001; /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); FMC_Bank5_6->SDCR[0] = 0x000019E4; - FMC_Bank5_6->SDTR[0] = 0x01115351; - + FMC_Bank5_6->SDTR[0] = 0x01115351; + /* SDRAM initialization sequence */ /* Clock enable command */ - FMC_Bank5_6->SDCMR = 0x00000011; - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - while((tmpreg != 0) && (timeout-- > 0)) + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + while ((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } /* Delay */ - for (index = 0; index<1000; index++); - + for (index = 0; index < 1000; index++); + /* PALL command */ - FMC_Bank5_6->SDCMR = 0x00000012; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) + FMC_Bank5_6->SDCMR = 0x00000012; + timeout = 0xFFFF; + while ((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } - + /* Auto refresh command */ FMC_Bank5_6->SDCMR = 0x00000073; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) + timeout = 0xFFFF; + while ((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } - + /* MRD register program */ FMC_Bank5_6->SDCMR = 0x00046014; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) + timeout = 0xFFFF; + while ((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + /* Set refresh count */ - tmpreg = FMC_Bank5_6->SDRTR; - FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); - + tmpreg = FMC_Bank5_6->SDRTR; + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C << 1)); + /* Disable write protection */ - tmpreg = FMC_Bank5_6->SDCR[0]; + tmpreg = FMC_Bank5_6->SDCR[0]; FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) + #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) /* Configure and enable Bank1_SRAM2 */ FMC_Bank1->BTCR[2] = 0x00001011; FMC_Bank1->BTCR[3] = 0x00000201; FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ -#if defined(STM32F469xx) || defined(STM32F479xx) + #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ + #if defined(STM32F469xx) || defined(STM32F479xx) /* Configure and enable Bank1_SRAM2 */ FMC_Bank1->BTCR[2] = 0x00001091; FMC_Bank1->BTCR[3] = 0x00110212; FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F469xx || STM32F479xx */ + #endif /* STM32F469xx || STM32F479xx */ - (void)(tmp); + (void)(tmp); } -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ -#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) + #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || \ + STM32F469xx || STM32F479xx */ +#elif defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM) /** - * @brief Setup the external memory controller. - * Called in startup_stm32f4xx.s before jump to main. - * This function configures the external memories (SRAM/SDRAM) - * This SRAM/SDRAM will be used as program data memory (including heap and stack). - * @param None - * @retval None - */ + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external memories (SRAM/SDRAM) + * This SRAM/SDRAM will be used as program data memory (including heap + * and stack). + * @param None + * @retval None + */ void SystemInit_ExtMemCtl(void) { __IO uint32_t tmp = 0x00; -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) -#if defined (DATA_IN_ExtSDRAM) - register uint32_t tmpreg = 0, timeout = 0xFFFF; + #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) \ + || defined(STM32F479xx) + #if defined(DATA_IN_ExtSDRAM) + register uint32_t tmpreg = 0, timeout = 0xFFFF; register __IO uint32_t index; -#if defined(STM32F446xx) + #if defined(STM32F446xx) /* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface clock */ RCC->AHB1ENR |= 0x0000007D; -#else - /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface + #else + /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */ RCC->AHB1ENR |= 0x000001F8; -#endif /* STM32F446xx */ + #endif /* STM32F446xx */ /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); - -#if defined(STM32F446xx) + + #if defined(STM32F446xx) /* Connect PAx pins to FMC Alternate function */ - GPIOA->AFR[0] |= 0xC0000000; - GPIOA->AFR[1] |= 0x00000000; + GPIOA->AFR[0] |= 0xC0000000; + GPIOA->AFR[1] |= 0x00000000; /* Configure PDx pins in Alternate function mode */ - GPIOA->MODER |= 0x00008000; + GPIOA->MODER |= 0x00008000; /* Configure PDx pins speed to 50 MHz */ GPIOA->OSPEEDR |= 0x00008000; /* Configure PDx pins Output type to push-pull */ - GPIOA->OTYPER |= 0x00000000; + GPIOA->OTYPER |= 0x00000000; /* No pull-up, pull-down for PDx pins */ - GPIOA->PUPDR |= 0x00000000; + GPIOA->PUPDR |= 0x00000000; /* Connect PCx pins to FMC Alternate function */ - GPIOC->AFR[0] |= 0x00CC0000; - GPIOC->AFR[1] |= 0x00000000; + GPIOC->AFR[0] |= 0x00CC0000; + GPIOC->AFR[1] |= 0x00000000; /* Configure PDx pins in Alternate function mode */ - GPIOC->MODER |= 0x00000A00; + GPIOC->MODER |= 0x00000A00; /* Configure PDx pins speed to 50 MHz */ GPIOC->OSPEEDR |= 0x00000A00; /* Configure PDx pins Output type to push-pull */ - GPIOC->OTYPER |= 0x00000000; + GPIOC->OTYPER |= 0x00000000; /* No pull-up, pull-down for PDx pins */ - GPIOC->PUPDR |= 0x00000000; -#endif /* STM32F446xx */ + GPIOC->PUPDR |= 0x00000000; + #endif /* STM32F446xx */ /* Connect PDx pins to FMC Alternate function */ - GPIOD->AFR[0] = 0x000000CC; - GPIOD->AFR[1] = 0xCC000CCC; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xA02A000A; - /* Configure PDx pins speed to 50 MHz */ + GPIOD->AFR[0] = 0x000000CC; + GPIOD->AFR[1] = 0xCC000CCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xA02A000A; + /* Configure PDx pins speed to 50 MHz */ GPIOD->OSPEEDR = 0xA02A000A; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; /* Connect PEx pins to FMC Alternate function */ - GPIOE->AFR[0] = 0xC00000CC; - GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xAAAA800A; - /* Configure PEx pins speed to 50 MHz */ + GPIOE->AFR[0] = 0xC00000CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA800A; + /* Configure PEx pins speed to 50 MHz */ GPIOE->OSPEEDR = 0xAAAA800A; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; /* Connect PFx pins to FMC Alternate function */ - GPIOF->AFR[0] = 0xCCCCCCCC; - GPIOF->AFR[1] = 0xCCCCCCCC; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xAA800AAA; - /* Configure PFx pins speed to 50 MHz */ + GPIOF->AFR[0] = 0xCCCCCCCC; + GPIOF->AFR[1] = 0xCCCCCCCC; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA800AAA; + /* Configure PFx pins speed to 50 MHz */ GPIOF->OSPEEDR = 0xAA800AAA; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; /* Connect PGx pins to FMC Alternate function */ - GPIOG->AFR[0] = 0xCCCCCCCC; - GPIOG->AFR[1] = 0xCCCCCCCC; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0xAAAAAAAA; - /* Configure PGx pins speed to 50 MHz */ + GPIOG->AFR[0] = 0xCCCCCCCC; + GPIOG->AFR[1] = 0xCCCCCCCC; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0xAAAAAAAA; + /* Configure PGx pins speed to 50 MHz */ GPIOG->OSPEEDR = 0xAAAAAAAA; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) + #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) /* Connect PHx pins to FMC Alternate function */ - GPIOH->AFR[0] = 0x00C0CC00; - GPIOH->AFR[1] = 0xCCCCCCCC; - /* Configure PHx pins in Alternate function mode */ - GPIOH->MODER = 0xAAAA08A0; - /* Configure PHx pins speed to 50 MHz */ + GPIOH->AFR[0] = 0x00C0CC00; + GPIOH->AFR[1] = 0xCCCCCCCC; + /* Configure PHx pins in Alternate function mode */ + GPIOH->MODER = 0xAAAA08A0; + /* Configure PHx pins speed to 50 MHz */ GPIOH->OSPEEDR = 0xAAAA08A0; - /* Configure PHx pins Output type to push-pull */ - GPIOH->OTYPER = 0x00000000; - /* No pull-up, pull-down for PHx pins */ - GPIOH->PUPDR = 0x00000000; - + /* Configure PHx pins Output type to push-pull */ + GPIOH->OTYPER = 0x00000000; + /* No pull-up, pull-down for PHx pins */ + GPIOH->PUPDR = 0x00000000; + /* Connect PIx pins to FMC Alternate function */ - GPIOI->AFR[0] = 0xCCCCCCCC; - GPIOI->AFR[1] = 0x00000CC0; - /* Configure PIx pins in Alternate function mode */ - GPIOI->MODER = 0x0028AAAA; - /* Configure PIx pins speed to 50 MHz */ + GPIOI->AFR[0] = 0xCCCCCCCC; + GPIOI->AFR[1] = 0x00000CC0; + /* Configure PIx pins in Alternate function mode */ + GPIOI->MODER = 0x0028AAAA; + /* Configure PIx pins speed to 50 MHz */ GPIOI->OSPEEDR = 0x0028AAAA; - /* Configure PIx pins Output type to push-pull */ - GPIOI->OTYPER = 0x00000000; - /* No pull-up, pull-down for PIx pins */ - GPIOI->PUPDR = 0x00000000; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ - -/*-- FMC Configuration -------------------------------------------------------*/ + /* Configure PIx pins Output type to push-pull */ + GPIOI->OTYPER = 0x00000000; + /* No pull-up, pull-down for PIx pins */ + GPIOI->PUPDR = 0x00000000; + #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || \ + STM32F469xx || STM32F479xx */ + + /*-- FMC Configuration + * -------------------------------------------------------*/ /* Enable the FMC interface clock */ RCC->AHB3ENR |= 0x00000001; /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); - /* Configure and enable SDRAM bank1 */ -#if defined(STM32F446xx) + /* Configure and enable SDRAM bank1 */ + #if defined(STM32F446xx) FMC_Bank5_6->SDCR[0] = 0x00001954; -#else + #else FMC_Bank5_6->SDCR[0] = 0x000019E4; -#endif /* STM32F446xx */ - FMC_Bank5_6->SDTR[0] = 0x01115351; - + #endif /* STM32F446xx */ + FMC_Bank5_6->SDTR[0] = 0x01115351; + /* SDRAM initialization sequence */ /* Clock enable command */ - FMC_Bank5_6->SDCMR = 0x00000011; - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - while((tmpreg != 0) && (timeout-- > 0)) + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + while ((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } /* Delay */ - for (index = 0; index<1000; index++); - + for (index = 0; index < 1000; index++); + /* PALL command */ - FMC_Bank5_6->SDCMR = 0x00000012; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) + FMC_Bank5_6->SDCMR = 0x00000012; + timeout = 0xFFFF; + while ((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } - - /* Auto refresh command */ -#if defined(STM32F446xx) + + /* Auto refresh command */ + #if defined(STM32F446xx) FMC_Bank5_6->SDCMR = 0x000000F3; -#else + #else FMC_Bank5_6->SDCMR = 0x00000073; -#endif /* STM32F446xx */ + #endif /* STM32F446xx */ timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) + while ((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } - - /* MRD register program */ -#if defined(STM32F446xx) + + /* MRD register program */ + #if defined(STM32F446xx) FMC_Bank5_6->SDCMR = 0x00044014; -#else + #else FMC_Bank5_6->SDCMR = 0x00046014; -#endif /* STM32F446xx */ + #endif /* STM32F446xx */ timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) + while ((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + /* Set refresh count */ tmpreg = FMC_Bank5_6->SDRTR; -#if defined(STM32F446xx) - FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1)); -#else - FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); -#endif /* STM32F446xx */ - + #if defined(STM32F446xx) + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C << 1)); + #else + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C << 1)); + #endif /* STM32F446xx */ + /* Disable write protection */ - tmpreg = FMC_Bank5_6->SDCR[0]; + tmpreg = FMC_Bank5_6->SDCR[0]; FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); -#endif /* DATA_IN_ExtSDRAM */ -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ + #endif /* DATA_IN_ExtSDRAM */ + #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || \ + STM32F446xx || STM32F469xx || STM32F479xx */ -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ - || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) + #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) \ + || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) -#if defined(DATA_IN_ExtSRAM) -/*-- GPIOs Configuration -----------------------------------------------------*/ - /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ - RCC->AHB1ENR |= 0x00000078; + #if defined(DATA_IN_ExtSRAM) + /*-- GPIOs Configuration + * -----------------------------------------------------*/ + /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ + RCC->AHB1ENR |= 0x00000078; /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); - + /* Connect PDx pins to FMC Alternate function */ - GPIOD->AFR[0] = 0x00CCC0CC; - GPIOD->AFR[1] = 0xCCCCCCCC; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xAAAA0A8A; - /* Configure PDx pins speed to 100 MHz */ + GPIOD->AFR[0] = 0x00CCC0CC; + GPIOD->AFR[1] = 0xCCCCCCCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xAAAA0A8A; + /* Configure PDx pins speed to 100 MHz */ GPIOD->OSPEEDR = 0xFFFF0FCF; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; /* Connect PEx pins to FMC Alternate function */ - GPIOE->AFR[0] = 0xC00CC0CC; - GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xAAAA828A; - /* Configure PEx pins speed to 100 MHz */ + GPIOE->AFR[0] = 0xC00CC0CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA828A; + /* Configure PEx pins speed to 100 MHz */ GPIOE->OSPEEDR = 0xFFFFC3CF; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; /* Connect PFx pins to FMC Alternate function */ - GPIOF->AFR[0] = 0x00CCCCCC; - GPIOF->AFR[1] = 0xCCCC0000; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xAA000AAA; - /* Configure PFx pins speed to 100 MHz */ + GPIOF->AFR[0] = 0x00CCCCCC; + GPIOF->AFR[1] = 0xCCCC0000; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA000AAA; + /* Configure PFx pins speed to 100 MHz */ GPIOF->OSPEEDR = 0xFF000FFF; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; /* Connect PGx pins to FMC Alternate function */ - GPIOG->AFR[0] = 0x00CCCCCC; - GPIOG->AFR[1] = 0x000000C0; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0x00085AAA; - /* Configure PGx pins speed to 100 MHz */ + GPIOG->AFR[0] = 0x00CCCCCC; + GPIOG->AFR[1] = 0x000000C0; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0x00085AAA; + /* Configure PGx pins speed to 100 MHz */ GPIOG->OSPEEDR = 0x000CAFFF; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; - -/*-- FMC/FSMC Configuration --------------------------------------------------*/ - /* Enable the FMC/FSMC interface clock */ - RCC->AHB3ENR |= 0x00000001; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) + /*-- FMC/FSMC Configuration + * --------------------------------------------------*/ + /* Enable the FMC/FSMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + + #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); /* Configure and enable Bank1_SRAM2 */ FMC_Bank1->BTCR[2] = 0x00001011; FMC_Bank1->BTCR[3] = 0x00000201; FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ -#if defined(STM32F469xx) || defined(STM32F479xx) + #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ + #if defined(STM32F469xx) || defined(STM32F479xx) /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); /* Configure and enable Bank1_SRAM2 */ FMC_Bank1->BTCR[2] = 0x00001091; FMC_Bank1->BTCR[3] = 0x00110212; FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F469xx || STM32F479xx */ -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\ - || defined(STM32F412Zx) || defined(STM32F412Vx) + #endif /* STM32F469xx || STM32F479xx */ + #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F412Zx) || defined(STM32F412Vx) /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN); /* Configure and enable Bank1_SRAM2 */ FSMC_Bank1->BTCR[2] = 0x00001011; FSMC_Bank1->BTCR[3] = 0x00000201; FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF; -#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */ + #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || \ + STM32F412Zx || STM32F412Vx */ -#endif /* DATA_IN_ExtSRAM */ -#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ - STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ - (void)(tmp); + #endif /* DATA_IN_ExtSRAM */ + #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || \ + STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || \ + STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ + (void)(tmp); } -#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */ +#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */ /** - * @} - */ + * @} + */ /** - * @} - */ + * @} + */ /** - * @} - */ + * @} + */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/examples/ArmTimerCallbacks - C++/etl_profile.h b/examples/ArmTimerCallbacks - C++/etl_profile.h index 84bbd550..d6eda2a5 100644 --- a/examples/ArmTimerCallbacks - C++/etl_profile.h +++ b/examples/ArmTimerCallbacks - C++/etl_profile.h @@ -10,6 +10,6 @@ #define ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK #define ETL_NO_STL -//#include "etl/profiles/auto.h" +// #include "etl/profiles/auto.h" #endif diff --git a/examples/ArmTimerCallbacks - C++/main.cpp b/examples/ArmTimerCallbacks - C++/main.cpp index 72692618..4a2ccb28 100644 --- a/examples/ArmTimerCallbacks - C++/main.cpp +++ b/examples/ArmTimerCallbacks - C++/main.cpp @@ -1,23 +1,23 @@ #include -//#if (__cplusplus < 201103L) +// #if (__cplusplus < 201103L) extern "C" { -//#endif -#include "Board_LED.h" // ::Board Support:LED +// #endif #include "Board_Buttons.h" // ::Board Support:Buttons -//#if (__cplusplus < 201103L) +#include "Board_LED.h" // ::Board Support:LED + // #if (__cplusplus < 201103L) } -//#endif +// #endif -#include "stm32f4xx.h" // Device header +#include "stm32f4xx.h" // Device header -#include "etl/function.h" -#include "etl/callback_timer.h" -#include "etl/vector.h" -#include "etl/iterator.h" #include "etl/binary.h" +#include "etl/callback_timer.h" +#include "etl/function.h" +#include "etl/iterator.h" +#include "etl/vector.h" struct FP { @@ -28,7 +28,7 @@ static etl::vector power_callbacks; void register_poweroff_callback(void (*function)()) { - FP fp = { function }; + FP fp = {function}; power_callbacks.push_back(fp); } @@ -45,38 +45,38 @@ etl::timer::id::type swap_timers; * SystemCoreClockConfigure: configure SystemCoreClock using HSI (HSE is not populated on Nucleo board) *----------------------------------------------------------------------------*/ -void SystemCoreClockConfigure(void) { +void SystemCoreClockConfigure(void) +{ + RCC->CR |= ((uint32_t)RCC_CR_HSION); // Enable HSI + while ((RCC->CR & RCC_CR_HSIRDY) == 0); // Wait for HSI Ready - RCC->CR |= ((uint32_t)RCC_CR_HSION); // Enable HSI - while ((RCC->CR & RCC_CR_HSIRDY) == 0); // Wait for HSI Ready + RCC->CFGR = RCC_CFGR_SW_HSI; // HSI is system clock + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI); // Wait for HSI used as system clock - RCC->CFGR = RCC_CFGR_SW_HSI; // HSI is system clock - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI); // Wait for HSI used as system clock + FLASH->ACR = FLASH_ACR_PRFTEN; // Enable Prefetch Buffer + FLASH->ACR |= FLASH_ACR_ICEN; // Instruction cache enable + FLASH->ACR |= FLASH_ACR_DCEN; // Data cache enable + FLASH->ACR |= FLASH_ACR_LATENCY_5WS; // Flash 5 wait state - FLASH->ACR = FLASH_ACR_PRFTEN; // Enable Prefetch Buffer - FLASH->ACR |= FLASH_ACR_ICEN; // Instruction cache enable - FLASH->ACR |= FLASH_ACR_DCEN; // Data cache enable - FLASH->ACR |= FLASH_ACR_LATENCY_5WS; // Flash 5 wait state + RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // HCLK = SYSCLK + RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; // APB1 = HCLK/4 + RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; // APB2 = HCLK/2 - RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // HCLK = SYSCLK - RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; // APB1 = HCLK/4 - RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; // APB2 = HCLK/2 - - RCC->CR &= ~RCC_CR_PLLON; // Disable PLL + RCC->CR &= ~RCC_CR_PLLON; // Disable PLL // PLL configuration: VCO = HSI/M * N, Sysclk = VCO/P - RCC->PLLCFGR = ( 16ul | // PLL_M = 16 - (384ul << 6U) | // PLL_N = 384 - ( 3ul << 16U) | // PLL_P = 8 - (RCC_PLLCFGR_PLLSRC_HSI) | // PLL_SRC = HSI - ( 8ul << 24U) ); // PLL_Q = 8 + RCC->PLLCFGR = (16ul | // PLL_M = 16 + (384ul << 6U) | // PLL_N = 384 + (3ul << 16U) | // PLL_P = 8 + (RCC_PLLCFGR_PLLSRC_HSI) | // PLL_SRC = HSI + (8ul << 24U)); // PLL_Q = 8 - RCC->CR |= RCC_CR_PLLON; // Enable PLL - while((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP(); // Wait till PLL is ready + RCC->CR |= RCC_CR_PLLON; // Enable PLL + while ((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP(); // Wait till PLL is ready - RCC->CFGR &= ~RCC_CFGR_SW; // Select PLL as system clock source - RCC->CFGR |= RCC_CFGR_SW_PLL; - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait till PLL is system clock src + RCC->CFGR &= ~RCC_CFGR_SW; // Select PLL as system clock source + RCC->CFGR |= RCC_CFGR_SW_PLL; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait till PLL is system clock src } void StartTimers() @@ -123,7 +123,7 @@ void LedToggle() int main() { - SystemCoreClockConfigure(); // configure HSI as System Clock + SystemCoreClockConfigure(); // configure HSI as System Clock SystemCoreClockUpdate(); LED_Initialize(); @@ -131,10 +131,10 @@ int main() // The LEDs will start flashing fast after 2 seconds. // After another 5 seconds they will start flashing slower. - short_toggle = callback_timer.register_timer(LedToggle, 50, etl::timer::mode::REPEATING); - long_toggle = callback_timer.register_timer(LedToggle, 100, etl::timer::mode::REPEATING); + short_toggle = callback_timer.register_timer(LedToggle, 50, etl::timer::mode::REPEATING); + long_toggle = callback_timer.register_timer(LedToggle, 100, etl::timer::mode::REPEATING); start_timers = callback_timer.register_timer(StartTimers, 2000, etl::timer::mode::SINGLE_SHOT); - swap_timers = callback_timer.register_timer(SwapTimers, 1500, etl::timer::mode::SINGLE_SHOT); + swap_timers = callback_timer.register_timer(SwapTimers, 1500, etl::timer::mode::SINGLE_SHOT); SysTick_Config(SystemCoreClock / 1000); @@ -152,7 +152,7 @@ extern "C" { void SysTick_Handler() { - const uint32_t TICK = 1U; + const uint32_t TICK = 1U; static uint32_t nticks = TICK; if (callback_timer.tick(nticks)) diff --git a/examples/FunctionInterruptSimulation-Delegates/FunctionInterruptSimulation.cpp b/examples/FunctionInterruptSimulation-Delegates/FunctionInterruptSimulation.cpp index bbf6debf..859b92c8 100644 --- a/examples/FunctionInterruptSimulation-Delegates/FunctionInterruptSimulation.cpp +++ b/examples/FunctionInterruptSimulation-Delegates/FunctionInterruptSimulation.cpp @@ -11,8 +11,8 @@ enum VectorId USART1_IRQ_HANDLER = 52, USART2_IRQ_HANDLER = 53, VECTOR_ID_END, - VECTOR_ID_OFFSET = TIM1_CC_IRQ_HANDLER, - VECTOR_ID_RANGE = VECTOR_ID_END - VECTOR_ID_OFFSET + VECTOR_ID_OFFSET = TIM1_CC_IRQ_HANDLER, + VECTOR_ID_RANGE = VECTOR_ID_END - VECTOR_ID_OFFSET }; typedef etl::delegate_service InterruptVectors; @@ -91,8 +91,8 @@ public: // Constructor. Uart(int port_id, size_t interruptId) - : port_id(port_id), - callback(etl::delegate::create(*this)) + : port_id(port_id) + , callback(etl::delegate::create(*this)) { GetInterruptVectorsInstance().register_delegate(interruptId, callback); } @@ -119,7 +119,8 @@ Uart uart1(0, USART1_IRQ_HANDLER); Uart uart2(1, USART2_IRQ_HANDLER); // Declare a global callback for the timer. -// Uses the most efficient callback type for a class, as everything is known at compile time. +// Uses the most efficient callback type for a class, as everything is known at +// compile time. etl::delegate timer_member_callback = etl::delegate::create(); // Declare the callbacks for the free functions. diff --git a/examples/FunctionInterruptSimulation/FunctionInterruptSimulation.cpp b/examples/FunctionInterruptSimulation/FunctionInterruptSimulation.cpp index 9eb6cb98..8e680e3d 100644 --- a/examples/FunctionInterruptSimulation/FunctionInterruptSimulation.cpp +++ b/examples/FunctionInterruptSimulation/FunctionInterruptSimulation.cpp @@ -1,7 +1,7 @@ #include -#include "etl/function.h" #include "etl/callback_service.h" +#include "etl/function.h" enum VectorId { @@ -11,8 +11,8 @@ enum VectorId USART1_IRQ_HANDLER = 52, USART2_IRQ_HANDLER = 53, VECTOR_ID_END, - VECTOR_ID_OFFSET = TIM1_CC_IRQ_HANDLER, - VECTOR_ID_RANGE = VECTOR_ID_END - VECTOR_ID_OFFSET + VECTOR_ID_OFFSET = TIM1_CC_IRQ_HANDLER, + VECTOR_ID_RANGE = VECTOR_ID_END - VECTOR_ID_OFFSET }; typedef etl::callback_service InterruptVectors; @@ -91,8 +91,8 @@ public: // Constructor. Uart(int port_id, int interruptId) - : port_id(port_id), - callback(*this) + : port_id(port_id) + , callback(*this) { GetInterruptVectorsInstance().register_callback(interruptId, callback); } @@ -119,7 +119,8 @@ Uart uart1(0, USART1_IRQ_HANDLER); Uart uart2(1, USART2_IRQ_HANDLER); // Declare a global callback for the timer. -// Uses the most efficient callback type for a class, as everything is known at compile time. +// Uses the most efficient callback type for a class, as everything is known at +// compile time. etl::function_imp timer_member_callback; // Declare the callbacks for the free functions. diff --git a/examples/MutexMessageRouter/MutexMessageRouter.cpp b/examples/MutexMessageRouter/MutexMessageRouter.cpp index 1d612673..b04a61f4 100644 --- a/examples/MutexMessageRouter/MutexMessageRouter.cpp +++ b/examples/MutexMessageRouter/MutexMessageRouter.cpp @@ -1,13 +1,13 @@ -#include -#include #include -#include #include +#include +#include +#include -#include "etl/mutex.h" #include "etl/message.h" #include "etl/message_router.h" +#include "etl/mutex.h" //************************************* struct Message1 : public etl::message<1> @@ -48,9 +48,7 @@ public: } //***************** - void on_receive_unknown(const etl::imessage&) - { - } + void on_receive_unknown(const etl::imessage&) {} std::string result; @@ -61,7 +59,7 @@ private: //************************************* etl::atomic start = false; -Router router; +Router router; //************************************* void thread1() @@ -106,5 +104,3 @@ int main() return 0; } - - diff --git a/examples/QueuedFSM/QueuedFSM.cpp b/examples/QueuedFSM/QueuedFSM.cpp index a0cbd029..5bda8913 100644 --- a/examples/QueuedFSM/QueuedFSM.cpp +++ b/examples/QueuedFSM/QueuedFSM.cpp @@ -31,9 +31,9 @@ SOFTWARE. // derived class. //***************************************************************************** -#include "etl/queue.h" #include "etl/fsm.h" #include "etl/message_packet.h" +#include "etl/queue.h" #include #include @@ -122,7 +122,7 @@ public: while (!queue.empty()) { message_packet& packet = queue.front(); - etl::imessage& msg = packet.get(); + etl::imessage& msg = packet.get(); std::cout << "Processing message " << int(msg.get_message_id()) << std::endl; // Call the base class's receive function. @@ -258,7 +258,7 @@ int main() State2 state2; // The list of states. - etl::ifsm_state* state_list[] = { &state1, &state2 }; + etl::ifsm_state* state_list[] = {&state1, &state2}; // Define some messages. Message1 m1(1); @@ -285,4 +285,3 @@ int main() return 0; } - diff --git a/examples/QueuedMessageRouter/QueuedMessageRouter.cpp b/examples/QueuedMessageRouter/QueuedMessageRouter.cpp index f4348e5e..e9d815d2 100644 --- a/examples/QueuedMessageRouter/QueuedMessageRouter.cpp +++ b/examples/QueuedMessageRouter/QueuedMessageRouter.cpp @@ -1,6 +1,6 @@ -#include "etl/queue.h" #include "etl/message_router.h" +#include "etl/queue.h" #include #include @@ -81,7 +81,7 @@ public: while (!queue.empty()) { message_packet& packet = queue.front(); - etl::imessage& msg = packet.get(); + etl::imessage& msg = packet.get(); std::cout << "Processing message " << int(msg.get_message_id()) << std::endl; // Call the base class's receive function. @@ -146,4 +146,3 @@ int main() return 0; } - diff --git a/examples/Scheduler/Scheduler.cpp b/examples/Scheduler/Scheduler.cpp index 015822ae..3ea957be 100644 --- a/examples/Scheduler/Scheduler.cpp +++ b/examples/Scheduler/Scheduler.cpp @@ -31,9 +31,9 @@ SOFTWARE. // Experiment with the different scheduling policies. //***************************************************************************** +#include "etl/function.h" #include "etl/scheduler.h" #include "etl/task.h" -#include "etl/function.h" #include #include @@ -50,13 +50,13 @@ public: : task(1) , work(3) { - } //************************************* uint32_t task_request_work() const { - return work; // How much work do we still have to do? This could be a message queue length. + return work; // How much work do we still have to do? This could be a + // message queue length. } //************************************* @@ -83,13 +83,13 @@ public: : task(2) , work(4) { - } //************************************* uint32_t task_request_work() const { - return work; // How much work do we still have to do? This could be a message queue length. + return work; // How much work do we still have to do? This could be a + // message queue length. } //************************************* @@ -115,7 +115,6 @@ public: Idle(etl::ischeduler& scheduler_) : scheduler(scheduler_) { - } //************************************* @@ -181,4 +180,3 @@ int main() return 0; } - diff --git a/examples/SharedMessage/SharedMessage.cpp b/examples/SharedMessage/SharedMessage.cpp index caaf4a0b..7bcbc27f 100644 --- a/examples/SharedMessage/SharedMessage.cpp +++ b/examples/SharedMessage/SharedMessage.cpp @@ -2,18 +2,18 @@ // Shared message example //***************************************************************************** -#include "etl/shared_message.h" -#include "etl/message.h" -#include "etl/reference_counted_message_pool.h" -#include "etl/message_router.h" -#include "etl/message_bus.h" #include "etl/fixed_sized_memory_block_allocator.h" +#include "etl/message.h" +#include "etl/message_bus.h" +#include "etl/message_router.h" #include "etl/queue.h" +#include "etl/reference_counted_message_pool.h" +#include "etl/shared_message.h" -#include #include -#include +#include #include +#include constexpr etl::message_router_id_t RouterId1 = 1U; constexpr etl::message_router_id_t RouterId2 = 2U; @@ -26,9 +26,8 @@ struct Message1 : public etl::message<1> Message1(std::string s_) : s(s_) { - } - + std::string s; }; @@ -40,10 +39,10 @@ struct Message2 : public etl::message<2> Message2(std::string s_) : s(s_) { - } - + std::string s; + char data[100]; }; @@ -55,7 +54,6 @@ struct Message3 : public etl::message<3> Message3(std::string s_) : s(s_) { - } std::string s; @@ -199,7 +197,7 @@ struct Bus : public etl::message_bus<2U> //***************************************************************************** MessageRouter1 router1; MessageRouter2 router2; -Bus bus; +Bus bus; //***************************************************************************** // The thread safe message pool. Uses atomic uint32_t for counting. @@ -230,8 +228,8 @@ private: }; //***************************************************************************** -// The memory block allocator that supplies the pool with memory -// to store reference counted messages in. +// The memory block allocator that supplies the pool with memory +// to store reference counted messages in. // The reference counted message parameters type for the messages we will use. using message_parameters_small = MessagePool::pool_message_parameters; @@ -243,10 +241,12 @@ constexpr size_t max_alignment_small = message_parameters_small::max_alignment; constexpr size_t max_size_large = message_parameters_large::max_size; constexpr size_t max_alignment_large = message_parameters_large::max_alignment; -// A fixed memory block allocator for 4 items, using the parameters from the smaller messages. +// A fixed memory block allocator for 4 items, using the parameters from the +// smaller messages. etl::fixed_sized_memory_block_allocator memory_allocator; -// A fixed memory block allocator for 4 items, using the parameters from the larger message. +// A fixed memory block allocator for 4 items, using the parameters from the +// larger message. etl::fixed_sized_memory_block_allocator memory_allocator_successor; //***************************************************************************** @@ -256,8 +256,8 @@ etl::fixed_sized_memory_block_allocator MessagePool message_pool(memory_allocator); //***************************************************************************** -// A statically allocated reference counted message that is never allocated or released by a pool. -// Contains a copy of Message3("Three"). +// A statically allocated reference counted message that is never allocated or +// released by a pool. Contains a copy of Message3("Three"). //***************************************************************************** etl::persistent_message pm3(Message3("Three")); @@ -269,10 +269,15 @@ int main() Message1 m1("One"); Message2 m2("Two"); - - etl::shared_message sm1(message_pool, m1); // Created a shared message by allocating a reference counted message from message_pool containing a copy of m1. - etl::shared_message sm2(message_pool, m2); // Created a shared message by allocating a reference counted message from message_pool containing a copy of m2. - etl::shared_message sm3(pm3); // Created a shared message from a statically allocated persistent message. + + etl::shared_message sm1(message_pool, + m1); // Created a shared message by allocating a reference counted message + // from message_pool containing a copy of m1. + etl::shared_message sm2(message_pool, + m2); // Created a shared message by allocating a reference counted message + // from message_pool containing a copy of m2. + etl::shared_message sm3(pm3); // Created a shared message from a statically + // allocated persistent message. bus.subscribe(router1); // Subscribe router1 to the bus. bus.subscribe(router2); // Subscribe router2 to the bus. diff --git a/examples/UniquePtrWithPool/Main.cpp b/examples/UniquePtrWithPool/Main.cpp index c3172ff9..30347951 100644 --- a/examples/UniquePtrWithPool/Main.cpp +++ b/examples/UniquePtrWithPool/Main.cpp @@ -6,7 +6,8 @@ struct S { S(int a_, double b_) - : a(a_), b(b_) + : a(a_) + , b(b_) { } @@ -17,11 +18,11 @@ struct S int main() { etl::pool pool; - auto pool_deleter = [&pool](auto ptr) - { - std::cout << "Releasing S(" << ptr->a << ", " << ptr->b << ") back to pool." << std::endl; - pool.destroy(ptr); - }; + auto pool_deleter = [&pool](auto ptr) + { + std::cout << "Releasing S(" << ptr->a << ", " << ptr->b << ") back to pool." << std::endl; + pool.destroy(ptr); + }; using Unique = etl::unique_ptr; Unique us1(pool.create(1, 2), pool_deleter); diff --git a/examples/platformio/src/main.cpp b/examples/platformio/src/main.cpp index 66295c17..0686ba82 100644 --- a/examples/platformio/src/main.cpp +++ b/examples/platformio/src/main.cpp @@ -88,35 +88,35 @@ public: // Notify observers about a position event. void Position_Event() { - Position position = { 100, 200 }; + Position position = {100, 200}; notify_observers(position); } // Notify observers about a button up event. void Button_Event_Up() { - Button button = { Button::Up }; + Button button = {Button::Up}; notify_observers(button); } // Notify observers about a button down event. void Button_Event_Down() { - Button button = { Button::Down }; + Button button = {Button::Down}; notify_observers(button); } // Notify observers about a wheel up event. void Wheel_Event_Up() { - Wheel wheel = { 50 }; + Wheel wheel = {50}; notify_observers(wheel); } // Notify observers about a wheel down event. void Wheel_Event_Down() { - Wheel wheel = { -25 }; + Wheel wheel = {-25}; notify_observers(wheel); } }; @@ -137,6 +137,6 @@ int main() mouse_driver.Position_Event(); mouse_driver.Wheel_Event_Down(); mouse_driver.Wheel_Event_Up(); - + return 0; } diff --git a/include/etl/absolute.h b/include/etl/absolute.h index cad11b7c..bfa68642 100644 --- a/include/etl/absolute.h +++ b/include/etl/absolute.h @@ -32,19 +32,40 @@ SOFTWARE. #define ETL_ABSOLUTE_INCLUDED #include "platform.h" -#include "type_traits.h" +#include "error_handler.h" #include "integral_limits.h" +#include "type_traits.h" namespace etl { + namespace private_absolute + { + //************************************************************************* + // Non-constexpr function that is never called for valid inputs. + // If reached during constant evaluation, the compiler emits an error + // because it's not constexpr. + // At runtime, triggers the ETL assert handler. + //************************************************************************* + template + inline T signed_min_error() + { + ETL_ASSERT_FAIL(ETL_ERROR_GENERIC("absolute value of minimum signed integer is undefined")); + return T(0); + } + } // namespace private_absolute + //*************************************************************************** // For signed types. //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR - typename etl::enable_if::value, T>::type - absolute(T value) ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR typename etl::enable_if< etl::is_signed::value && etl::is_integral::value, T>::type absolute(T value) + { + return (value == etl::integral_limits::min) ? etl::private_absolute::signed_min_error() : static_cast((value < T(0)) ? -value : value); + } + + template + ETL_NODISCARD ETL_CONSTEXPR typename etl::enable_if< etl::is_signed::value && !etl::is_integral::value, T>::type absolute(T value) + ETL_NOEXCEPT { return (value < T(0)) ? -value : value; } @@ -53,10 +74,7 @@ namespace etl // For unsigned types. //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR - typename etl::enable_if::value, T>::type - absolute(T value) ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR typename etl::enable_if::value, T>::type absolute(T value) ETL_NOEXCEPT { return value; } @@ -66,15 +84,14 @@ namespace etl // Returns the result as the unsigned type. //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR - typename etl::enable_if::value, typename etl::make_unsigned::type>::type - absolute_unsigned(T value) ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR typename etl::enable_if::value, typename etl::make_unsigned::type>::type absolute_unsigned(T value) + ETL_NOEXCEPT { typedef typename etl::make_unsigned::type TReturn; return (value == etl::integral_limits::min) ? (etl::integral_limits::max / 2U) + 1U - : (value < T(0)) ? TReturn(-value) : TReturn(value); + : (value < T(0)) ? TReturn(-value) + : TReturn(value); } //*************************************************************************** @@ -82,14 +99,10 @@ namespace etl // Returns the result as the unsigned type. //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR - typename etl::enable_if::value, T>::type - absolute_unsigned(T value) ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR typename etl::enable_if::value, T>::type absolute_unsigned(T value) ETL_NOEXCEPT { return etl::absolute(value); } -} +} // namespace etl #endif - diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 74fbb8ed..0a4348a2 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -34,19 +34,21 @@ SOFTWARE. #define ETL_ALGORITHM_INCLUDED ///\defgroup algorithm algorithm -/// Including reverse engineered algorithms from C++ 0x11, 0x14, 0x17 +/// Including reverse engineered algorithms from C++11, 14, 17 /// Additional new variants of certain algorithms. ///\ingroup utilities #include "platform.h" -#include "type_traits.h" -#include "iterator.h" -#include "functional.h" -#include "utility.h" -#include "largest.h" -#include "gcd.h" #include "error_handler.h" #include "exception.h" +#include "functional.h" +#include "gcd.h" +#include "invoke.h" +#include "iterator.h" +#include "largest.h" +#include "ranges.h" +#include "type_traits.h" +#include "utility.h" #include #include @@ -55,10 +57,10 @@ SOFTWARE. #if ETL_USING_STL #include - #include - #include #include + #include #include + #include #endif namespace etl @@ -66,11 +68,12 @@ namespace etl // Declare prototypes of the ETL's sort functions template #if ETL_USING_STD_NAMESPACE - ETL_CONSTEXPR20 + ETL_CONSTEXPR20 #else ETL_CONSTEXPR14 #endif - void shell_sort(TIterator first, TIterator last); + void + shell_sort(TIterator first, TIterator last); template #if ETL_USING_STD_NAMESPACE @@ -78,7 +81,8 @@ namespace etl #else ETL_CONSTEXPR14 #endif - void shell_sort(TIterator first, TIterator last, TCompare compare); + void + shell_sort(TIterator first, TIterator last, TCompare compare); template ETL_CONSTEXPR14 void insertion_sort(TIterator first, TIterator last); @@ -106,7 +110,7 @@ namespace etl } }; -} +} // namespace etl //***************************************************************************** // Algorithms defined by the ETL @@ -126,8 +130,8 @@ namespace etl static void do_swap(TIterator1 a, TIterator2 b) { typename etl::iterator_traits::value_type tmp = *a; - *a = *b; - *b = tmp; + *a = *b; + *b = tmp; } }; @@ -142,7 +146,7 @@ namespace etl swap(*a, *b); } }; - } + } // namespace private_algorithm //*************************************************************************** // iter_swap @@ -153,7 +157,8 @@ namespace etl #else ETL_CONSTEXPR14 #endif - void iter_swap(TIterator1 a, TIterator2 b) + void + iter_swap(TIterator1 a, TIterator2 b) { typedef etl::iterator_traits traits1; typedef etl::iterator_traits traits2; @@ -164,9 +169,7 @@ namespace etl typedef typename traits1::reference r1; typedef typename traits2::reference r2; - const bool use_swap = etl::is_same::value && - etl::is_reference::value && - etl::is_reference::value; + const bool use_swap = etl::is_same::value && etl::is_reference::value && etl::is_reference::value; private_algorithm::swap_impl::do_swap(a, b); } @@ -180,9 +183,8 @@ namespace etl #else ETL_CONSTEXPR14 #endif - TIterator2 swap_ranges(TIterator1 first1, - TIterator1 last1, - TIterator2 first2) + TIterator2 + swap_ranges(TIterator1 first1, TIterator1 last1, TIterator2 first2) { while (first1 != last1) { @@ -197,8 +199,7 @@ namespace etl //*************************************************************************** // generate template - ETL_CONSTEXPR14 - void generate(TIterator db, TIterator de, TFunction funct) + ETL_CONSTEXPR14 void generate(TIterator db, TIterator de, TFunction funct) { while (db != de) { @@ -208,7 +209,7 @@ namespace etl //*************************************************************************** // copy -#if ETL_USING_STL && ETL_USING_CPP20 +#if ETL_USING_STL && ETL_USING_CPP20 // Use the STL constexpr implementation. template constexpr TIterator2 copy(TIterator1 sb, TIterator1 se, TIterator2 db) @@ -241,8 +242,7 @@ namespace etl } #else template - ETL_CONSTEXPR14 - TIterator2 reverse_copy(TIterator1 sb, TIterator1 se, TIterator2 db) + ETL_CONSTEXPR14 TIterator2 reverse_copy(TIterator1 sb, TIterator1 se, TIterator2 db) { while (sb != se) { @@ -338,9 +338,9 @@ namespace etl template ETL_CONSTEXPR20 TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) { -#include "etl/private/diagnostic_array_bounds_push.h" + #include "etl/private/diagnostic_array_bounds_push.h" return std::move_backward(sb, se, de); -#include "etl/private/diagnostic_pop.h" + #include "etl/private/diagnostic_pop.h" } #elif ETL_USING_CPP11 // For C++11 @@ -368,9 +368,7 @@ namespace etl //*************************************************************************** // Pointers template - ETL_CONSTEXPR14 - typename etl::enable_if::value, void>::type - reverse(TIterator b, TIterator e) + ETL_CONSTEXPR14 typename etl::enable_if::value, void>::type reverse(TIterator b, TIterator e) { if (b != e) { @@ -384,9 +382,7 @@ namespace etl // Non-pointers template - ETL_CONSTEXPR14 - typename etl::enable_if::value, void>::type - reverse(TIterator b, TIterator e) + ETL_CONSTEXPR14 typename etl::enable_if::value, void>::type reverse(TIterator b, TIterator e) { while ((b != e) && (b != --e)) { @@ -397,10 +393,8 @@ namespace etl //*************************************************************************** // lower_bound //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator lower_bound(TIterator first, TIterator last, const TValue& value, TCompare compare) + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator lower_bound(TIterator first, TIterator last, const TValue& value, TCompare compare) { typedef typename etl::iterator_traits::difference_type difference_t; @@ -408,7 +402,7 @@ namespace etl while (count > 0) { - TIterator itr = first; + TIterator itr = first; difference_t step = count / 2; etl::advance(itr, step); @@ -427,10 +421,8 @@ namespace etl return first; } - template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator lower_bound(TIterator first, TIterator last, const TValue& value) + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator lower_bound(TIterator first, TIterator last, const TValue& value) { typedef etl::less::value_type> compare; @@ -440,10 +432,8 @@ namespace etl //*************************************************************************** // upper_bound //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator upper_bound(TIterator first, TIterator last, const TValue& value, TCompare compare) + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator upper_bound(TIterator first, TIterator last, const TValue& value, TCompare compare) { typedef typename etl::iterator_traits::difference_type difference_t; @@ -451,7 +441,7 @@ namespace etl while (count > 0) { - TIterator itr = first; + TIterator itr = first; difference_t step = count / 2; etl::advance(itr, step); @@ -470,10 +460,8 @@ namespace etl return first; } - template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator upper_bound(TIterator first, TIterator last, const TValue& value) + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator upper_bound(TIterator first, TIterator last, const TValue& value) { typedef etl::less::value_type> compare; @@ -483,31 +471,26 @@ namespace etl //*************************************************************************** // equal_range //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - ETL_OR_STD::pair equal_range(TIterator first, TIterator last, const TValue& value, TCompare compare) + template + ETL_NODISCARD ETL_CONSTEXPR14 ETL_OR_STD::pair equal_range(TIterator first, TIterator last, const TValue& value, TCompare compare) { - return ETL_OR_STD::make_pair(etl::lower_bound(first, last, value, compare), - etl::upper_bound(first, last, value, compare)); + return ETL_OR_STD::make_pair(etl::lower_bound(first, last, value, compare), etl::upper_bound(first, last, value, compare)); } - template + template ETL_NODISCARD ETL_OR_STD::pair equal_range(TIterator first, TIterator last, const TValue& value) { typedef etl::less::value_type> compare; - return ETL_OR_STD::make_pair(etl::lower_bound(first, last, value, compare()), - etl::upper_bound(first, last, value, compare())); + return ETL_OR_STD::make_pair(etl::lower_bound(first, last, value, compare()), etl::upper_bound(first, last, value, compare())); } //*************************************************************************** // binary_search //*************************************************************************** template - ETL_NODISCARD - bool binary_search(TIterator first, TIterator last, const T& value, Compare compare) + ETL_NODISCARD ETL_CONSTEXPR14 bool binary_search(TIterator first, TIterator last, const T& value, Compare compare) { first = etl::lower_bound(first, last, value, compare); @@ -515,8 +498,7 @@ namespace etl } template - ETL_NODISCARD - bool binary_search(TIterator first, TIterator last, const T& value) + ETL_NODISCARD ETL_CONSTEXPR14 bool binary_search(TIterator first, TIterator last, const T& value) { typedef etl::less::value_type> compare; @@ -527,9 +509,7 @@ namespace etl // find_if //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator find_if(TIterator first, TIterator last, TUnaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator find_if(TIterator first, TIterator last, TUnaryPredicate predicate) { while (first != last) { @@ -548,9 +528,7 @@ namespace etl // find //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator find(TIterator first, TIterator last, const T& value) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator find(TIterator first, TIterator last, const T& value) { while (first != last) { @@ -568,13 +546,13 @@ namespace etl //*************************************************************************** // fill #if ETL_USING_STL && ETL_USING_CPP20 - template + template constexpr void fill(TIterator first, TIterator last, const TValue& value) { std::fill(first, last, value); } #else - template + template ETL_CONSTEXPR14 void fill(TIterator first, TIterator last, const TValue& value) { while (first != last) @@ -588,13 +566,13 @@ namespace etl //*************************************************************************** // fill_n #if ETL_USING_STL && ETL_USING_CPP20 - template + template constexpr TIterator fill_n(TIterator first, TSize count, const TValue& value) { return std::fill_n(first, count, value); } #else - template + template ETL_CONSTEXPR14 TIterator fill_n(TIterator first, TSize count, const TValue& value) { while (count != 0) @@ -611,9 +589,7 @@ namespace etl // count //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - typename etl::iterator_traits::difference_type count(TIterator first, TIterator last, const T& value) + ETL_NODISCARD ETL_CONSTEXPR14 typename etl::iterator_traits::difference_type count(TIterator first, TIterator last, const T& value) { typename iterator_traits::difference_type n = 0; @@ -634,10 +610,7 @@ namespace etl // count_if //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - typename etl::iterator_traits::difference_type - count_if(TIterator first, TIterator last, TUnaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 typename etl::iterator_traits::difference_type count_if(TIterator first, TIterator last, TUnaryPredicate predicate) { typename iterator_traits::difference_type n = 0; @@ -660,8 +633,7 @@ namespace etl // Three parameter template [[nodiscard]] - constexpr - bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2) + constexpr bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2) { return std::equal(first1, last1, first2); } @@ -669,8 +641,7 @@ namespace etl // Three parameter + predicate template [[nodiscard]] - constexpr - bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TPredicate predicate) + constexpr bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TPredicate predicate) { return std::equal(first1, last1, first2, predicate); } @@ -678,8 +649,7 @@ namespace etl // Four parameter template [[nodiscard]] - constexpr - bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2) + constexpr bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2) { return std::equal(first1, last1, first2, last2); } @@ -687,8 +657,7 @@ namespace etl // Four parameter + Predicate template [[nodiscard]] - constexpr - bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2, TPredicate predicate) + constexpr bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2, TPredicate predicate) { return std::equal(first1, last1, first2, last2, predicate); } @@ -696,9 +665,7 @@ namespace etl #else template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2) + ETL_NODISCARD ETL_CONSTEXPR14 bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2) { while (first1 != last1) { @@ -716,9 +683,7 @@ namespace etl // Predicate template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TPredicate predicate) { while (first1 != last1) { @@ -736,9 +701,7 @@ namespace etl // Four parameter template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2) + ETL_NODISCARD ETL_CONSTEXPR14 bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2) { while ((first1 != last1) && (first2 != last2)) { @@ -756,13 +719,11 @@ namespace etl // Four parameter, Predicate template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2, TPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2, TPredicate predicate) { while ((first1 != last1) && (first2 != last2)) { - if (!predicate(*first1 , *first2)) + if (!predicate(*first1, *first2)) { return false; } @@ -779,11 +740,7 @@ namespace etl // lexicographical_compare //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool lexicographical_compare(TIterator1 first1, TIterator1 last1, - TIterator2 first2, TIterator2 last2, - TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR14 bool lexicographical_compare(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2, TCompare compare) { while ((first1 != last1) && (first2 != last2)) { @@ -806,10 +763,7 @@ namespace etl // lexicographical_compare template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool lexicographical_compare(TIterator1 first1, TIterator1 last1, - TIterator2 first2, TIterator2 last2) + ETL_NODISCARD ETL_CONSTEXPR14 bool lexicographical_compare(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2) { typedef etl::less::value_type> compare; @@ -820,17 +774,13 @@ namespace etl // min //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR - const T& min(const T& a, const T& b, TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR const T& min(const T& a, const T& b, TCompare compare) { return (compare(a, b)) ? a : b; } template - ETL_NODISCARD - ETL_CONSTEXPR - const T& min(const T& a, const T& b) + ETL_NODISCARD ETL_CONSTEXPR const T& min(const T& a, const T& b) { typedef etl::less compare; @@ -841,17 +791,13 @@ namespace etl // max //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR - const T& max(const T& a, const T& b, TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR const T& max(const T& a, const T& b, TCompare compare) { return (compare(a, b)) ? b : a; } template - ETL_NODISCARD - ETL_CONSTEXPR - const T& max(const T& a, const T& b) + ETL_NODISCARD ETL_CONSTEXPR const T& max(const T& a, const T& b) { typedef etl::less compare; @@ -862,8 +808,7 @@ namespace etl // for_each //*************************************************************************** template - ETL_CONSTEXPR14 - TUnaryOperation for_each(TIterator first, TIterator last, TUnaryOperation unary_operation) + ETL_CONSTEXPR14 TUnaryOperation for_each(TIterator first, TIterator last, TUnaryOperation unary_operation) { while (first != last) { @@ -878,8 +823,7 @@ namespace etl // transform //*************************************************************************** template - ETL_CONSTEXPR14 - TIteratorOut transform(TIteratorIn first1, TIteratorIn last1, TIteratorOut d_first, TUnaryOperation unary_operation) + ETL_CONSTEXPR14 TIteratorOut transform(TIteratorIn first1, TIteratorIn last1, TIteratorOut d_first, TUnaryOperation unary_operation) { while (first1 != last1) { @@ -893,8 +837,8 @@ namespace etl } template - ETL_CONSTEXPR14 - TIteratorOut transform(TIteratorIn1 first1, TIteratorIn1 last1, TIteratorIn2 first2, TIteratorOut d_first, TBinaryOperation binary_operation) + ETL_CONSTEXPR14 TIteratorOut transform(TIteratorIn1 first1, TIteratorIn1 last1, TIteratorIn2 first2, TIteratorOut d_first, + TBinaryOperation binary_operation) { while (first1 != last1) { @@ -949,15 +893,15 @@ namespace etl { // Push Heap Helper template - void push_heap(TIterator first, TDistance value_index, TDistance top_index, TValue value, TCompare compare) + ETL_CONSTEXPR14 void push_heap(TIterator first, TDistance value_index, TDistance top_index, TValue value, TCompare compare) { TDistance parent = (value_index - 1) / 2; while ((value_index > top_index) && compare(first[parent], value)) { first[value_index] = ETL_MOVE(first[parent]); - value_index = parent; - parent = (value_index - 1) / 2; + value_index = parent; + parent = (value_index - 1) / 2; } first[value_index] = ETL_MOVE(value); @@ -965,10 +909,10 @@ namespace etl // Adjust Heap Helper template - void adjust_heap(TIterator first, TDistance value_index, TDistance length, TValue value, TCompare compare) + ETL_CONSTEXPR14 void adjust_heap(TIterator first, TDistance value_index, TDistance length, TValue value, TCompare compare) { TDistance top_index = value_index; - TDistance child2nd = (2 * value_index) + 2; + TDistance child2nd = (2 * value_index) + 2; while (child2nd < length) { @@ -978,14 +922,14 @@ namespace etl } first[value_index] = ETL_MOVE(first[child2nd]); - value_index = child2nd; - child2nd = 2 * (child2nd + 1); + value_index = child2nd; + child2nd = 2 * (child2nd + 1); } if (child2nd == length) { first[value_index] = ETL_MOVE(first[child2nd - 1]); - value_index = child2nd - 1; + value_index = child2nd - 1; } push_heap(first, value_index, top_index, ETL_MOVE(value), compare); @@ -993,7 +937,7 @@ namespace etl // Is Heap Helper template - bool is_heap(const TIterator first, const TDistance n, TCompare compare) + ETL_CONSTEXPR14 bool is_heap(const TIterator first, const TDistance n, TCompare compare) { TDistance parent = 0; @@ -1012,24 +956,24 @@ namespace etl return true; } - } + } // namespace private_heap // Pop Heap template - void pop_heap(TIterator first, TIterator last, TCompare compare) + ETL_CONSTEXPR14 void pop_heap(TIterator first, TIterator last, TCompare compare) { - typedef typename etl::iterator_traits::value_type value_t; + typedef typename etl::iterator_traits::value_type value_t; typedef typename etl::iterator_traits::difference_type distance_t; value_t value = ETL_MOVE(last[-1]); - last[-1] = ETL_MOVE(first[0]); + last[-1] = ETL_MOVE(first[0]); private_heap::adjust_heap(first, distance_t(0), distance_t(last - first - 1), ETL_MOVE(value), compare); } // Pop Heap template - void pop_heap(TIterator first, TIterator last) + ETL_CONSTEXPR14 void pop_heap(TIterator first, TIterator last) { typedef etl::less::value_type> compare; @@ -1038,7 +982,7 @@ namespace etl // Push Heap template - void push_heap(TIterator first, TIterator last, TCompare compare) + ETL_CONSTEXPR14 void push_heap(TIterator first, TIterator last, TCompare compare) { typedef typename etl::iterator_traits::difference_type difference_t; typedef typename etl::iterator_traits::value_type value_t; @@ -1048,7 +992,7 @@ namespace etl // Push Heap template - void push_heap(TIterator first, TIterator last) + ETL_CONSTEXPR14 void push_heap(TIterator first, TIterator last) { typedef etl::less::value_type> compare; @@ -1057,7 +1001,7 @@ namespace etl // Make Heap template - void make_heap(TIterator first, TIterator last, TCompare compare) + ETL_CONSTEXPR14 void make_heap(TIterator first, TIterator last, TCompare compare) { typedef typename etl::iterator_traits::difference_type difference_t; @@ -1084,7 +1028,7 @@ namespace etl // Make Heap template - void make_heap(TIterator first, TIterator last) + ETL_CONSTEXPR14 void make_heap(TIterator first, TIterator last) { typedef etl::less::value_type> compare; @@ -1093,8 +1037,7 @@ namespace etl // Is Heap template - ETL_NODISCARD - bool is_heap(TIterator first, TIterator last) + ETL_NODISCARD ETL_CONSTEXPR14 bool is_heap(TIterator first, TIterator last) { typedef etl::less::value_type> compare; @@ -1103,15 +1046,14 @@ namespace etl // Is Heap template - ETL_NODISCARD - bool is_heap(TIterator first, TIterator last, TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR14 bool is_heap(TIterator first, TIterator last, TCompare compare) { return private_heap::is_heap(first, last - first, compare); } // Sort Heap template - void sort_heap(TIterator first, TIterator last) + ETL_CONSTEXPR14 void sort_heap(TIterator first, TIterator last) { while (first != last) { @@ -1122,7 +1064,7 @@ namespace etl // Sort Heap template - void sort_heap(TIterator first, TIterator last, TCompare compare) + ETL_CONSTEXPR14 void sort_heap(TIterator first, TIterator last, TCompare compare) { while (first != last) { @@ -1131,17 +1073,121 @@ namespace etl } } + //*************************************************************************** + /// partial_sort + ///\ingroup algorithm + ///< a href="http://en.cppreference.com/w/cpp/algorithm/partial_sort"> + //*************************************************************************** + template + ETL_CONSTEXPR14 void partial_sort(TIterator first, TIterator middle, TIterator last, TCompare compare) + { + if (first == middle) + { + return; + } + + typedef typename etl::iterator_traits::value_type value_t; + typedef typename etl::iterator_traits::difference_type difference_t; + + etl::make_heap(first, middle, compare); + + for (TIterator i = middle; i != last; ++i) + { + if (compare(*i, *first)) + { + value_t value = ETL_MOVE(*i); + *i = ETL_MOVE(*first); + + private_heap::adjust_heap(first, difference_t(0), difference_t(middle - first), ETL_MOVE(value), compare); + } + } + + etl::sort_heap(first, middle, compare); + } + + //*************************************************************************** + /// partial_sort + ///\ingroup algorithm + ///< a href="http://en.cppreference.com/w/cpp/algorithm/partial_sort"> + //*************************************************************************** + template + ETL_CONSTEXPR14 void partial_sort(TIterator first, TIterator middle, TIterator last) + { + typedef etl::less::value_type> compare; + + etl::partial_sort(first, middle, last, compare()); + } + + //*************************************************************************** + /// partial_sort_copy + ///\ingroup algorithm + ///< a + ///< href="http://en.cppreference.com/w/cpp/algorithm/partial_sort_copy"> + //*************************************************************************** + template + ETL_CONSTEXPR14 TRandomAccessIterator partial_sort_copy(TInputIterator first, TInputIterator last, TRandomAccessIterator d_first, + TRandomAccessIterator d_last, TCompare compare) + { + typedef typename etl::iterator_traits::value_type value_t; + typedef typename etl::iterator_traits::difference_type difference_t; + + TRandomAccessIterator result = d_first; + + // Fill the destination range + while ((first != last) && (result != d_last)) + { + *result = *first; + ++result; + ++first; + } + + if (result == d_first) + { + return result; + } + + // Build a max-heap over the destination range + etl::make_heap(d_first, result, compare); + + // Process remaining input elements + for (TInputIterator i = first; i != last; ++i) + { + if (compare(*i, *d_first)) + { + value_t value = *i; + private_heap::adjust_heap(d_first, difference_t(0), difference_t(result - d_first), ETL_MOVE(value), compare); + } + } + + etl::sort_heap(d_first, result, compare); + + return result; + } + + //*************************************************************************** + /// partial_sort_copy + ///\ingroup algorithm + ///< a + ///< href="http://en.cppreference.com/w/cpp/algorithm/partial_sort_copy"> + //*************************************************************************** + template + ETL_CONSTEXPR14 TRandomAccessIterator partial_sort_copy(TInputIterator first, TInputIterator last, TRandomAccessIterator d_first, + TRandomAccessIterator d_last) + { + typedef etl::less< typename etl::iterator_traits::value_type> compare; + + return etl::partial_sort_copy(first, last, d_first, d_last, compare()); + } + //*************************************************************************** // Search //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator1 search(TIterator1 first, TIterator1 last, TIterator2 search_first, TIterator2 search_last, TCompare compare) + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator1 search(TIterator1 first, TIterator1 last, TIterator2 search_first, TIterator2 search_last, TCompare compare) { while (true) { - TIterator1 itr = first; + TIterator1 itr = first; TIterator2 search_itr = search_first; while (true) @@ -1170,10 +1216,8 @@ namespace etl } // Search - template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator1 search(TIterator1 first, TIterator1 last, TIterator2 search_first, TIterator2 search_last) + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator1 search(TIterator1 first, TIterator1 last, TIterator2 search_first, TIterator2 search_last) { typedef etl::equal_to::value_type> compare; @@ -1185,48 +1229,51 @@ namespace etl //*************************************************************************** namespace private_algorithm { -#if ETL_USING_CPP11 //********************************* // For random access iterators template - ETL_CONSTEXPR14 - typename etl::enable_if::value, TIterator>::type - rotate_general(TIterator first, TIterator middle, TIterator last) + ETL_CONSTEXPR14 typename etl::enable_if::value, TIterator>::type + rotate_general(TIterator first, TIterator middle, TIterator last) { - if (first == middle || middle == last) + if (first == middle) + { + return last; + } + + if (middle == last) { return first; } - typedef typename etl::iterator_traits::value_type value_type; + typedef typename etl::iterator_traits::value_type value_type; + typedef typename etl::iterator_traits::difference_type difference_type; - int n = last - first; - int m = middle - first; - int gcd_nm = (n == 0 || m == 0) ? n + m : etl::gcd(n, m); + difference_type n = last - first; + difference_type m = middle - first; + difference_type gcd_nm = (n == 0 || m == 0) ? n + m : etl::gcd(n, m); + TIterator result = first + (last - middle); - TIterator result = first + (last - middle); - - for (int i = 0; i < gcd_nm; i++) + for (difference_type i = 0; i < gcd_nm; i++) { - value_type temp = ETL_MOVE(*(first + i)); - int j = i; - - while (true) + value_type temp = ETL_MOVE(*(first + i)); + difference_type j = i; + + while (true) { - int k = j + m; - + difference_type k = j + m; + if (k >= n) { k = k - n; } - + if (k == i) { break; } *(first + j) = ETL_MOVE(*(first + k)); - j = k; + j = k; } *(first + j) = ETL_MOVE(temp); @@ -1234,65 +1281,19 @@ namespace etl return result; } -#else - //********************************* - // For random access iterators - template - ETL_CONSTEXPR14 - typename etl::enable_if::value, TIterator>::type - rotate_general(TIterator first, TIterator middle, TIterator last) - { - if (first == middle || middle == last) - { - return first; - } - - typedef typename etl::iterator_traits::value_type value_type; - - int n = last - first; - int m = middle - first; - int gcd_nm = (n == 0 || m == 0) ? n + m : etl::gcd(n, m); - - TIterator result = first + (last - middle); - - for (int i = 0; i < gcd_nm; i++) - { - value_type temp = *(first + i); - int j = i; - - while (true) - { - int k = j + m; - - if (k >= n) - { - k = k - n; - } - - if (k == i) - { - break; - } - - *(first + j) = *(first + k); - j = k; - } - - *(first + j) = temp; - } - - return result; - } -#endif //********************************* // For bidirectional iterators template - ETL_CONSTEXPR14 - typename etl::enable_if::value, TIterator>::type + ETL_CONSTEXPR14 typename etl::enable_if::value, TIterator>::type rotate_general(TIterator first, TIterator middle, TIterator last) { - if (first == middle || middle == last) + if (first == middle) + { + return last; + } + + if (middle == last) { return first; } @@ -1310,16 +1311,20 @@ namespace etl //********************************* // For forward iterators template - ETL_CONSTEXPR14 - typename etl::enable_if::value, TIterator>::type - rotate_general(TIterator first, TIterator middle, TIterator last) + ETL_CONSTEXPR14 typename etl::enable_if::value, TIterator>::type rotate_general(TIterator first, TIterator middle, + TIterator last) { - if (first == middle || middle == last) + if (first == middle) + { + return last; + } + + if (middle == last) { return first; } - TIterator next = middle; + TIterator next = middle; TIterator result = first; etl::advance(result, etl::distance(middle, last)); @@ -1344,8 +1349,7 @@ namespace etl //********************************* // Simplified algorithm for rotate left by one template - ETL_CONSTEXPR14 - TIterator rotate_left_by_one(TIterator first, TIterator last) + ETL_CONSTEXPR14 TIterator rotate_left_by_one(TIterator first, TIterator last) { typedef typename etl::iterator_traits::value_type value_type; @@ -1365,13 +1369,12 @@ namespace etl //********************************* // Simplified for algorithm rotate right by one template - ETL_CONSTEXPR14 - TIterator rotate_right_by_one(TIterator first, TIterator last) + ETL_CONSTEXPR14 TIterator rotate_right_by_one(TIterator first, TIterator last) { typedef typename etl::iterator_traits::value_type value_type; // Save the last item. - TIterator previous = etl::prev(last); + TIterator previous = etl::prev(last); value_type temp(ETL_MOVE(*previous)); // Move the rest. @@ -1383,33 +1386,35 @@ namespace etl // The new position of the first item. return result; } - } + } // namespace private_algorithm //********************************* - template - ETL_CONSTEXPR14 - TIterator rotate(TIterator first, TIterator middle, TIterator last) + template + ETL_CONSTEXPR14 TIterator rotate(TIterator first, TIterator middle, TIterator last) { + if (first == middle) + { + return last; + } + if (middle == last) + { + return first; + } + if (etl::next(first) == middle) { return private_algorithm::rotate_left_by_one(first, last); } +#if ETL_USING_CPP20 if (etl::next(middle) == last) { -#if ETL_USING_CPP20 - if ETL_IF_CONSTEXPR(etl::is_forward_iterator::value) - { - return private_algorithm::rotate_general(first, middle, last); - } - else + if ETL_IF_CONSTEXPR (etl::is_bidirectional_iterator_concept< TIterator>::value) { return private_algorithm::rotate_right_by_one(first, last); } -#else - return private_algorithm::rotate_general(first, middle, last); -#endif } +#endif return private_algorithm::rotate_general(first, middle, last); } @@ -1419,11 +1424,7 @@ namespace etl //*************************************************************************** // Predicate template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator1 find_end(TIterator1 b, TIterator1 e, - TIterator2 sb, TIterator2 se, - TPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator1 find_end(TIterator1 b, TIterator1 e, TIterator2 sb, TIterator2 se, TPredicate predicate) { if (sb == se) { @@ -1443,7 +1444,7 @@ namespace etl else { result = new_result; - b = result; + b = result; ++b; } } @@ -1452,10 +1453,7 @@ namespace etl // Default template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator1 find_end(TIterator1 b, TIterator1 e, - TIterator2 sb, TIterator2 se) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator1 find_end(TIterator1 b, TIterator1 e, TIterator2 sb, TIterator2 se) { typedef etl::equal_to::value_type> predicate; @@ -1464,15 +1462,11 @@ namespace etl //*************************************************************************** /// Finds the iterator to the smallest element in the range (begin, end).
- /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/min_element"> ///\ingroup algorithm //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator min_element(TIterator begin, - TIterator end, - TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator min_element(TIterator begin, TIterator end, TCompare compare) { TIterator minimum = begin; @@ -1497,13 +1491,10 @@ namespace etl //*************************************************************************** /// min_element ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/min_element"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator min_element(TIterator begin, - TIterator end) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator min_element(TIterator begin, TIterator end) { typedef typename etl::iterator_traits::value_type value_t; @@ -1512,15 +1503,11 @@ namespace etl //*************************************************************************** /// Finds the iterator to the largest element in the range (begin, end).
- /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/max_element"> ///\ingroup algorithm //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator max_element(TIterator begin, - TIterator end, - TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator max_element(TIterator begin, TIterator end, TCompare compare) { TIterator maximum = begin; @@ -1545,13 +1532,10 @@ namespace etl //*************************************************************************** /// max_element ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/max_element"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator max_element(TIterator begin, - TIterator end) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator max_element(TIterator begin, TIterator end) { typedef typename etl::iterator_traits::value_type value_t; @@ -1560,15 +1544,11 @@ namespace etl //*************************************************************************** /// Finds the greatest and the smallest element in the range (begin, end).
- /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/minmax_element"> ///\ingroup algorithm //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - ETL_OR_STD::pair minmax_element(TIterator begin, - TIterator end, - TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR14 ETL_OR_STD::pair minmax_element(TIterator begin, TIterator end, TCompare compare) { TIterator minimum = begin; TIterator maximum = begin; @@ -1599,13 +1579,10 @@ namespace etl //*************************************************************************** /// minmax_element ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/minmax_element"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - ETL_OR_STD::pair minmax_element(TIterator begin, - TIterator end) + ETL_NODISCARD ETL_CONSTEXPR14 ETL_OR_STD::pair minmax_element(TIterator begin, TIterator end) { typedef typename etl::iterator_traits::value_type value_t; @@ -1615,13 +1592,10 @@ namespace etl //*************************************************************************** /// minmax ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/minmax"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - ETL_OR_STD::pair minmax(const T& a, - const T& b) + ETL_NODISCARD ETL_CONSTEXPR14 ETL_OR_STD::pair minmax(const T& a, const T& b) { return (b < a) ? ETL_OR_STD::pair(b, a) : ETL_OR_STD::pair(a, b); } @@ -1629,14 +1603,10 @@ namespace etl //*************************************************************************** /// minmax ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/minmax"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - ETL_OR_STD::pair minmax(const T& a, - const T& b, - TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR14 ETL_OR_STD::pair minmax(const T& a, const T& b, TCompare compare) { return compare(b, a) ? ETL_OR_STD::pair(b, a) : ETL_OR_STD::pair(a, b); } @@ -1644,43 +1614,10 @@ namespace etl //*************************************************************************** /// is_sorted_until ///\ingroup algorithm - /// - //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator is_sorted_until(TIterator begin, - TIterator end) - { - if (begin != end) - { - TIterator next = begin; - - while (++next != end) - { - if (*next < *begin) - { - return next; - } - - ++begin; - } - } - - return end; - } - - //*************************************************************************** - /// is_sorted_until - ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted_until"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator is_sorted_until(TIterator begin, - TIterator end, - TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator is_sorted_until(TIterator begin, TIterator end, TCompare compare) { if (begin != end) { @@ -1700,16 +1637,26 @@ namespace etl return end; } + //*************************************************************************** + /// is_sorted_until + ///\ingroup algorithm + ///< a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted_until"> + //*************************************************************************** + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator is_sorted_until(TIterator begin, TIterator end) + { + typedef etl::less::value_type> compare; + + return etl::is_sorted_until(begin, end, compare()); + } + //*************************************************************************** /// is_sorted ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted"> //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool is_sorted(TIterator begin, - TIterator end) + template + ETL_NODISCARD ETL_CONSTEXPR14 bool is_sorted(TIterator begin, TIterator end) { return etl::is_sorted_until(begin, end) == end; } @@ -1717,14 +1664,10 @@ namespace etl //*************************************************************************** /// is_sorted ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted"> //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool is_sorted(TIterator begin, - TIterator end, - TCompare compare) + template + ETL_NODISCARD ETL_CONSTEXPR14 bool is_sorted(TIterator begin, TIterator end, TCompare compare) { return etl::is_sorted_until(begin, end, compare) == end; } @@ -1734,11 +1677,7 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator is_unique_sorted_until(TIterator begin, - TIterator end, - TCompare compare) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator is_unique_sorted_until(TIterator begin, TIterator end, TCompare compare) { if (begin != end) { @@ -1763,38 +1702,19 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator is_unique_sorted_until(TIterator begin, - TIterator end) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator is_unique_sorted_until(TIterator begin, TIterator end) { - if (begin != end) - { - TIterator next = begin; + typedef etl::less::value_type> compare; - while (++next != end) - { - if (!(*begin < *next)) - { - return next; - } - - ++begin; - } - } - - return end; + return etl::is_unique_sorted_until(begin, end, compare()); } //*************************************************************************** /// is_unique_sorted ///\ingroup algorithm //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool is_unique_sorted(TIterator begin, - TIterator end) + template + ETL_NODISCARD ETL_CONSTEXPR14 bool is_unique_sorted(TIterator begin, TIterator end) { return etl::is_unique_sorted_until(begin, end) == end; } @@ -1803,12 +1723,8 @@ namespace etl /// is_unique_sorted ///\ingroup algorithm //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool is_unique_sorted(TIterator begin, - TIterator end, - TCompare compare) + template + ETL_NODISCARD ETL_CONSTEXPR14 bool is_unique_sorted(TIterator begin, TIterator end, TCompare compare) { return etl::is_unique_sorted_until(begin, end, compare) == end; } @@ -1816,14 +1732,10 @@ namespace etl //*************************************************************************** /// find_if_not ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/find"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator find_if_not(TIterator begin, - TIterator end, - TUnaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator find_if_not(TIterator begin, TIterator end, TUnaryPredicate predicate) { while (begin != end) { @@ -1838,17 +1750,54 @@ namespace etl return end; } + //*************************************************************************** + /// adjacent_find + ///\ingroup algorithm + ///< a href="http://en.cppreference.com/w/cpp/algorithm/adjacent_find"> + //*************************************************************************** + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator adjacent_find(TIterator first, TIterator last, TBinaryPredicate predicate) + { + if (first != last) + { + TIterator next = first; + ++next; + + while (next != last) + { + if (predicate(*first, *next)) + { + return first; + } + + ++first; + ++next; + } + } + + return last; + } + + //*************************************************************************** + /// adjacent_find + ///\ingroup algorithm + ///< a href="http://en.cppreference.com/w/cpp/algorithm/adjacent_find"> + //*************************************************************************** + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator adjacent_find(TIterator first, TIterator last) + { + typedef etl::equal_to::value_type> predicate; + + return etl::adjacent_find(first, last, predicate()); + } + //*************************************************************************** /// is_permutation ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool is_permutation(TIterator1 begin1, - TIterator1 end1, - TIterator2 begin2) + ETL_NODISCARD ETL_CONSTEXPR14 bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2) { if (begin1 != end1) { @@ -1860,7 +1809,7 @@ namespace etl { if (i == etl::find(begin1, i, *i)) { - size_t n = etl::count(begin2, end2, *i); + size_t n = static_cast(etl::count(begin2, end2, *i)); if (n == 0 || size_t(etl::count(i, end1, *i)) != n) { @@ -1876,15 +1825,10 @@ namespace etl //*************************************************************************** /// is_permutation ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool is_permutation(TIterator1 begin1, - TIterator1 end1, - TIterator2 begin2, - TBinaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2, TBinaryPredicate predicate) { if (begin1 != end1) { @@ -1894,11 +1838,12 @@ namespace etl for (TIterator1 i = begin1; i != end1; ++i) { - if (i == etl::find_if(begin1, i, etl::bind1st(predicate, *i))) + const typename etl::binder1st predicate_is_i = etl::bind1st(predicate, *i); + if (i == etl::find_if(begin1, i, predicate_is_i)) { - size_t n = etl::count(begin2, end2, *i); + size_t n = static_cast(etl::count_if(begin2, end2, predicate_is_i)); - if (n == 0 || size_t(etl::count(i, end1, *i)) != n) + if (n == 0 || size_t(etl::count_if(i, end1, predicate_is_i)) != n) { return false; } @@ -1912,23 +1857,23 @@ namespace etl //*************************************************************************** /// is_permutation ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool is_permutation(TIterator1 begin1, - TIterator1 end1, - TIterator2 begin2, - TIterator2 end2) + ETL_NODISCARD ETL_CONSTEXPR14 bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2, TIterator2 end2) { + if (etl::distance(begin1, end1) != etl::distance(begin2, end2)) + { + return false; + } + if (begin1 != end1) { for (TIterator1 i = begin1; i != end1; ++i) { if (i == etl::find(begin1, i, *i)) { - size_t n = etl::count(begin2, end2, *i); + size_t n = static_cast(etl::count(begin2, end2, *i)); if (n == 0 || size_t(etl::count(i, end1, *i)) != n) { @@ -1944,25 +1889,26 @@ namespace etl //*************************************************************************** /// is_permutation ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"> //*************************************************************************** template - ETL_NODISCARD - bool is_permutation(TIterator1 begin1, - TIterator1 end1, - TIterator2 begin2, - TIterator2 end2, - TBinaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2, TIterator2 end2, TBinaryPredicate predicate) { + if (etl::distance(begin1, end1) != etl::distance(begin2, end2)) + { + return false; + } + if (begin1 != end1) { for (TIterator1 i = begin1; i != end1; ++i) { - if (i == etl::find_if(begin1, i, etl::bind1st(predicate, *i))) + const typename etl::binder1st predicate_is_i = etl::bind1st(predicate, *i); + if (i == etl::find_if(begin1, i, predicate_is_i)) { - size_t n = etl::count(begin2, end2, *i); + size_t n = static_cast(etl::count_if(begin2, end2, predicate_is_i)); - if (n == 0 || size_t(etl::count(i, end1, *i)) != n) + if (n == 0 || size_t(etl::count_if(i, end1, predicate_is_i)) != n) { return false; } @@ -1973,17 +1919,135 @@ namespace etl return true; } + //*************************************************************************** + /// next_permutation + ///\ingroup algorithm + ///< a href="http://en.cppreference.com/w/cpp/algorithm/next_permutation"> + //*************************************************************************** + template + ETL_CONSTEXPR14 bool next_permutation(TIterator first, TIterator last, TCompare compare) + { + if (first == last) + { + return false; + } + + TIterator i = last; + --i; + + if (first == i) + { + return false; + } + + while (true) + { + TIterator i1 = i; + --i; + + if (compare(*i, *i1)) + { + TIterator j = last; + --j; + + while (!compare(*i, *j)) + { + --j; + } + + etl::iter_swap(i, j); + etl::reverse(i1, last); + return true; + } + + if (i == first) + { + etl::reverse(first, last); + return false; + } + } + } + + //*************************************************************************** + /// next_permutation + ///\ingroup algorithm + ///< a href="http://en.cppreference.com/w/cpp/algorithm/next_permutation"> + //*************************************************************************** + template + ETL_CONSTEXPR14 bool next_permutation(TIterator first, TIterator last) + { + typedef etl::less::value_type> compare; + return etl::next_permutation(first, last, compare()); + } + + //*************************************************************************** + /// prev_permutation + ///\ingroup algorithm + ///< a href="http://en.cppreference.com/w/cpp/algorithm/prev_permutation"> + //*************************************************************************** + template + ETL_CONSTEXPR14 bool prev_permutation(TIterator first, TIterator last, TCompare compare) + { + if (first == last) + { + return false; + } + + TIterator i = last; + --i; + + if (first == i) + { + return false; + } + + while (true) + { + TIterator i1 = i; + --i; + + if (compare(*i1, *i)) + { + TIterator j = last; + --j; + + while (!compare(*j, *i)) + { + --j; + } + + etl::iter_swap(i, j); + etl::reverse(i1, last); + return true; + } + + if (i == first) + { + etl::reverse(first, last); + return false; + } + } + } + + //*************************************************************************** + /// prev_permutation + ///\ingroup algorithm + ///< a href="http://en.cppreference.com/w/cpp/algorithm/prev_permutation"> + //*************************************************************************** + template + ETL_CONSTEXPR14 bool prev_permutation(TIterator first, TIterator last) + { + typedef etl::less::value_type> compare; + return etl::prev_permutation(first, last, compare()); + } + //*************************************************************************** /// is_partitioned ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/is_partitioned"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool is_partitioned(TIterator begin, - TIterator end, - TUnaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 bool is_partitioned(TIterator begin, TIterator end, TUnaryPredicate predicate) { while (begin != end) { @@ -2010,24 +2074,28 @@ namespace etl //*************************************************************************** /// partition_point - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/partition_point"> ///\ingroup algorithm //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator partition_point(TIterator begin, - TIterator end, - TUnaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator partition_point(TIterator begin, TIterator end, TUnaryPredicate predicate) { - while (begin != end) - { - if (!predicate(*begin)) - { - return begin; - } + typedef typename etl::iterator_traits::difference_type difference_t; - ++begin; + // binary search on a partitioned range + for (difference_t length = etl::distance(begin, end); 0 < length;) + { + difference_t half = length / 2; + TIterator middle = etl::next(begin, half); + if (predicate(*middle)) + { + begin = etl::next(middle); + length -= (half + 1); + } + else + { + length = half; + } } return begin; @@ -2036,16 +2104,12 @@ namespace etl //*************************************************************************** /// Copies the elements from the range (begin, end) to two different ranges /// depending on the value returned by the predicate.
- /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/partition_copy"> ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - ETL_OR_STD::pair partition_copy(TSource begin, - TSource end, - TDestinationTrue destination_true, - TDestinationFalse destination_false, - TUnaryPredicate predicate) + ETL_CONSTEXPR14 ETL_OR_STD::pair partition_copy(TSource begin, TSource end, TDestinationTrue destination_true, + TDestinationFalse destination_false, TUnaryPredicate predicate) { while (begin != end) { @@ -2069,14 +2133,10 @@ namespace etl //*************************************************************************** /// copy_if ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/copy"> //*************************************************************************** template - ETL_CONSTEXPR14 - TOutputIterator copy_if(TIterator begin, - TIterator end, - TOutputIterator out, - TUnaryPredicate predicate) + ETL_CONSTEXPR14 TOutputIterator copy_if(TIterator begin, TIterator end, TOutputIterator out, TUnaryPredicate predicate) { while (begin != end) { @@ -2095,14 +2155,10 @@ namespace etl //*************************************************************************** /// all_of ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/all_any_none_of"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool all_of(TIterator begin, - TIterator end, - TUnaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 bool all_of(TIterator begin, TIterator end, TUnaryPredicate predicate) { return etl::find_if_not(begin, end, predicate) == end; } @@ -2110,14 +2166,10 @@ namespace etl //*************************************************************************** /// any_of ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/all_any_none_of"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool any_of(TIterator begin, - TIterator end, - TUnaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 bool any_of(TIterator begin, TIterator end, TUnaryPredicate predicate) { return etl::find_if(begin, end, predicate) != end; } @@ -2125,14 +2177,10 @@ namespace etl //*************************************************************************** /// none_of ///\ingroup algorithm - /// + ///< a href="http://en.cppreference.com/w/cpp/algorithm/all_any_none_of"> //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - bool none_of(TIterator begin, - TIterator end, - TUnaryPredicate predicate) + ETL_NODISCARD ETL_CONSTEXPR14 bool none_of(TIterator begin, TIterator end, TUnaryPredicate predicate) { return etl::find_if(begin, end, predicate) == end; } @@ -2232,15 +2280,14 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - T accumulate(TIterator first, TIterator last, T sum) + ETL_CONSTEXPR14 T accumulate(TIterator first, TIterator last, T sum) { while (first != last) { - sum = ETL_MOVE(sum) + *first; + sum = static_cast(ETL_MOVE(sum) + static_cast(*first)); ++first; } - + return sum; } @@ -2249,8 +2296,7 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - T accumulate(TIterator first, TIterator last, T sum, TBinaryOperation operation) + ETL_CONSTEXPR14 T accumulate(TIterator first, TIterator last, T sum, TBinaryOperation operation) { while (first != last) { @@ -2265,30 +2311,26 @@ namespace etl /// Clamp values. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR - T clamp(const T& value, const T& low, const T& high, TCompare compare) + template + ETL_CONSTEXPR T clamp(const T& value, const T& low, const T& high, TCompare compare) { return compare(value, low) ? low : compare(high, value) ? high : value; } - + template - ETL_CONSTEXPR - T clamp(const T& value, const T& low, const T& high) + ETL_CONSTEXPR T clamp(const T& value, const T& low, const T& high) { return clamp(value, low, high, etl::less()); } - template - ETL_CONSTEXPR - T clamp(const T& value, TCompare compare) + template + ETL_CONSTEXPR T clamp(const T& value, TCompare compare) { return compare(value, Low) ? Low : compare(High, value) ? High : value; } template - ETL_CONSTEXPR - T clamp(const T& value) + ETL_CONSTEXPR T clamp(const T& value) { return clamp(value, etl::less()); } @@ -2298,9 +2340,8 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - TIterator remove(TIterator first, TIterator last, const T& value) - { + ETL_CONSTEXPR14 TIterator remove(TIterator first, TIterator last, const T& value) + { first = etl::find(first, last, value); if (first != last) @@ -2315,7 +2356,7 @@ namespace etl } } } - + return first; } @@ -2324,8 +2365,7 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - TIterator remove_if(TIterator first, TIterator last, TUnaryPredicate predicate) + ETL_CONSTEXPR14 TIterator remove_if(TIterator first, TIterator last, TUnaryPredicate predicate) { first = etl::find_if(first, last, predicate); @@ -2342,9 +2382,238 @@ namespace etl } } - return first; + return first; } -} + + //*************************************************************************** + /// unique + /// see https://en.cppreference.com/w/cpp/algorithm/unique + ///\ingroup algorithm + //*************************************************************************** + template + ETL_CONSTEXPR14 TIterator unique(TIterator first, TIterator last) + { + if (first == last) + { + return last; + } + + TIterator result = first; + + while (++first != last) + { + if (!(*result == *first) && (++result != first)) + { + *result = ETL_MOVE(*first); + } + } + + return ++result; + } + + //*************************************************************************** + /// unique + /// see https://en.cppreference.com/w/cpp/algorithm/unique + /// predicate overload to determine equality. + ///\ingroup algorithm + //*************************************************************************** + template + ETL_CONSTEXPR14 TIterator unique(TIterator first, TIterator last, TBinaryPredicate predicate) + { + if (first == last) + { + return last; + } + + TIterator result = first; + + while (++first != last) + { + if (!predicate(*result, *first) && (++result != first)) + { + *result = ETL_MOVE(*first); + } + } + + return ++result; + } + + //*************************************************************************** + /// unique_copy + /// see https://en.cppreference.com/w/cpp/algorithm/unique_copy + ///\ingroup algorithm + //*************************************************************************** + template + ETL_CONSTEXPR14 TOutputIterator unique_copy(TInputIterator first, TInputIterator last, TOutputIterator d_first) + { + if (first == last) + { + return d_first; + } + + typename etl::iterator_traits::value_type prev = *first; + *d_first = prev; + + while (++first != last) + { + if (!(prev == *first)) + { + prev = *first; + *(++d_first) = prev; + } + } + + return ++d_first; + } + + //*************************************************************************** + /// unique_copy + /// see https://en.cppreference.com/w/cpp/algorithm/unique_copy + /// predicate overload to determine equality. + ///\ingroup algorithm + //*************************************************************************** + template + ETL_CONSTEXPR14 TOutputIterator unique_copy(TInputIterator first, TInputIterator last, TOutputIterator d_first, TBinaryPredicate predicate) + { + if (first == last) + { + return d_first; + } + + typename etl::iterator_traits::value_type prev = *first; + *d_first = prev; + + while (++first != last) + { + if (!predicate(prev, *first)) + { + prev = *first; + *(++d_first) = prev; + } + } + + return ++d_first; + } + + //*************************************************************************** + /// merge + /// Merges two sorted ranges into one sorted range. + /// see https://en.cppreference.com/w/cpp/algorithm/merge + ///\ingroup algorithm + //*************************************************************************** + template + ETL_CONSTEXPR14 TOutputIterator merge(TInputIterator1 first1, TInputIterator1 last1, TInputIterator2 first2, TInputIterator2 last2, + TOutputIterator d_first, TCompare compare) + { + while ((first1 != last1) && (first2 != last2)) + { + if (compare(*first2, *first1)) + { + *d_first = *first2; + ++first2; + } + else + { + *d_first = *first1; + ++first1; + } + ++d_first; + } + + d_first = etl::copy(first1, last1, d_first); + d_first = etl::copy(first2, last2, d_first); + + return d_first; + } + + //*************************************************************************** + /// merge + /// Merges two sorted ranges into one sorted range. + /// Uses operator< for comparison. + /// see https://en.cppreference.com/w/cpp/algorithm/merge + ///\ingroup algorithm + //*************************************************************************** + template + ETL_CONSTEXPR14 TOutputIterator merge(TInputIterator1 first1, TInputIterator1 last1, TInputIterator2 first2, TInputIterator2 last2, + TOutputIterator d_first) + { + typedef etl::less< typename etl::iterator_traits::value_type> compare; + + return etl::merge(first1, last1, first2, last2, d_first, compare()); + } + + //*************************************************************************** + /// inplace_merge + /// Merges two consecutive sorted ranges [first, middle) and [middle, last) + /// into one sorted range [first, last) in-place. + /// Uses an iterative rotate-based algorithm that requires no additional + /// memory, no recursion and no explicit stack, making it safe for deeply + /// embedded targets with constrained stack sizes. + /// Complexity: O(N log N) comparisons, O(N log N) element moves. + /// see https://en.cppreference.com/w/cpp/algorithm/inplace_merge + ///\ingroup algorithm + //*************************************************************************** + template + void inplace_merge(TBidirectionalIterator first, TBidirectionalIterator middle, TBidirectionalIterator last, TCompare compare) + { + typedef typename etl::iterator_traits::difference_type difference_type; + + difference_type len1 = etl::distance(first, middle); + difference_type len2 = etl::distance(middle, last); + + while ((len1 != 0) && (len2 != 0)) + { + // Find where the first element of the right half belongs in the left + // half. All elements in [first, cut1) are <= *middle, so they are already + // in place. + TBidirectionalIterator cut1 = etl::upper_bound(first, middle, *middle, compare); + difference_type prefix = etl::distance(first, cut1); + len1 -= prefix; + + // If the entire left half is <= *middle, we are done. + if (len1 == 0) + { + return; + } + + // Advance first past the already-placed prefix. + first = cut1; + + // Find where the first element of the (remaining) left half belongs in + // the right half. All elements in [middle, cut2) are < *first, so they + // need to be moved before *first. + TBidirectionalIterator cut2 = etl::lower_bound(middle, last, *first, compare); + difference_type run = etl::distance(middle, cut2); + len2 -= run; + + // Rotate the block [first, middle, cut2) so that [middle, cut2) moves + // before [first, middle). After the rotate the elements from + // [middle, cut2) (length = run) now occupy [first, first + run) and + // are in their final position. + etl::rotate(first, middle, cut2); + + // Advance past the block we just placed. + etl::advance(first, run); + middle = cut2; + } + } + + //*************************************************************************** + /// inplace_merge + /// Merges two consecutive sorted ranges [first, middle) and [middle, last) + /// into one sorted range [first, last) in-place. + /// Uses operator< for comparison. + /// see https://en.cppreference.com/w/cpp/algorithm/inplace_merge + ///\ingroup algorithm + //*************************************************************************** + template + void inplace_merge(TBidirectionalIterator first, TBidirectionalIterator middle, TBidirectionalIterator last) + { + typedef etl::less< typename etl::iterator_traits::value_type> compare; + + etl::inplace_merge(first, middle, last, compare()); + } +} // namespace etl //***************************************************************************** // ETL extensions to the STL algorithms. @@ -2362,27 +2631,22 @@ namespace etl ///\param o_end End of the output range. ///\ingroup algorithm //*************************************************************************** - template + template ETL_CONSTEXPR14 - typename etl::enable_if::value && - etl::is_random_iterator::value, TOutputIterator>::type - copy_s(TInputIterator i_begin, - TInputIterator i_end, - TOutputIterator o_begin, - TOutputIterator o_end) + typename etl::enable_if< etl::is_random_iterator::value && etl::is_random_iterator::value, TOutputIterator>::type + copy_s(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TOutputIterator o_end) { typedef typename iterator_traits::difference_type s_size_type; typedef typename iterator_traits::difference_type d_size_type; #if ETL_USING_CPP11 - typedef typename etl::common_type::type min_size_type; + typedef typename etl::common_type::type min_size_type; #else - typedef typename etl::largest_type::type min_size_type; + typedef typename etl::largest_type::type min_size_type; #endif - s_size_type s_size = etl::distance(i_begin, i_end); - d_size_type d_size = etl::distance(o_begin, o_end); + s_size_type s_size = etl::distance(i_begin, i_end); + d_size_type d_size = etl::distance(o_begin, o_end); min_size_type min_size = etl::min(s_size, d_size); return etl::copy(i_begin, i_begin + min_size, o_begin); @@ -2399,15 +2663,10 @@ namespace etl ///\param o_end End of the output range. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - typename etl::enable_if::value || - !etl::is_random_iterator::value, TOutputIterator>::type - copy_s(TInputIterator i_begin, - TInputIterator i_end, - TOutputIterator o_begin, - TOutputIterator o_end) + template + ETL_CONSTEXPR14 typename etl::enable_if< !etl::is_random_iterator::value || !etl::is_random_iterator::value, + TOutputIterator>::type + copy_s(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TOutputIterator o_end) { while ((i_begin != i_end) && (o_begin != o_end)) { @@ -2424,14 +2683,8 @@ namespace etl /// A safer form of copy_n where the smallest of the two ranges is used. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TOutputIterator copy_n_s(TInputIterator i_begin, - TSize n, - TOutputIterator o_begin, - TOutputIterator o_end) + template + ETL_CONSTEXPR14 TOutputIterator copy_n_s(TInputIterator i_begin, TSize n, TOutputIterator o_begin, TOutputIterator o_end) { while ((n-- > 0) && (o_begin != o_end)) { @@ -2448,15 +2701,8 @@ namespace etl /// A safer form of copy_n where the smallest of the two ranges is used. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TOutputIterator copy_n_s(TInputIterator i_begin, - TSize1 n1, - TOutputIterator o_begin, - TSize2 n2) + template + ETL_CONSTEXPR14 TOutputIterator copy_n_s(TInputIterator i_begin, TSize1 n1, TOutputIterator o_begin, TSize2 n2) { while ((n1-- > 0) && (n2-- > 0)) { @@ -2470,19 +2716,13 @@ namespace etl //*************************************************************************** /// copy_if - /// A safer form of copy_if where it terminates when the first end iterator is reached. - /// There is currently no STL equivalent. + /// A safer form of copy_if where it terminates when the first end iterator is + /// reached. There is currently no STL equivalent. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TOutputIterator copy_if_s(TInputIterator i_begin, - TInputIterator i_end, - TOutputIterator o_begin, - TOutputIterator o_end, - TUnaryPredicate predicate) + template + ETL_CONSTEXPR14 TOutputIterator copy_if_s(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TOutputIterator o_end, + TUnaryPredicate predicate) { while ((i_begin != i_end) && (o_begin != o_end)) { @@ -2502,16 +2742,9 @@ namespace etl /// copy_n_if /// Combination of copy_n and copy_if. ///\ingroup algorithm - //*************************************************************************** - template - ETL_CONSTEXPR14 - TOutputIterator copy_n_if(TInputIterator i_begin, - TSize n, - TOutputIterator o_begin, - TUnaryPredicate predicate) + //*************************************************************************** + template + ETL_CONSTEXPR14 TOutputIterator copy_n_if(TInputIterator i_begin, TSize n, TOutputIterator o_begin, TUnaryPredicate predicate) { while (n-- > 0) { @@ -2541,19 +2774,15 @@ namespace etl //*************************************************************************** template ETL_CONSTEXPR14 - typename etl::enable_if::value && - etl::is_random_iterator::value, TOutputIterator>::type - move_s(TInputIterator i_begin, - TInputIterator i_end, - TOutputIterator o_begin, - TOutputIterator o_end) + typename etl::enable_if< etl::is_random_iterator::value && etl::is_random_iterator::value, TOutputIterator>::type + move_s(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TOutputIterator o_end) { - using s_size_type = typename iterator_traits::difference_type; - using d_size_type = typename iterator_traits::difference_type; + using s_size_type = typename iterator_traits::difference_type; + using d_size_type = typename iterator_traits::difference_type; using min_size_type = typename etl::common_type::type; - s_size_type s_size = etl::distance(i_begin, i_end); - d_size_type d_size = etl::distance(o_begin, o_end); + s_size_type s_size = etl::distance(i_begin, i_end); + d_size_type d_size = etl::distance(o_begin, o_end); min_size_type min_size = etl::min(s_size, d_size); return etl::move(i_begin, i_begin + min_size, o_begin); @@ -2571,13 +2800,9 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - typename etl::enable_if::value || - !etl::is_random_iterator::value, TOutputIterator>::type - move_s(TInputIterator i_begin, - TInputIterator i_end, - TOutputIterator o_begin, - TOutputIterator o_end) + ETL_CONSTEXPR14 typename etl::enable_if< !etl::is_random_iterator::value || !etl::is_random_iterator::value, + TOutputIterator>::type + move_s(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TOutputIterator o_end) { while ((i_begin != i_end) && (o_begin != o_end)) { @@ -2602,10 +2827,7 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - TOutputIterator move_s(TInputIterator i_begin, - TInputIterator i_end, - TOutputIterator o_begin, - TOutputIterator o_end) + TOutputIterator move_s(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TOutputIterator o_end) { // Move not supported. Defer to copy. return etl::copy_s(i_begin, i_end, o_begin, o_end); @@ -2615,14 +2837,11 @@ namespace etl //*************************************************************************** /// binary_find ///\ingroup algorithm - /// Does a binary search and returns an iterator to the value or end if not found. + /// Does a binary search and returns an iterator to the value or end if not + /// found. //*************************************************************************** template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator binary_find(TIterator begin, - TIterator end, - const TValue& value) + ETL_NODISCARD ETL_CONSTEXPR14 TIterator binary_find(TIterator begin, TIterator end, const TValue& value) { TIterator it = etl::lower_bound(begin, end, value); @@ -2637,19 +2856,11 @@ namespace etl //*************************************************************************** /// binary_find ///\ingroup algorithm - /// Does a binary search and returns an iterator to the value or end if not found. + /// Does a binary search and returns an iterator to the value or end if not + /// found. //*************************************************************************** - template - ETL_NODISCARD - ETL_CONSTEXPR14 - TIterator binary_find(TIterator begin, - TIterator end, - const TValue& value, - TBinaryPredicate predicate, - TBinaryEquality equality) + template + ETL_NODISCARD ETL_CONSTEXPR14 TIterator binary_find(TIterator begin, TIterator end, const TValue& value, TBinaryPredicate predicate, TBinaryEquality equality) { TIterator it = etl::lower_bound(begin, end, value, predicate); @@ -2665,14 +2876,8 @@ namespace etl /// Like std::for_each but applies a predicate before calling the function. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TUnaryFunction for_each_if(TIterator begin, - const TIterator end, - TUnaryFunction function, - TUnaryPredicate predicate) + template + ETL_CONSTEXPR14 TUnaryFunction for_each_if(TIterator begin, const TIterator end, TUnaryFunction function, TUnaryPredicate predicate) { while (begin != end) { @@ -2691,13 +2896,8 @@ namespace etl /// Like std::for_each but for 'n' iterations. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TIterator for_each_n(TIterator begin, - TSize n, - TUnaryFunction function) + template + ETL_CONSTEXPR14 TIterator for_each_n(TIterator begin, TSize n, TUnaryFunction function) { while (n-- > 0) { @@ -2709,18 +2909,12 @@ namespace etl } //*************************************************************************** - /// Like std::for_each but applies a predicate before calling the function, for 'n' iterations + /// Like std::for_each but applies a predicate before calling the function, + /// for 'n' iterations ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TIterator for_each_n_if(TIterator begin, - TSize n, - TUnaryFunction function, - TUnaryPredicate predicate) + template + ETL_CONSTEXPR14 TIterator for_each_n_if(TIterator begin, TSize n, TUnaryFunction function, TUnaryPredicate predicate) { while (n-- > 0) { @@ -2742,12 +2936,8 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - TOutputIterator transform_s(TInputIterator i_begin, - TInputIterator i_end, - TOutputIterator o_begin, - TOutputIterator o_end, - TUnaryFunction function) + ETL_CONSTEXPR14 TOutputIterator transform_s(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TOutputIterator o_end, + TUnaryFunction function) { while ((i_begin != i_end) && (o_begin != o_end)) { @@ -2765,15 +2955,8 @@ namespace etl /// There is currently no STL equivalent. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - void transform_n(TInputIterator i_begin, - TSize n, - TOutputIterator o_begin, - TUnaryFunction function) + template + ETL_CONSTEXPR14 void transform_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin, TUnaryFunction function) { TInputIterator i_end(i_begin); etl::advance(i_end, n); @@ -2787,17 +2970,8 @@ namespace etl /// There is currently no STL equivalent. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - void transform_n(TInputIterator1 i_begin1, - TInputIterator2 i_begin2, - TSize n, - TOutputIterator o_begin, - TBinaryFunction function) + template + ETL_CONSTEXPR14 void transform_n(TInputIterator1 i_begin1, TInputIterator2 i_begin2, TSize n, TOutputIterator o_begin, TBinaryFunction function) { TInputIterator1 i_end1(i_begin1); etl::advance(i_end1, n); @@ -2809,16 +2983,9 @@ namespace etl /// Like std::transform but applies a predicate before calling the function. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TOutputIterator transform_if(TInputIterator i_begin, - const TInputIterator i_end, - TOutputIterator o_begin, - TUnaryFunction function, - TUnaryPredicate predicate) + template + ETL_CONSTEXPR14 TOutputIterator transform_if(TInputIterator i_begin, const TInputIterator i_end, TOutputIterator o_begin, TUnaryFunction function, + TUnaryPredicate predicate) { while (i_begin != i_end) { @@ -2838,18 +3005,9 @@ namespace etl /// Like etl::transform_if but inputs from two ranges. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TOutputIterator transform_if(TInputIterator1 i_begin1, - const TInputIterator1 i_end1, - TInputIterator2 i_begin2, - TOutputIterator o_begin, - TBinaryFunction function, - TBinaryPredicate predicate) + template + ETL_CONSTEXPR14 TOutputIterator transform_if(TInputIterator1 i_begin1, const TInputIterator1 i_end1, TInputIterator2 i_begin2, TOutputIterator o_begin, + TBinaryFunction function, TBinaryPredicate predicate) { while (i_begin1 != i_end1) { @@ -2870,17 +3028,9 @@ namespace etl /// Like std::transform_if, for 'n' items. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TOutputIterator transform_n_if(TInputIterator i_begin, - TSize n, - TOutputIterator o_begin, - TUnaryFunction function, - TUnaryPredicate predicate) + template + ETL_CONSTEXPR14 TOutputIterator transform_n_if(TInputIterator i_begin, TSize n, TOutputIterator o_begin, TUnaryFunction function, + TUnaryPredicate predicate) { while (n-- > 0) { @@ -2900,19 +3050,10 @@ namespace etl /// Like etl::transform_if but inputs from two ranges for 'n' items. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - TOutputIterator transform_n_if(TInputIterator1 i_begin1, - TInputIterator2 i_begin2, - TSize n, - TOutputIterator o_begin, - TBinaryFunction function, - TBinaryPredicate predicate) + ETL_CONSTEXPR14 TOutputIterator transform_n_if(TInputIterator1 i_begin1, TInputIterator2 i_begin2, TSize n, TOutputIterator o_begin, + TBinaryFunction function, TBinaryPredicate predicate) { while (n-- > 0) { @@ -2929,21 +3070,15 @@ namespace etl } //*************************************************************************** - /// Transforms the elements from the range (begin, end) to two different ranges - /// depending on the value returned by the predicate.
+ /// Transforms the elements from the range (begin, end) to two different + /// ranges depending on the value returned by the predicate.
///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - ETL_OR_STD::pair partition_transform(TSource begin, - TSource end, - TDestinationTrue destination_true, - TDestinationFalse destination_false, - TUnaryFunctionTrue function_true, - TUnaryFunctionFalse function_false, - TUnaryPredicate predicate) + ETL_CONSTEXPR14 ETL_OR_STD::pair + partition_transform(TSource begin, TSource end, TDestinationTrue destination_true, TDestinationFalse destination_false, + TUnaryFunctionTrue function_true, TUnaryFunctionFalse function_false, TUnaryPredicate predicate) { while (begin != end) { @@ -2969,22 +3104,11 @@ namespace etl /// to two different ranges depending on the value returned by the predicate. ///\ingroup algorithm //*************************************************************************** - template - ETL_CONSTEXPR14 - ETL_OR_STD::pair partition_transform(TSource1 begin1, - TSource1 end1, - TSource2 begin2, - TDestinationTrue destination_true, - TDestinationFalse destination_false, - TBinaryFunctionTrue function_true, - TBinaryFunctionFalse function_false, - TBinaryPredicate predicate) + template + ETL_CONSTEXPR14 ETL_OR_STD::pair + partition_transform(TSource1 begin1, TSource1 end1, TSource2 begin2, TDestinationTrue destination_true, TDestinationFalse destination_false, + TBinaryFunctionTrue function_true, TBinaryFunctionFalse function_false, TBinaryPredicate predicate) { while (begin1 != end1) { @@ -3017,7 +3141,8 @@ namespace etl #else ETL_CONSTEXPR14 #endif - void shell_sort(TIterator first, TIterator last, TCompare compare) + void + shell_sort(TIterator first, TIterator last, TCompare compare) { if (first == last) { @@ -3059,7 +3184,8 @@ namespace etl #else ETL_CONSTEXPR14 #endif - void shell_sort(TIterator first, TIterator last) + void + shell_sort(TIterator first, TIterator last) { etl::shell_sort(first, last, etl::less::value_type>()); } @@ -3070,8 +3196,7 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - void insertion_sort(TIterator first, TIterator last, TCompare compare) + ETL_CONSTEXPR14 void insertion_sort(TIterator first, TIterator last, TCompare compare) { for (TIterator itr = first; itr != last; ++itr) { @@ -3084,8 +3209,7 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - void insertion_sort(TIterator first, TIterator last) + ETL_CONSTEXPR14 void insertion_sort(TIterator first, TIterator last) { etl::insertion_sort(first, last, etl::less::value_type>()); } @@ -3094,9 +3218,7 @@ namespace etl namespace private_algorithm { template - ETL_CONSTEXPR14 - typename etl::enable_if::value, TIterator>::type - get_before_last(TIterator first_, TIterator last_) + ETL_CONSTEXPR14 typename etl::enable_if::value, TIterator>::type get_before_last(TIterator first_, TIterator last_) { TIterator last = first_; TIterator lastplus1 = first_; @@ -3112,9 +3234,8 @@ namespace etl } template - ETL_CONSTEXPR14 - typename etl::enable_if::value, TIterator>::type - get_before_last(TIterator /*first_*/, TIterator last_) + ETL_CONSTEXPR14 typename etl::enable_if::value, TIterator>::type get_before_last(TIterator /*first_*/, + TIterator last_) { TIterator last = last_; --last; @@ -3123,13 +3244,12 @@ namespace etl } template - ETL_CONSTEXPR14 - typename etl::enable_if::value, TIterator>::type - get_before_last(TIterator /*first_*/, TIterator last_) + ETL_CONSTEXPR14 typename etl::enable_if::value, TIterator>::type get_before_last(TIterator /*first_*/, + TIterator last_) { return last_ - 1; } - } + } // namespace private_algorithm //*************************************************************************** /// Sorts the elements using selection sort. @@ -3137,17 +3257,21 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR20 - void selection_sort(TIterator first, TIterator last, TCompare compare) + ETL_CONSTEXPR20 void selection_sort(TIterator first, TIterator last, TCompare compare) { - TIterator min; + if (first == last) + { + return; + } + + TIterator min; const TIterator ilast = private_algorithm::get_before_last(first, last); const TIterator jlast = last; for (TIterator i = first; i != ilast; ++i) { min = i; - + TIterator j = i; ++j; @@ -3160,7 +3284,10 @@ namespace etl } using ETL_OR_STD::swap; // Allow ADL - swap(*i, *min); + if (min != i) + { + swap(*i, *min); + } } } @@ -3169,8 +3296,7 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR20 - void selection_sort(TIterator first, TIterator last) + ETL_CONSTEXPR20 void selection_sort(TIterator first, TIterator last) { selection_sort(first, last, etl::less::value_type>()); } @@ -3181,14 +3307,9 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - void heap_sort(TIterator first, TIterator last, TCompare compare) + ETL_CONSTEXPR14 void heap_sort(TIterator first, TIterator last, TCompare compare) { - if (!etl::is_heap(first, last, compare)) - { - etl::make_heap(first, last, compare); - } - + etl::make_heap(first, last, compare); etl::sort_heap(first, last, compare); } @@ -3197,14 +3318,9 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR14 - void heap_sort(TIterator first, TIterator last) + ETL_CONSTEXPR14 void heap_sort(TIterator first, TIterator last) { - if (!etl::is_heap(first, last)) - { - etl::make_heap(first, last); - } - + etl::make_heap(first, last); etl::sort_heap(first, last); } @@ -3248,7 +3364,7 @@ namespace etl #endif //*************************************************************************** - /// Returns the maximum value. + /// Returns the minimum value. //*************************************************************************** #if ETL_USING_CPP11 template @@ -3370,9 +3486,8 @@ namespace etl /// Does at most etl::distance(first, last) swaps. //*************************************************************************** template - ETL_CONSTEXPR14 - typename etl::enable_if::value, TIterator>::type - partition(TIterator first, TIterator last, TPredicate predicate) + ETL_CONSTEXPR14 typename etl::enable_if::value, TIterator>::type partition(TIterator first, TIterator last, + TPredicate predicate) { first = etl::find_if_not(first, last, predicate); @@ -3400,9 +3515,8 @@ namespace etl /// Does at most (etl::distance(first, last) / 2) swaps. //*************************************************************************** template - ETL_CONSTEXPR14 - typename etl::enable_if::value, TIterator>::type - partition(TIterator first, TIterator last, TPredicate predicate) + ETL_CONSTEXPR14 typename etl::enable_if< etl::is_bidirectional_iterator_concept::value, TIterator>::type + partition(TIterator first, TIterator last, TPredicate predicate) { while (first != last) { @@ -3413,9 +3527,7 @@ namespace etl break; } - last = etl::find_if(etl::reverse_iterator(last), - etl::reverse_iterator(first), - predicate).base(); + last = etl::find_if(etl::reverse_iterator(last), etl::reverse_iterator(first), predicate).base(); if (first == last) { @@ -3440,24 +3552,19 @@ namespace etl #if (ETL_USING_CPP20 && ETL_USING_STL) || (ETL_USING_CPP14 && ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)) constexpr #endif - TIterator nth_partition(TIterator first, TIterator last, TCompare compare) + TIterator + nth_partition(TIterator first, TIterator last, TCompare compare) { typedef typename etl::iterator_traits::value_type value_type; - TIterator pivot = last; // Maybe find a better pivot choice? - value_type pivot_value = *pivot; - - // Swap the pivot with the last, if necessary. - if (pivot != last) - { - swap(*pivot, *last); - } + value_type pivot_value = ETL_MOVE(*last); TIterator i = first; for (TIterator j = first; j < last; ++j) { - if (!compare(pivot_value, *j)) // Hack to get '*j <= pivot_value' in terms of 'pivot_value < *j' + if (!compare(pivot_value, *j)) // Hack to get '*j <= pivot_value' in + // terms of 'pivot_value < *j' { swap(*i, *j); ++i; @@ -3468,7 +3575,7 @@ namespace etl return i; } - } + } // namespace private_algorithm //********************************************************* /// nth_element @@ -3476,10 +3583,10 @@ namespace etl //********************************************************* #if ETL_USING_CPP11 template ::value_type>> -#if (ETL_USING_CPP20 && ETL_USING_STL) || (ETL_USING_CPP14 && ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)) + #if (ETL_USING_CPP20 && ETL_USING_STL) || (ETL_USING_CPP14 && ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)) constexpr -#endif - typename etl::enable_if::value, void>::type + #endif + typename etl::enable_if< etl::is_random_access_iterator_concept::value, void>::type nth_element(TIterator first, TIterator nth, TIterator last, TCompare compare = TCompare()) { if (first == last) @@ -3513,8 +3620,8 @@ namespace etl //********************************************************* template - typename etl::enable_if::value, void>::type - nth_element(TIterator first, TIterator nth, TIterator last, TCompare compare) + typename etl::enable_if< etl::is_random_access_iterator_concept::value, void>::type nth_element(TIterator first, TIterator nth, + TIterator last, TCompare compare) { if (first == last) { @@ -3545,15 +3652,3789 @@ namespace etl //********************************************************* template - typename etl::enable_if::value, void>::type - nth_element(TIterator first, TIterator nth, TIterator last) + typename etl::enable_if< etl::is_random_access_iterator_concept::value, void>::type nth_element(TIterator first, TIterator nth, + TIterator last) { typedef etl::less::value_type> compare_t; - nth_element(first, last, compare_t()); + nth_element(first, nth, last, compare_t()); } #endif -} + +#if ETL_USING_CPP17 + + namespace ranges + { + template + struct in_fun_result + { + ETL_NO_UNIQUE_ADDRESS I in; + ETL_NO_UNIQUE_ADDRESS F fun; + + template + constexpr operator in_fun_result() const& + { + return {in, fun}; + } + + template + constexpr operator in_fun_result() && + { + return {etl::move(in), etl::move(fun)}; + } + }; + + template + struct in_in_result + { + ETL_NO_UNIQUE_ADDRESS I1 in1; + ETL_NO_UNIQUE_ADDRESS I2 in2; + + template + constexpr operator in_in_result() const& + { + return {in1, in2}; + } + + template + constexpr operator in_in_result() && + { + return {etl::move(in1), etl::move(in2)}; + } + }; + + template + struct in_out_result + { + ETL_NO_UNIQUE_ADDRESS I in; + ETL_NO_UNIQUE_ADDRESS O out; + + template + constexpr operator in_out_result() const& + { + return {in, out}; + } + + template + constexpr operator in_out_result() && + { + return {etl::move(in), etl::move(out)}; + } + }; + + template + struct in_in_out_result + { + ETL_NO_UNIQUE_ADDRESS I1 in1; + ETL_NO_UNIQUE_ADDRESS I2 in2; + ETL_NO_UNIQUE_ADDRESS O out; + + template + constexpr operator in_in_out_result() const& + { + return {in1, in2, out}; + } + + template + constexpr operator in_in_out_result() && + { + return {etl::move(in1), etl::move(in2), etl::move(out)}; + } + }; + + template + struct in_out_out_result + { + ETL_NO_UNIQUE_ADDRESS I in; + ETL_NO_UNIQUE_ADDRESS O1 out1; + ETL_NO_UNIQUE_ADDRESS O2 out2; + + template + constexpr operator in_out_out_result() const& + { + return {in, out1, out2}; + } + + template + constexpr operator in_out_out_result() && + { + return {etl::move(in), etl::move(out1), etl::move(out2)}; + } + }; + + template + struct in_found_result + { + ETL_NO_UNIQUE_ADDRESS I in; + bool found; + + template + constexpr operator in_found_result() const& + { + return {in, found}; + } + + template + constexpr operator in_found_result() && + { + return {etl::move(in), found}; + } + }; + + template + struct out_value_result + { + ETL_NO_UNIQUE_ADDRESS O out; + ETL_NO_UNIQUE_ADDRESS T value; + + template + constexpr operator out_value_result() const& + { + return {out, value}; + } + + template + constexpr operator out_value_result() && + { + return {etl::move(out), etl::move(value)}; + } + }; + + template + using iota_result = out_value_result; + + template + using copy_result = in_out_result; + + template + using copy_n_result = in_out_result; + + template + using copy_if_result = in_out_result; + + template + using copy_backward_result = in_out_result; + + template + using uninitialized_copy_result = in_out_result; + + template + using uninitialized_copy_n_result = in_out_result; + + template + using uninitialized_move_result = in_out_result; + + template + using uninitialized_move_n_result = in_out_result; + + template + using move_result = in_out_result; + + template + using move_backward_result = in_out_result; + + template + using mismatch_result = in_in_result; + + template + using swap_ranges_result = in_in_result; + + template + using unary_transform_result = in_out_result; + + template + using binary_transform_result = in_in_out_result; + + template + using replace_copy_result = in_out_result; + + template + using replace_copy_if_result = in_out_result; + + template + using remove_copy_result = in_out_result; + + template + using unique_copy_result = in_out_result; + + template + using rotate_copy_result = in_out_result; + + template + using partial_sort_copy_result = in_out_result; + + template + using partition_copy_result = in_out_out_result; + + template + using set_union_result = in_in_out_result; + + template + using set_intersection_result = in_in_out_result; + + template + using set_difference_result = in_out_result; + + template + using set_symmetric_difference_result = in_in_out_result; + + template + using merge_result = in_in_out_result; + + template + using next_permutation_result = in_found_result; + + template + using prev_permutation_result = in_found_result; + + template + struct min_max_result + { + T min; + T max; + + template + constexpr operator min_max_result() const& + { + return {min, max}; + } + + template + constexpr operator min_max_result() && + { + return {etl::move(min), etl::move(max)}; + } + }; + + template + using minmax_result = min_max_result; + + template + using minmax_element_result = min_max_result; + + template + using for_each_result = in_fun_result; + + struct for_each_fn + { + template >> + constexpr ranges::for_each_result operator()(I first, S last, Fun f, Proj proj = {}) const + { + for (; first != last; ++first) + { + etl::invoke(f, etl::invoke(proj, *first)); + } + return {etl::move(first), etl::move(f)}; + } + + template >> + constexpr ranges::for_each_result, Fun> operator()(R&& r, Fun f, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(f), etl::ref(proj)); + } + }; + + inline constexpr for_each_fn for_each; + + template + using for_each_n_result = in_fun_result; + + struct for_each_n_fn + { + template >> + constexpr for_each_n_result operator()(I first, etl::iter_difference_t n, Fun fun, Proj proj = Proj{}) const + { + for (; n-- > 0; ++first) + { + etl::invoke(fun, etl::invoke(proj, *first)); + } + return {etl::move(first), etl::move(fun)}; + } + }; + + inline constexpr for_each_n_fn for_each_n{}; + + struct find_fn + { + template >> + constexpr I operator()(I first, S last, const T& value, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (etl::invoke(proj, *first) == value) + { + return first; + } + } + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, const T& value, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), value, etl::ref(proj)); + } + }; + + inline constexpr find_fn find; + + struct find_if_fn + { + template >> + constexpr I operator()(I first, S last, Pred pred, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (etl::invoke(pred, etl::invoke(proj, *first))) + { + return first; + } + } + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Pred pred, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr find_if_fn find_if; + + struct find_if_not_fn + { + template >> + constexpr I operator()(I first, S last, Pred pred, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (!etl::invoke(pred, etl::invoke(proj, *first))) + { + return first; + } + } + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Pred pred, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr find_if_not_fn find_if_not; + + struct search_fn + { + template >> + constexpr ranges::subrange operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + for (;; ++first1) + { + I1 it1 = first1; + for (I2 it2 = first2;; ++it1, ++it2) + { + if (it2 == last2) + { + return {first1, it1}; + } + if (it1 == last1) + { + return {it1, it1}; + } + if (!etl::invoke(pred, etl::invoke(proj1, *it1), etl::invoke(proj2, *it2))) + { + break; + } + } + } + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(pred), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr search_fn search{}; + + struct search_n_fn + { + template , class Pred = ranges::equal_to, class Proj = etl::identity, + typename = etl::enable_if_t>> + constexpr ranges::subrange operator()(I first, S last, etl::iter_difference_t count, const T& value, Pred pred = {}, Proj proj = {}) const + { + if (count <= 0) + { + return {first, first}; + } + + for (; first != last; ++first) + { + if (etl::invoke(pred, etl::invoke(proj, *first), value)) + { + I start = first; + etl::iter_difference_t n = 1; + + for (;;) + { + if (n >= count) + { + return {start, ++first}; + } + ++first; + if (first == last) + { + return {first, first}; + } + if (!etl::invoke(pred, etl::invoke(proj, *first), value)) + { + break; + } + ++n; + } + } + } + return {first, first}; + } + + template , class Pred = ranges::equal_to, class Proj = etl::identity, + typename = etl::enable_if_t>> + constexpr ranges::borrowed_subrange_t operator()(R&& r, ranges::range_difference_t count, const T& value, Pred pred = {}, + Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), count, value, etl::move(pred), etl::move(proj)); + } + }; + + inline constexpr search_n_fn search_n{}; + + struct find_end_fn + { + template >> + constexpr ranges::subrange operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + if (first2 == last2) + { + auto last_it = ranges::next(first1, last1); + return {last_it, last_it}; + } + auto result = ranges::search(etl::move(first1), last1, first2, last2, pred, proj1, proj2); + + if (result.empty()) + { + return result; + } + + for (;;) + { + auto new_result = ranges::search(etl::next(result.begin()), last1, first2, last2, pred, proj1, proj2); + if (new_result.empty()) + { + return result; + } + else + { + result = etl::move(new_result); + } + } + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(pred), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr find_end_fn find_end{}; + + struct find_first_of_fn + { + template >> + constexpr I1 operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + for (; first1 != last1; ++first1) + { + for (auto i = first2; i != last2; ++i) + { + if (etl::invoke(pred, etl::invoke(proj1, *first1), etl::invoke(proj2, *i))) + { + return first1; + } + } + } + return first1; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(pred), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr find_first_of_fn find_first_of{}; + + struct adjacent_find_fn + { + template >> + constexpr I operator()(I first, S last, Pred pred = {}, Proj proj = {}) const + { + if (first == last) + { + return first; + } + auto next_it = ranges::next(first); + for (; next_it != last; ++next_it, ++first) + { + if (etl::invoke(pred, etl::invoke(proj, *first), etl::invoke(proj, *next_it))) + { + return first; + } + } + return next_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Pred pred = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr adjacent_find_fn adjacent_find; + + struct count_fn + { + template , + typename = etl::enable_if_t>> + constexpr etl::iter_difference_t operator()(I first, S last, const T& value, Proj proj = {}) const + { + etl::iter_difference_t counter = 0; + for (; first != last; ++first) + { + if (etl::invoke(proj, *first) == value) + { + ++counter; + } + } + return counter; + } + + template , Proj>, + typename = etl::enable_if_t>> + constexpr ranges::range_difference_t operator()(R&& r, const T& value, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), value, etl::ref(proj)); + } + }; + + inline constexpr count_fn count; + + struct count_if_fn + { + template >> + constexpr etl::iter_difference_t operator()(I first, S last, Pred pred, Proj proj = {}) const + { + etl::iter_difference_t counter = 0; + for (; first != last; ++first) + { + if (etl::invoke(pred, etl::invoke(proj, *first))) + { + ++counter; + } + } + return counter; + } + + template >> + constexpr ranges::range_difference_t operator()(R&& r, Pred pred, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr count_if_fn count_if; + + struct all_of_fn + { + template >> + constexpr bool operator()(I first, S last, Pred pred, Proj proj = {}) const + { + return ranges::find_if_not(first, last, etl::ref(pred), etl::ref(proj)) == last; + } + + template >> + constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const + { + return operator()(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr all_of_fn all_of; + + struct any_of_fn + { + template >> + constexpr bool operator()(I first, S last, Pred pred, Proj proj = {}) const + { + return ranges::find_if(first, last, etl::ref(pred), etl::ref(proj)) != last; + } + + template >> + constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const + { + return operator()(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr any_of_fn any_of; + + struct none_of_fn + { + template >> + constexpr bool operator()(I first, S last, Pred pred, Proj proj = {}) const + { + return ranges::find_if(first, last, etl::ref(pred), etl::ref(proj)) == last; + } + + template >> + constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const + { + return operator()(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr none_of_fn none_of; + + struct mismatch_fn + { + template >> + constexpr ranges::mismatch_result operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}) const + { + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + { + if (!etl::invoke(pred, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + break; + } + } + return {etl::move(first1), etl::move(first2)}; + } + + template >> + constexpr ranges::mismatch_result, ranges::borrowed_iterator_t> + operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(pred), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr mismatch_fn mismatch{}; + + struct equal_fn + { + template >> + constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + { + if (!etl::invoke(pred, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + return false; + } + } + return first1 == last1 && first2 == last2; + } + + template >> + constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(pred), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr equal_fn equal{}; + + struct is_permutation_fn + { + template >> + constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + // Skip common prefix + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + { + if (!etl::invoke(pred, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + break; + } + } + + if (first1 == last1) + { + return first2 == last2; + } + + if (first2 == last2) + { + return false; + } + + // Check remaining elements + for (I1 i = first1; i != last1; ++i) + { + // Check if we already counted this element + bool already_seen = false; + for (I1 j = first1; j != i; ++j) + { + if (etl::invoke(pred, etl::invoke(proj1, *i), etl::invoke(proj1, *j))) + { + already_seen = true; + break; + } + } + + if (already_seen) + { + continue; + } + + // Count occurrences in range2 + auto count2 = etl::iter_difference_t(0); + for (I2 k = first2; k != last2; ++k) + { + if (etl::invoke(pred, etl::invoke(proj1, *i), etl::invoke(proj2, *k))) + { + ++count2; + } + } + + if (count2 == 0) + { + return false; + } + + // Count occurrences in range1 + auto count1 = etl::iter_difference_t(0); + for (I1 k = i; k != last1; ++k) + { + if (etl::invoke(pred, etl::invoke(proj1, *i), etl::invoke(proj1, *k))) + { + ++count1; + } + } + + if (count1 != count2) + { + return false; + } + } + + return true; + } + + template >> + constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(pred), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr is_permutation_fn is_permutation{}; + + struct starts_with_fn + { + template >> + constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + for (; first2 != last2; ++first1, ++first2) + { + if (first1 == last1 || !etl::invoke(pred, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + return false; + } + } + return true; + } + + template >> + constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(pred), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr starts_with_fn starts_with{}; + + struct ends_with_fn + { + template >> + constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + auto n1 = etl::distance(first1, last1); + auto n2 = etl::distance(first2, last2); + + if (n2 > n1) + { + return false; + } + + ranges::advance(first1, n1 - n2); + + return starts_with(first1, last1, first2, last2, etl::move(pred), etl::move(proj1), etl::move(proj2)); + } + + template >> + constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(pred), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr ends_with_fn ends_with{}; + + struct lexicographical_compare_fn + { + template >> + constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + { + if (etl::invoke(comp, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + return true; + } + + if (etl::invoke(comp, etl::invoke(proj2, *first2), etl::invoke(proj1, *first1))) + { + return false; + } + } + return first1 == last1 && first2 != last2; + } + + template >> + constexpr bool operator()(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(comp), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr lexicographical_compare_fn lexicographical_compare{}; + + template + struct in_value_result + { + ETL_NO_UNIQUE_ADDRESS I in; + ETL_NO_UNIQUE_ADDRESS T value; + + template + constexpr operator in_value_result() const& + { + return {in, value}; + } + + template + constexpr operator in_value_result() && + { + return {etl::move(in), etl::move(value)}; + } + }; + + template + using fold_left_with_iter_result = in_value_result; + + struct fold_left_fn + { + template >> + constexpr auto operator()(I first, S last, T init, F f) const -> etl::decay_t>> + { + using U = etl::decay_t>>; + U accum = etl::move(init); + for (; first != last; ++first) + { + accum = etl::invoke(f, etl::move(accum), *first); + } + return accum; + } + + template >> + constexpr auto operator()(R&& r, T init, F f) const -> etl::decay_t< etl::invoke_result_t>> + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(init), etl::move(f)); + } + }; + + inline constexpr fold_left_fn fold_left{}; + + struct fold_left_with_iter_fn + { + template >> + constexpr auto operator()(I first, S last, T init, + F f) const -> fold_left_with_iter_result< I, etl::decay_t>>> + { + using U = etl::decay_t>>; + U accum = etl::move(init); + for (; first != last; ++first) + { + accum = etl::invoke(f, etl::move(accum), *first); + } + return {etl::move(first), etl::move(accum)}; + } + + template >> + constexpr auto operator()(R&& r, T init, F f) const + -> fold_left_with_iter_result< ranges::borrowed_iterator_t, etl::decay_t< etl::invoke_result_t>>> + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(init), etl::move(f)); + } + }; + + inline constexpr fold_left_with_iter_fn fold_left_with_iter{}; + + struct fold_left_first_fn + { + template >> + constexpr auto operator()(I first, S last, F f) const -> etl::decay_t, etl::iter_reference_t>> + { + using U = etl::decay_t, etl::iter_reference_t>>; + if (first == last) + { + return U{}; + } + U accum = *first; + ++first; + for (; first != last; ++first) + { + accum = etl::invoke(f, etl::move(accum), *first); + } + return accum; + } + + template >> + constexpr auto operator()(R&& r, + F f) const -> etl::decay_t, etl::ranges::range_reference_t>> + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(f)); + } + }; + + inline constexpr fold_left_first_fn fold_left_first{}; + + struct fold_left_first_with_iter_fn + { + template >> + constexpr auto operator()(I first, S last, F f) const + -> fold_left_with_iter_result< I, etl::decay_t, etl::iter_reference_t>>> + { + using U = etl::decay_t, etl::iter_reference_t>>; + if (first == last) + { + return {etl::move(first), U{}}; + } + U accum = *first; + ++first; + for (; first != last; ++first) + { + accum = etl::invoke(f, etl::move(accum), *first); + } + return {etl::move(first), etl::move(accum)}; + } + + template >> + constexpr auto operator()(R&& r, F f) const + -> fold_left_with_iter_result< ranges::borrowed_iterator_t, + etl::decay_t, etl::ranges::range_reference_t>>> + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(f)); + } + }; + + inline constexpr fold_left_first_with_iter_fn fold_left_first_with_iter{}; + + struct fold_right_fn + { + template >> + constexpr auto operator()(I first, S last, T init, F f) const -> etl::decay_t, T>> + { + using U = etl::decay_t, T>>; + U accum = etl::move(init); + I tail = ranges::next(first, last); + while (tail != first) + { + tail = ranges::prev(tail); + accum = etl::invoke(f, *tail, etl::move(accum)); + } + return accum; + } + + template >> + constexpr auto operator()(R&& r, T init, F f) const -> etl::decay_t< etl::invoke_result_t, T>> + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(init), etl::move(f)); + } + }; + + inline constexpr fold_right_fn fold_right{}; + + struct fold_right_last_fn + { + template >> + constexpr auto operator()(I first, S last, F f) const -> etl::decay_t, etl::iter_value_t>> + { + using U = etl::decay_t, etl::iter_value_t>>; + I tail = ranges::next(first, last); + if (tail == first) + { + return U{}; + } + tail = ranges::prev(tail); + U accum = *tail; + while (tail != first) + { + tail = ranges::prev(tail); + accum = etl::invoke(f, *tail, etl::move(accum)); + } + return accum; + } + + template >> + constexpr auto + operator()(R&& r, F f) const -> etl::decay_t, etl::ranges::range_value_t>> + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(f)); + } + }; + + inline constexpr fold_right_last_fn fold_right_last{}; + + struct copy_fn + { + template >> + constexpr ranges::copy_result operator()(I first, S last, O result) const + { + for (; first != last; ++first, ++result) + { + *result = *first; + } + return {etl::move(first), etl::move(result)}; + } + + template >> + constexpr ranges::copy_result, O> operator()(R&& r, O result) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result)); + } + }; + + inline constexpr copy_fn copy{}; + + struct copy_n_fn + { + template + constexpr ranges::copy_n_result operator()(I first, etl::iter_difference_t n, O result) const + { + for (etl::iter_difference_t i = 0; i < n; ++i, ++first, ++result) + { + *result = *first; + } + return {etl::move(first), etl::move(result)}; + } + }; + + inline constexpr copy_n_fn copy_n{}; + + struct copy_if_fn + { + template >> + constexpr ranges::copy_if_result operator()(I first, S last, O result, Pred pred, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (etl::invoke(pred, etl::invoke(proj, *first))) + { + *result = *first; + ++result; + } + } + return {etl::move(first), etl::move(result)}; + } + + template >> + constexpr ranges::copy_if_result, O> operator()(R&& r, O result, Pred pred, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr copy_if_fn copy_if{}; + + struct copy_backward_fn + { + template >> + constexpr ranges::copy_backward_result operator()(I1 first, S1 last, I2 result) const + { + I1 last_it = ranges::next(first, last); + I1 tail = last_it; + while (first != tail) + { + *(--result) = *(--tail); + } + return {etl::move(last_it), etl::move(result)}; + } + + template >> + constexpr ranges::copy_backward_result, I> operator()(R&& r, I result) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result)); + } + }; + + inline constexpr copy_backward_fn copy_backward{}; + + struct move_fn + { + template >> + constexpr ranges::move_result operator()(I first, S last, O result) const + { + for (; first != last; ++first, ++result) + { + *result = etl::move(*first); + } + return {etl::move(first), etl::move(result)}; + } + + template >> + constexpr ranges::move_result, O> operator()(R&& r, O result) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result)); + } + }; + + inline constexpr move_fn move{}; + + struct move_backward_fn + { + template >> + constexpr ranges::move_backward_result operator()(I1 first, S1 last, I2 result) const + { + I1 last_it = ranges::next(first, last); + I1 tail = last_it; + while (first != tail) + { + *(--result) = etl::move(*(--tail)); + } + return {etl::move(last_it), etl::move(result)}; + } + + template >> + constexpr ranges::move_backward_result, I> operator()(R&& r, I result) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result)); + } + }; + + inline constexpr move_backward_fn move_backward{}; + + struct swap_ranges_fn + { + template >> + constexpr ranges::swap_ranges_result operator()(I1 first1, S1 last1, I2 first2, S2 last2) const + { + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + { + etl::iter_swap(first1, first2); + } + return {etl::move(first1), etl::move(first2)}; + } + + template >> + constexpr ranges::swap_ranges_result, ranges::borrowed_iterator_t> operator()(R1&& r1, R2&& r2) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2)); + } + }; + + inline constexpr swap_ranges_fn swap_ranges{}; + + struct replace_fn + { + template >> + constexpr I operator()(I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (etl::invoke(proj, *first) == old_value) + { + *first = new_value; + } + } + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), old_value, new_value, etl::ref(proj)); + } + }; + + inline constexpr replace_fn replace{}; + + struct replace_if_fn + { + template >> + constexpr I operator()(I first, S last, Pred pred, const T& new_value, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (etl::invoke(pred, etl::invoke(proj, *first))) + { + *first = new_value; + } + } + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Pred pred, const T& new_value, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), new_value, etl::ref(proj)); + } + }; + + inline constexpr replace_if_fn replace_if{}; + + struct replace_copy_fn + { + template >> + constexpr ranges::replace_copy_result operator()(I first, S last, O result, const T1& old_value, const T2& new_value, + Proj proj = {}) const + { + for (; first != last; ++first, ++result) + { + if (etl::invoke(proj, *first) == old_value) + { + *result = new_value; + } + else + { + *result = *first; + } + } + return {etl::move(first), etl::move(result)}; + } + + template >> + constexpr ranges::replace_copy_result, O> operator()(R&& r, O result, const T1& old_value, const T2& new_value, + Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result), old_value, new_value, etl::ref(proj)); + } + }; + + inline constexpr replace_copy_fn replace_copy{}; + + struct replace_copy_if_fn + { + template >> + constexpr ranges::replace_copy_if_result operator()(I first, S last, O result, Pred pred, const T& new_value, Proj proj = {}) const + { + for (; first != last; ++first, ++result) + { + if (etl::invoke(pred, etl::invoke(proj, *first))) + { + *result = new_value; + } + else + { + *result = *first; + } + } + return {etl::move(first), etl::move(result)}; + } + + template >> + constexpr ranges::replace_copy_if_result, O> operator()(R&& r, O result, Pred pred, const T& new_value, + Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result), etl::ref(pred), new_value, etl::ref(proj)); + } + }; + + inline constexpr replace_copy_if_fn replace_copy_if{}; + + struct remove_fn + { + template >> + constexpr ranges::subrange operator()(I first, S last, const T& value, Proj proj = {}) const + { + first = ranges::find(first, last, value, etl::ref(proj)); + + if (first != last) + { + I result = first; + + for (I it = result; ++it != last;) + { + if (!(etl::invoke(proj, *it) == value)) + { + *result = etl::move(*it); + ++result; + } + } + + return {result, last}; + } + + return {first, last}; + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R&& r, const T& value, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), value, etl::ref(proj)); + } + }; + + inline constexpr remove_fn remove{}; + + struct remove_if_fn + { + template >> + constexpr ranges::subrange operator()(I first, S last, Pred pred, Proj proj = {}) const + { + first = ranges::find_if(first, last, etl::ref(pred), etl::ref(proj)); + + if (first != last) + { + I result = first; + + for (I it = result; ++it != last;) + { + if (!etl::invoke(pred, etl::invoke(proj, *it))) + { + *result = etl::move(*it); + ++result; + } + } + + return {result, last}; + } + + return {first, last}; + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R&& r, Pred pred, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr remove_if_fn remove_if{}; + + struct remove_copy_fn + { + template >> + constexpr ranges::remove_copy_result operator()(I first, S last, O result, const T& value, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (!(etl::invoke(proj, *first) == value)) + { + *result = *first; + ++result; + } + } + return {etl::move(first), etl::move(result)}; + } + + template >> + constexpr ranges::remove_copy_result, O> operator()(R&& r, O result, const T& value, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result), value, etl::ref(proj)); + } + }; + + inline constexpr remove_copy_fn remove_copy{}; + + struct fill_fn + { + template >> + constexpr I operator()(I first, S last, const T& value) const + { + for (; first != last; ++first) + { + *first = value; + } + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, const T& value) const + { + return (*this)(ranges::begin(r), ranges::end(r), value); + } + }; + + inline constexpr fill_fn fill{}; + + struct fill_n_fn + { + template + constexpr I operator()(I first, etl::iter_difference_t n, const T& value) const + { + for (; n-- > 0; ++first) + { + *first = value; + } + return first; + } + }; + + inline constexpr fill_n_fn fill_n{}; + + struct generate_fn + { + template >> + constexpr I operator()(I first, S last, F gen) const + { + for (; first != last; ++first) + { + *first = gen(); + } + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, F gen) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(gen)); + } + }; + + inline constexpr generate_fn generate{}; + + struct generate_n_fn + { + template + constexpr I operator()(I first, etl::iter_difference_t n, F gen) const + { + for (; n-- > 0; ++first) + { + *first = gen(); + } + return first; + } + }; + + inline constexpr generate_n_fn generate_n{}; + + struct iota_fn + { + template >> + constexpr ranges::iota_result operator()(O first, S last, T value) const + { + while (first != last) + { + *first = value; + ++first; + ++value; + } + return {etl::move(first), etl::move(value)}; + } + + template >> + constexpr ranges::iota_result, T> operator()(R&& r, T value) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(value)); + } + }; + + inline constexpr iota_fn iota{}; + + struct unique_fn + { + template >> + constexpr ranges::subrange operator()(I first, S last, Pred pred = {}, Proj proj = {}) const + { + first = ranges::adjacent_find(first, last, etl::ref(pred), etl::ref(proj)); + + if (first != last) + { + I result = first; + ++first; + + while (++first != last) + { + if (!etl::invoke(pred, etl::invoke(proj, *result), etl::invoke(proj, *first))) + { + *++result = etl::move(*first); + } + } + + return {++result, last}; + } + + return {first, last}; + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R&& r, Pred pred = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr unique_fn unique{}; + + struct unique_copy_fn + { + template >> + constexpr ranges::unique_copy_result operator()(I first, S last, O result, Pred pred = {}, Proj proj = {}) const + { + if (first != last) + { + *result = *first; + ++result; + + auto previous = first; + ++first; + + for (; first != last; ++first) + { + if (!etl::invoke(pred, etl::invoke(proj, *previous), etl::invoke(proj, *first))) + { + *result = *first; + ++result; + } + previous = first; + } + } + + return {etl::move(first), etl::move(result)}; + } + + template >> + constexpr ranges::unique_copy_result, O> operator()(R&& r, O result, Pred pred = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr unique_copy_fn unique_copy{}; + + struct transform_fn + { + // Unary: iterator + sentinel + template >> + constexpr ranges::unary_transform_result operator()(I first, S last, O result, F op, Proj proj = {}) const + { + for (; first != last; ++first, ++result) + { + *result = etl::invoke(op, etl::invoke(proj, *first)); + } + return {etl::move(first), etl::move(result)}; + } + + // Unary: range + template < class R, class O, class F, class Proj = etl::identity, typename = etl::enable_if_t && !etl::is_range_v>> + constexpr ranges::unary_transform_result, O> operator()(R&& r, O result, F op, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result), etl::ref(op), etl::ref(proj)); + } + + // Binary: iterator + sentinel + template >> + constexpr ranges::binary_transform_result operator()(I1 first1, S1 last1, I2 first2, S2 last2, O result, F op, Proj1 proj1 = {}, + Proj2 proj2 = {}) const + { + for (; first1 != last1 && first2 != last2; ++first1, ++first2, ++result) + { + *result = etl::invoke(op, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2)); + } + return {etl::move(first1), etl::move(first2), etl::move(result)}; + } + + // Binary: range + template < class R1, class R2, class O, class F, class Proj1 = etl::identity, class Proj2 = etl::identity, + typename = etl::enable_if_t && etl::is_range_v>> + constexpr ranges::binary_transform_result< ranges::borrowed_iterator_t, ranges::borrowed_iterator_t, O> + operator()(R1&& r1, R2&& r2, O result, F op, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(result), etl::ref(op), etl::ref(proj1), + etl::ref(proj2)); + } + }; + + inline constexpr transform_fn transform{}; + + struct reverse_fn + { + template >> + constexpr I operator()(I first, S last) const + { + I tail = ranges::next(first, last); + I result = tail; + + for (; first != tail && first != --tail; ++first) + { + etl::iter_swap(first, tail); + } + + return result; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r) const + { + return (*this)(ranges::begin(r), ranges::end(r)); + } + }; + + inline constexpr reverse_fn reverse{}; + + template + using reverse_copy_result = in_out_result; + + struct reverse_copy_fn + { + template >> + constexpr ranges::reverse_copy_result operator()(I first, S last, O result) const + { + I tail = ranges::next(first, last); + I end_it = tail; + + while (tail != first) + { + *result = *--tail; + ++result; + } + + return {etl::move(end_it), etl::move(result)}; + } + + template >> + constexpr ranges::reverse_copy_result, O> operator()(R&& r, O result) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(result)); + } + }; + + inline constexpr reverse_copy_fn reverse_copy{}; + + template + using rotate_result = ranges::subrange; + + struct rotate_fn + { + template >> + constexpr ranges::rotate_result operator()(I first, I middle, S last) const + { + if (first == middle) + { + I last_it = ranges::next(first, last); + return {last_it, last_it}; + } + + I last_it = ranges::next(first, last); + + if (middle == last_it) + { + return {first, last_it}; + } + + I new_first = etl::rotate(first, middle, last_it); + return {etl::move(new_first), etl::move(last_it)}; + } + + template >> + constexpr ranges::rotate_result> operator()(R&& r, ranges::iterator_t middle) const + { + return (*this)(ranges::begin(r), etl::move(middle), ranges::end(r)); + } + }; + + inline constexpr rotate_fn rotate{}; + + struct rotate_copy_fn + { + template >> + constexpr ranges::rotate_copy_result operator()(I first, I middle, S last, O result) const + { + I last_it = ranges::next(first, last); + O end_out = etl::copy(middle, last_it, result); + end_out = etl::copy(first, middle, end_out); + return {etl::move(last_it), etl::move(end_out)}; + } + + template >> + constexpr ranges::rotate_copy_result, O> operator()(R&& r, ranges::iterator_t middle, O result) const + { + return (*this)(ranges::begin(r), etl::move(middle), ranges::end(r), etl::move(result)); + } + }; + + inline constexpr rotate_copy_fn rotate_copy{}; + + struct shift_left_fn + { + template >> + constexpr ranges::subrange operator()(I first, S last, etl::iter_difference_t n) const + { + I last_it = ranges::next(first, last); + + if (n <= 0) + { + return {first, last_it}; + } + + I mid = first; + if (ranges::advance(mid, n, last_it) != 0) + { + return {first, first}; + } + + I result = ranges::move(mid, last_it, first).out; + return {first, etl::move(result)}; + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R&& r, etl::ranges::range_difference_t n) const + { + return (*this)(ranges::begin(r), ranges::end(r), n); + } + }; + + inline constexpr shift_left_fn shift_left{}; + + struct shift_right_fn + { + template >> + constexpr ranges::subrange operator()(I first, S last, etl::iter_difference_t n) const + { + I last_it = ranges::next(first, last); + + if (n <= 0) + { + return {first, last_it}; + } + + I trail = last_it; + if (ranges::advance(trail, -n, first) != 0) + { + return {last_it, last_it}; + } + + I new_first = ranges::move_backward(first, trail, last_it).out; + return {etl::move(new_first), etl::move(last_it)}; + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R&& r, etl::ranges::range_difference_t n) const + { + return (*this)(ranges::begin(r), ranges::end(r), n); + } + }; + + inline constexpr shift_right_fn shift_right{}; + + struct shuffle_fn + { + template >> + I operator()(I first, S last, Gen&& gen) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "shuffle requires random access iterators"); + + using diff_t = etl::iter_difference_t; + using udiff_t = etl::make_unsigned_t; + using gen_t = etl::remove_reference_t; + using uresult_t = decltype(gen()); + + I last_it = ranges::next(first, last); + diff_t n = last_it - first; + + if (n <= 1) + { + return last_it; + } + + for (diff_t i = n - 1; i > 0; --i) + { + // Generate a uniformly distributed random index in [0, i] + // using rejection sampling to avoid modulo bias. + udiff_t range = static_cast(i); + constexpr uresult_t gmin = gen_t::min(); + constexpr uresult_t gmax = gen_t::max(); + constexpr uresult_t grange = gmax - gmin; + + uresult_t j; + + if ETL_IF_CONSTEXPR (grange == static_cast(-1)) + { + // Generator covers full range of uresult_t, just use modulo with + // rejection + uresult_t limit = (static_cast(-1) / (static_cast(range) + 1)) * (static_cast(range) + 1); + do { + j = static_cast(gen() - gmin); + } while (j >= limit); + j %= (static_cast(range) + 1); + } + else + { + uresult_t limit = (grange / (static_cast(range) + 1)) * (static_cast(range) + 1); + do { + j = static_cast(gen() - gmin); + } while (j >= limit); + j %= (static_cast(range) + 1); + } + + etl::iter_swap(first + i, first + static_cast(j)); + } + + return last_it; + } + + template >> + ranges::borrowed_iterator_t operator()(R&& r, Gen&& gen) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator>::value, "shuffle requires a range with random access iterators"); + + return (*this)(ranges::begin(r), ranges::end(r), static_cast(gen)); + } + }; + + inline constexpr shuffle_fn shuffle{}; + + struct sample_fn + { + template >> + O operator()(I first, S last, O out, etl::iter_difference_t n, Gen&& gen) const + { + using diff_t = etl::iter_difference_t; + using udiff_t = etl::make_unsigned_t; + using gen_t = etl::remove_reference_t; + using uresult_t = decltype(gen()); + + if (n <= 0) + { + return out; + } + + // Compute the size of [first, last). + I first_copy = first; + diff_t pop_size = 0; + for (I it = first_copy; it != last; ++it) + { + ++pop_size; + } + + if (pop_size <= n) + { + // Copy all elements. + for (; first != last; ++first, ++out) + { + *out = *first; + } + return out; + } + + // Selection sampling (Algorithm S / Vitter). + // For each element, decide whether to include it. + diff_t remaining = pop_size; + diff_t needed = n; + + for (; first != last && needed > 0; ++first, --remaining) + { + // Generate a uniformly distributed random number in [0, remaining). + udiff_t range = static_cast(remaining - 1); + constexpr uresult_t gmin = gen_t::min(); + constexpr uresult_t gmax = gen_t::max(); + constexpr uresult_t grange = gmax - gmin; + + uresult_t j; + + if ETL_IF_CONSTEXPR (grange == static_cast(-1)) + { + if (range == 0) + { + j = 0; + } + else + { + uresult_t limit = (static_cast(-1) / (static_cast(range) + 1)) * (static_cast(range) + 1); + do { + j = static_cast(gen() - gmin); + } while (j >= limit); + j %= (static_cast(range) + 1); + } + } + else + { + if (range == 0) + { + j = 0; + } + else + { + uresult_t limit = (grange / (static_cast(range) + 1)) * (static_cast(range) + 1); + do { + j = static_cast(gen() - gmin); + } while (j >= limit); + j %= (static_cast(range) + 1); + } + } + + if (static_cast(j) < needed) + { + *out = *first; + ++out; + --needed; + } + } + + return out; + } + + template >> + O operator()(R&& r, O out, etl::ranges::range_difference_t n, Gen&& gen) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(out), n, static_cast(gen)); + } + }; + + inline constexpr sample_fn sample{}; + + struct sort_fn + { + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "sort requires random access iterators"); + + I last_it = ranges::next(first, last); + + if (first == last_it) + { + return last_it; + } + + // Shell sort with projection support + auto n = etl::distance(first, last_it); + + for (auto gap = n / 2; gap > 0; gap /= 2) + { + for (auto i = gap; i < n; ++i) + { + auto temp = etl::move(*(first + i)); + auto j = i; + + while (j >= gap && etl::invoke(comp, etl::invoke(proj, temp), etl::invoke(proj, *(first + (j - gap))))) + { + *(first + j) = etl::move(*(first + (j - gap))); + j -= gap; + } + + *(first + j) = etl::move(temp); + } + } + + return last_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator>::value, "sort requires a range with random access iterators"); + + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr sort_fn sort{}; + + struct stable_sort_fn + { + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + I last_it = ranges::next(first, last); + + if (first == last_it) + { + return last_it; + } + + // Insertion sort with projection support (stable) + for (I i = ranges::next(first); i != last_it; ++i) + { + auto temp = etl::move(*i); + I j = i; + + while (j != first) + { + I prev_j = ranges::prev(j); + if (etl::invoke(comp, etl::invoke(proj, temp), etl::invoke(proj, *prev_j))) + { + *j = etl::move(*prev_j); + j = prev_j; + } + else + { + break; + } + } + + *j = etl::move(temp); + } + + return last_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr stable_sort_fn stable_sort{}; + + struct partial_sort_fn + { + template >> + constexpr I operator()(I first, I middle, S last, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "partial_sort requires random access iterators"); + + I last_it = ranges::next(first, last); + + if (first == middle || first == last_it) + { + return last_it; + } + + // Build a max-heap on [first, middle) + auto heap_size = etl::distance(first, middle); + + // Heapify: process from the last parent down to 0 + for (auto start = (heap_size - 1) / 2; start >= 0; --start) + { + sift_down(first, start, heap_size, comp, proj); + } + + // For each element in [middle, last_it), if it is smaller than the heap + // root, swap it in and re-heapify + for (I it = middle; it != last_it; ++it) + { + if (etl::invoke(comp, etl::invoke(proj, *it), etl::invoke(proj, *first))) + { + etl::iter_swap(it, first); + sift_down(first, decltype(heap_size){0}, heap_size, comp, proj); + } + } + + // Sort the heap to produce a sorted [first, middle) + // Repeatedly extract the max from the heap + for (auto heap_end = heap_size - 1; heap_end > 0; --heap_end) + { + etl::iter_swap(first, first + heap_end); + sift_down(first, decltype(heap_size){0}, heap_end, comp, proj); + } + + return last_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, ranges::iterator_t middle, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator>::value, "partial_sort requires a range with random access iterators"); + + return (*this)(ranges::begin(r), etl::move(middle), ranges::end(r), etl::move(comp), etl::move(proj)); + } + + private: + + template + static constexpr void sift_down(I first, DiffType index, DiffType heap_size, Comp& comp, Proj& proj) + { + while (true) + { + auto largest = index; + auto left = 2 * index + 1; + auto right = 2 * index + 2; + + if (left < heap_size && etl::invoke(comp, etl::invoke(proj, *(first + largest)), etl::invoke(proj, *(first + left)))) + { + largest = left; + } + + if (right < heap_size && etl::invoke(comp, etl::invoke(proj, *(first + largest)), etl::invoke(proj, *(first + right)))) + { + largest = right; + } + + if (largest == index) + { + break; + } + + etl::iter_swap(first + index, first + largest); + index = largest; + } + } + }; + + inline constexpr partial_sort_fn partial_sort{}; + + struct partial_sort_copy_fn + { + template >> + constexpr ranges::partial_sort_copy_result operator()(I1 first, S1 last, I2 result_first, S2 result_last, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "partial_sort_copy requires the output to be random access iterators"); + + I1 in_last = ranges::next(first, last); + I2 out_last = ranges::next(result_first, result_last); + + I2 r = result_first; + + // Copy elements from the input range into the output range + for (I1 it = first; it != in_last && r != out_last; ++it, ++r) + { + *r = *it; + } + + auto heap_size = etl::distance(result_first, r); + + if (heap_size == 0) + { + return {etl::move(in_last), etl::move(r)}; + } + + // Build a max-heap on [result_first, r) + for (auto start = (heap_size - 1) / 2; start >= 0; --start) + { + sift_down(result_first, start, heap_size, comp, proj2); + } + + // For remaining elements in [first + heap_size, in_last), if smaller + // than the heap root, swap it in and re-heapify + I1 it = first; + etl::advance(it, heap_size); + for (; it != in_last; ++it) + { + if (etl::invoke(comp, etl::invoke(proj1, *it), etl::invoke(proj2, *result_first))) + { + *result_first = *it; + sift_down(result_first, decltype(heap_size){0}, heap_size, comp, proj2); + } + } + + // Sort the heap to produce a sorted output range + for (auto heap_end = heap_size - 1; heap_end > 0; --heap_end) + { + etl::iter_swap(result_first, result_first + heap_end); + sift_down(result_first, decltype(heap_size){0}, heap_end, comp, proj2); + } + + return {etl::move(in_last), etl::move(r)}; + } + + template >> + constexpr ranges::partial_sort_copy_result< ranges::borrowed_iterator_t, ranges::borrowed_iterator_t> + operator()(R1&& r, R2&& result_r, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator>::value, + "partial_sort_copy requires the output range to have random access iterators"); + + return (*this)(ranges::begin(r), ranges::end(r), ranges::begin(result_r), ranges::end(result_r), etl::move(comp), etl::move(proj1), + etl::move(proj2)); + } + + private: + + template + static constexpr void sift_down(I first, DiffType index, DiffType heap_size, Comp& comp, Proj& proj) + { + while (true) + { + auto largest = index; + auto left = 2 * index + 1; + auto right = 2 * index + 2; + + if (left < heap_size && etl::invoke(comp, etl::invoke(proj, *(first + largest)), etl::invoke(proj, *(first + left)))) + { + largest = left; + } + + if (right < heap_size && etl::invoke(comp, etl::invoke(proj, *(first + largest)), etl::invoke(proj, *(first + right)))) + { + largest = right; + } + + if (largest == index) + { + break; + } + + etl::iter_swap(first + index, first + largest); + index = largest; + } + } + }; + + inline constexpr partial_sort_copy_fn partial_sort_copy{}; + + struct nth_element_fn + { + template >> + constexpr I operator()(I first, I nth, S last, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "nth_element requires random access iterators"); + + I last_it = ranges::next(first, last); + + if (first == last_it || ranges::next(first) == last_it) + { + return last_it; + } + + I lo = first; + I hi = ranges::prev(last_it); + + while (lo <= hi) + { + I p = nth_partition(lo, hi, comp, proj); + + if (p == nth) + { + return last_it; + } + else if (p > nth) + { + hi = ranges::prev(p); + } + else + { + lo = ranges::next(p); + } + } + + return last_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, ranges::iterator_t nth, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator>::value, "nth_element requires a range with random access iterators"); + + return (*this)(ranges::begin(r), etl::move(nth), ranges::end(r), etl::move(comp), etl::move(proj)); + } + + private: + + template + static constexpr I nth_partition(I first, I last, Comp& comp, Proj& proj) + { + if (first == last) + { + return first; + } + + if (last - first == 1) + { + if (etl::invoke(comp, etl::invoke(proj, *last), etl::invoke(proj, *first))) + { + etl::iter_swap(first, last); + } + return first; + } + + // Median-of-three pivot selection + I mid = first + (last - first) / 2; + + if (etl::invoke(comp, etl::invoke(proj, *mid), etl::invoke(proj, *first))) + { + etl::iter_swap(first, mid); + } + + if (etl::invoke(comp, etl::invoke(proj, *last), etl::invoke(proj, *first))) + { + etl::iter_swap(first, last); + } + + if (etl::invoke(comp, etl::invoke(proj, *mid), etl::invoke(proj, *last))) + { + etl::iter_swap(mid, last); + } + + // Pivot is now at *last + I i = first; + I j = last; + + while (true) + { + while (etl::invoke(comp, etl::invoke(proj, *i), etl::invoke(proj, *last))) + { + ++i; + } + + --j; + + while (i < j && etl::invoke(comp, etl::invoke(proj, *last), etl::invoke(proj, *j))) + { + --j; + } + + if (i >= j) + { + break; + } + + etl::iter_swap(i, j); + ++i; + } + + etl::iter_swap(i, last); + return i; + } + }; + + inline constexpr nth_element_fn nth_element{}; + + struct partition_fn + { + template >> + constexpr ranges::subrange operator()(I first, S last, Pred pred, Proj proj = {}) const + { + first = ranges::find_if_not(first, last, etl::ref(pred), etl::ref(proj)); + + if (first == last) + { + return {first, first}; + } + + for (I i = ranges::next(first); i != last; ++i) + { + if (etl::invoke(pred, etl::invoke(proj, *i))) + { + etl::iter_swap(i, first); + ++first; + } + } + + return {first, ranges::next(first, last)}; + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R&& r, Pred pred, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr partition_fn partition{}; + + struct is_partitioned_fn + { + template >> + constexpr bool operator()(I first, S last, Pred pred, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (!etl::invoke(pred, etl::invoke(proj, *first))) + { + break; + } + } + + for (; first != last; ++first) + { + if (etl::invoke(pred, etl::invoke(proj, *first))) + { + return false; + } + } + + return true; + } + + template >> + constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr is_partitioned_fn is_partitioned{}; + + struct partition_copy_fn + { + template >> + constexpr ranges::partition_copy_result operator()(I first, S last, O1 out_true, O2 out_false, Pred pred, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (etl::invoke(pred, etl::invoke(proj, *first))) + { + *out_true = *first; + ++out_true; + } + else + { + *out_false = *first; + ++out_false; + } + } + + return {etl::move(first), etl::move(out_true), etl::move(out_false)}; + } + + template >> + constexpr ranges::partition_copy_result, O1, O2> operator()(R&& r, O1 out_true, O2 out_false, Pred pred, + Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(out_true), etl::move(out_false), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr partition_copy_fn partition_copy{}; + + struct partition_point_fn + { + template >> + constexpr I operator()(I first, S last, Pred pred, Proj proj = {}) const + { + for (; first != last; ++first) + { + if (!etl::invoke(pred, etl::invoke(proj, *first))) + { + return first; + } + } + + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Pred pred, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + }; + + inline constexpr partition_point_fn partition_point{}; + + struct stable_partition_fn + { + template >> + constexpr ranges::subrange operator()(I first, S last, Pred pred, Proj proj = {}) const + { + // Find the first element that does not satisfy the predicate + first = ranges::find_if_not(first, last, etl::ref(pred), etl::ref(proj)); + + if (first == last) + { + return {first, first}; + } + + I last_it = ranges::next(first, last); + + I pp = stable_partition_impl(first, last_it, etl::ref(pred), etl::ref(proj), etl::distance(first, last_it)); + + return {pp, last_it}; + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R&& r, Pred pred, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::ref(pred), etl::ref(proj)); + } + + private: + + template + static constexpr I stable_partition_impl(I first, I last, Pred pred, Proj proj, typename etl::iterator_traits::difference_type len) + { + if (len == 0) + { + return first; + } + + if (len == 1) + { + return etl::invoke(pred, etl::invoke(proj, *first)) ? ranges::next(first) : first; + } + + I middle = ranges::next(first, len / 2); + + I left_partition = stable_partition_impl(first, middle, etl::ref(pred), etl::ref(proj), len / 2); + I right_partition = stable_partition_impl(middle, last, etl::ref(pred), etl::ref(proj), len - len / 2); + + return etl::rotate(left_partition, middle, right_partition); + } + }; + + inline constexpr stable_partition_fn stable_partition{}; + + struct is_sorted_until_fn + { + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + if (first != last) + { + I next_it = ranges::next(first); + + while (next_it != last) + { + if (etl::invoke(comp, etl::invoke(proj, *next_it), etl::invoke(proj, *first))) + { + return next_it; + } + + first = next_it; + ++next_it; + } + } + + return ranges::next(first, last); + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr is_sorted_until_fn is_sorted_until{}; + + struct is_sorted_fn + { + template >> + constexpr bool operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + return ranges::is_sorted_until(first, last, etl::ref(comp), etl::ref(proj)) == last; + } + + template >> + constexpr bool operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr is_sorted_fn is_sorted{}; + + struct lower_bound_fn + { + template >> + constexpr I operator()(I first, S last, const T& value, Comp comp = {}, Proj proj = {}) const + { + auto len = etl::distance(first, last); + + while (len > 0) + { + auto half = len / 2; + I middle = ranges::next(first, half); + + if (etl::invoke(comp, etl::invoke(proj, *middle), value)) + { + first = ranges::next(middle); + len -= half + 1; + } + else + { + len = half; + } + } + + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, const T& value, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), value, etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr lower_bound_fn lower_bound{}; + + struct upper_bound_fn + { + template >> + constexpr I operator()(I first, S last, const T& value, Comp comp = {}, Proj proj = {}) const + { + auto len = etl::distance(first, last); + + while (len > 0) + { + auto half = len / 2; + I middle = ranges::next(first, half); + + if (!etl::invoke(comp, value, etl::invoke(proj, *middle))) + { + first = ranges::next(middle); + len -= half + 1; + } + else + { + len = half; + } + } + + return first; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, const T& value, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), value, etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr upper_bound_fn upper_bound{}; + + struct equal_range_fn + { + template >> + constexpr ranges::subrange operator()(I first, S last, const T& value, Comp comp = {}, Proj proj = {}) const + { + return {ranges::lower_bound(first, last, value, etl::ref(comp), etl::ref(proj)), + ranges::upper_bound(first, last, value, etl::ref(comp), etl::ref(proj))}; + } + + template >> + constexpr ranges::borrowed_subrange_t operator()(R&& r, const T& value, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), value, etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr equal_range_fn equal_range{}; + + struct binary_search_fn + { + template >> + ETL_NODISCARD + constexpr bool operator()(I first, S last, const T& value, Comp comp = {}, Proj proj = {}) const + { + first = ranges::lower_bound(first, last, value, etl::ref(comp), etl::ref(proj)); + + return (!(first == last) && !(etl::invoke(comp, value, etl::invoke(proj, *first)))); + } + + template >> + ETL_NODISCARD + constexpr bool operator()(R&& r, const T& value, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), value, etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr binary_search_fn binary_search{}; + + struct includes_fn + { + template >> + ETL_NODISCARD + constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + for (; first2 != last2; ++first1) + { + if (first1 == last1) + { + return false; + } + + if (etl::invoke(comp, etl::invoke(proj2, *first2), etl::invoke(proj1, *first1))) + { + return false; + } + + if (!etl::invoke(comp, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + ++first2; + } + } + + return true; + } + + template >> + ETL_NODISCARD + constexpr bool operator()(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(comp), etl::move(proj1), etl::move(proj2)); + } + }; + + inline constexpr includes_fn includes{}; + + struct merge_fn + { + template >> + constexpr ranges::merge_result operator()(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}) const + { + while (first1 != last1 && first2 != last2) + { + if (etl::invoke(comp, etl::invoke(proj2, *first2), etl::invoke(proj1, *first1))) + { + *result = *first2; + ++first2; + } + else + { + *result = *first1; + ++first1; + } + ++result; + } + + while (first1 != last1) + { + *result = *first1; + ++first1; + ++result; + } + + while (first2 != last2) + { + *result = *first2; + ++first2; + ++result; + } + + return {etl::move(first1), etl::move(first2), etl::move(result)}; + } + + template >> + constexpr ranges::merge_result, ranges::borrowed_iterator_t, O> + operator()(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(result), etl::move(comp), etl::move(proj1), + etl::move(proj2)); + } + }; + + inline constexpr merge_fn merge{}; + + struct inplace_merge_fn + { + template >> + constexpr I operator()(I first, I middle, S last, Comp comp = {}, Proj proj = {}) const + { + I last_it = ranges::next(first, last); + + if (first == middle || middle == last_it) + { + return last_it; + } + + inplace_merge_impl(first, middle, last_it, comp, proj, etl::distance(first, middle), etl::distance(middle, last_it)); + + return last_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, ranges::iterator_t middle, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), etl::move(middle), ranges::end(r), etl::move(comp), etl::move(proj)); + } + + private: + + template + static constexpr void inplace_merge_impl(I first, I middle, I last, Comp& comp, Proj& proj, + typename etl::iterator_traits::difference_type len1, + typename etl::iterator_traits::difference_type len2) + { + if (len1 == 0 || len2 == 0) + { + return; + } + + if (len1 + len2 == 2) + { + if (etl::invoke(comp, etl::invoke(proj, *middle), etl::invoke(proj, *first))) + { + etl::iter_swap(first, middle); + } + return; + } + + I first_cut; + I second_cut; + typename etl::iterator_traits::difference_type new_len1; + typename etl::iterator_traits::difference_type new_len2; + + if (len1 > len2) + { + new_len1 = len1 / 2; + first_cut = ranges::next(first, new_len1); + second_cut = ranges::lower_bound(middle, last, etl::invoke(proj, *first_cut), etl::ref(comp), etl::ref(proj)); + new_len2 = etl::distance(middle, second_cut); + } + else + { + new_len2 = len2 / 2; + second_cut = ranges::next(middle, new_len2); + first_cut = ranges::upper_bound(first, middle, etl::invoke(proj, *second_cut), etl::ref(comp), etl::ref(proj)); + new_len1 = etl::distance(first, first_cut); + } + + I new_middle; + // Due to a non-standard etl::rotate implementation, we need to handle + // the case where one of the cuts is the middle separately to avoid + // returning an iterator outside of [first, last) + // As soon as etl::rotate is fixed to return an iterator in the middle + // of the rotated range, this can be simplified to just calling + // etl::rotate + if (first_cut == middle) + { + new_middle = second_cut; + } + else if (second_cut == middle) + { + new_middle = first_cut; + } + else + { + new_middle = etl::rotate(first_cut, middle, second_cut); + } + + inplace_merge_impl(first, first_cut, new_middle, comp, proj, new_len1, new_len2); + inplace_merge_impl(new_middle, second_cut, last, comp, proj, len1 - new_len1, len2 - new_len2); + } + }; + + inline constexpr inplace_merge_fn inplace_merge{}; + + struct set_union_fn + { + template >> + constexpr ranges::set_union_result operator()(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}) const + { + while (first1 != last1 && first2 != last2) + { + if (etl::invoke(comp, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + *result = *first1; + ++first1; + } + else if (etl::invoke(comp, etl::invoke(proj2, *first2), etl::invoke(proj1, *first1))) + { + *result = *first2; + ++first2; + } + else + { + *result = *first1; + ++first1; + ++first2; + } + ++result; + } + + while (first1 != last1) + { + *result = *first1; + ++first1; + ++result; + } + + while (first2 != last2) + { + *result = *first2; + ++first2; + ++result; + } + + return {etl::move(first1), etl::move(first2), etl::move(result)}; + } + + template >> + constexpr ranges::set_union_result, ranges::borrowed_iterator_t, O> + operator()(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(result), etl::move(comp), etl::move(proj1), + etl::move(proj2)); + } + }; + + inline constexpr set_union_fn set_union{}; + + struct set_intersection_fn + { + template >> + constexpr ranges::set_intersection_result operator()(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + while (first1 != last1 && first2 != last2) + { + if (etl::invoke(comp, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + ++first1; + } + else if (etl::invoke(comp, etl::invoke(proj2, *first2), etl::invoke(proj1, *first1))) + { + ++first2; + } + else + { + *result = *first1; + ++first1; + ++first2; + ++result; + } + } + + return {etl::move(first1), etl::move(first2), etl::move(result)}; + } + + template >> + constexpr ranges::set_intersection_result< ranges::borrowed_iterator_t, ranges::borrowed_iterator_t, O> + operator()(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(result), etl::move(comp), etl::move(proj1), + etl::move(proj2)); + } + }; + + inline constexpr set_intersection_fn set_intersection{}; + + struct set_difference_fn + { + template >> + constexpr ranges::set_difference_result operator()(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}) const + { + while (first1 != last1 && first2 != last2) + { + if (etl::invoke(comp, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + *result = *first1; + ++first1; + ++result; + } + else if (etl::invoke(comp, etl::invoke(proj2, *first2), etl::invoke(proj1, *first1))) + { + ++first2; + } + else + { + ++first1; + ++first2; + } + } + + while (first1 != last1) + { + *result = *first1; + ++first1; + ++result; + } + + return {etl::move(first1), etl::move(result)}; + } + + template >> + constexpr ranges::set_difference_result, O> operator()(R1&& r1, R2&& r2, O result, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(result), etl::move(comp), etl::move(proj1), + etl::move(proj2)); + } + }; + + inline constexpr set_difference_fn set_difference{}; + + struct set_symmetric_difference_fn + { + template >> + constexpr ranges::set_symmetric_difference_result operator()(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + while (first1 != last1 && first2 != last2) + { + if (etl::invoke(comp, etl::invoke(proj1, *first1), etl::invoke(proj2, *first2))) + { + *result = *first1; + ++first1; + ++result; + } + else if (etl::invoke(comp, etl::invoke(proj2, *first2), etl::invoke(proj1, *first1))) + { + *result = *first2; + ++first2; + ++result; + } + else + { + ++first1; + ++first2; + } + } + + while (first1 != last1) + { + *result = *first1; + ++first1; + ++result; + } + + while (first2 != last2) + { + *result = *first2; + ++first2; + ++result; + } + + return {etl::move(first1), etl::move(first2), etl::move(result)}; + } + + template >> + constexpr ranges::set_symmetric_difference_result< ranges::borrowed_iterator_t, ranges::borrowed_iterator_t, O> + operator()(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const + { + return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), etl::move(result), etl::move(comp), etl::move(proj1), + etl::move(proj2)); + } + }; + + inline constexpr set_symmetric_difference_fn set_symmetric_difference{}; + + struct make_heap_fn + { + private: + + template + static constexpr void sift_down(I first, typename etl::iterator_traits::difference_type index, + typename etl::iterator_traits::difference_type length, Comp& comp, Proj& proj) + { + while (true) + { + auto child = 2 * index + 1; + + if (child >= length) + { + break; + } + + if ((child + 1 < length) && etl::invoke(comp, etl::invoke(proj, *(first + child)), etl::invoke(proj, *(first + (child + 1))))) + { + ++child; + } + + if (!etl::invoke(comp, etl::invoke(proj, *(first + index)), etl::invoke(proj, *(first + child)))) + { + break; + } + + etl::iter_swap(first + index, first + child); + index = child; + } + } + + public: + + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + I last_it = ranges::next(first, last); + + auto length = etl::distance(first, last_it); + + if (length < 2) + { + return last_it; + } + + auto parent = (length - 2) / 2; + + while (true) + { + sift_down(first, parent, length, comp, proj); + + if (parent == 0) + { + break; + } + + --parent; + } + + return last_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr make_heap_fn make_heap{}; + + struct push_heap_fn + { + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "push_heap requires random access iterators"); + + I last_it = ranges::next(first, last); + + auto length = etl::distance(first, last_it); + + if (length < 2) + { + return last_it; + } + + auto value_index = length - 1; + auto parent = (value_index - 1) / 2; + auto value = etl::move(*(first + value_index)); + + while ((value_index > 0) && etl::invoke(comp, etl::invoke(proj, *(first + parent)), etl::invoke(proj, value))) + { + *(first + value_index) = etl::move(*(first + parent)); + value_index = parent; + parent = (value_index - 1) / 2; + } + + *(first + value_index) = etl::move(value); + + return last_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr push_heap_fn push_heap{}; + + struct pop_heap_fn + { + private: + + template + static constexpr void sift_down(I first, typename etl::iterator_traits::difference_type index, + typename etl::iterator_traits::difference_type length, Comp& comp, Proj& proj) + { + while (true) + { + auto child = 2 * index + 1; + + if (child >= length) + { + break; + } + + if ((child + 1 < length) && etl::invoke(comp, etl::invoke(proj, *(first + child)), etl::invoke(proj, *(first + (child + 1))))) + { + ++child; + } + + if (!etl::invoke(comp, etl::invoke(proj, *(first + index)), etl::invoke(proj, *(first + child)))) + { + break; + } + + etl::iter_swap(first + index, first + child); + index = child; + } + } + + public: + + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "pop_heap requires random access iterators"); + + I last_it = ranges::next(first, last); + + auto length = etl::distance(first, last_it); + + if (length < 2) + { + return last_it; + } + + --last_it; + + etl::iter_swap(first, last_it); + + sift_down(first, decltype(length)(0), etl::distance(first, last_it), comp, proj); + + return ranges::next(first, last); + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr pop_heap_fn pop_heap{}; + + struct is_heap_until_fn + { + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "is_heap_until requires random access iterators"); + + I last_it = ranges::next(first, last); + + auto length = etl::distance(first, last_it); + + decltype(length) parent = 0; + + for (decltype(length) child = 1; child < length; ++child) + { + if (etl::invoke(comp, etl::invoke(proj, *(first + parent)), etl::invoke(proj, *(first + child)))) + { + return first + child; + } + + if ((child & 1) == 0) + { + ++parent; + } + } + + return last_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr is_heap_until_fn is_heap_until{}; + + struct is_heap_fn + { + template >> + constexpr bool operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + return ranges::is_heap_until(first, last, etl::ref(comp), etl::ref(proj)) == last; + } + + template >> + constexpr bool operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr is_heap_fn is_heap{}; + + struct sort_heap_fn + { + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "sort_heap requires random access iterators"); + + I last_it = ranges::next(first, last); + I current_last = last_it; + + while (first != current_last) + { + ranges::pop_heap(first, current_last, comp, proj); + --current_last; + } + + return last_it; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr sort_heap_fn sort_heap{}; + + struct min_fn + { + template + constexpr const T& operator()(const T& a, const T& b, Comp comp = {}, Proj proj = {}) const + { + return etl::invoke(comp, etl::invoke(proj, b), etl::invoke(proj, a)) ? b : a; + } + + template + constexpr T operator()(std::initializer_list r, Comp comp = {}, Proj proj = {}) const + { + auto first = r.begin(); + auto last = r.end(); + + auto smallest = first; + while (++first != last) + { + if (etl::invoke(comp, etl::invoke(proj, *first), etl::invoke(proj, *smallest))) + { + smallest = first; + } + } + return *smallest; + } + + template >> + constexpr ranges::range_value_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + auto first = ranges::begin(r); + auto last = ranges::end(r); + + auto smallest = first; + while (++first != last) + { + if (etl::invoke(comp, etl::invoke(proj, *first), etl::invoke(proj, *smallest))) + { + smallest = first; + } + } + return *smallest; + } + }; + + inline constexpr min_fn min{}; + + struct min_element_fn + { + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + if (first == last) + { + return first; + } + + I smallest = first; + ++first; + + for (; first != last; ++first) + { + if (etl::invoke(comp, etl::invoke(proj, *first), etl::invoke(proj, *smallest))) + { + smallest = first; + } + } + + return smallest; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr min_element_fn min_element{}; + + struct max_fn + { + template + constexpr const T& operator()(const T& a, const T& b, Comp comp = {}, Proj proj = {}) const + { + return etl::invoke(comp, etl::invoke(proj, a), etl::invoke(proj, b)) ? b : a; + } + + template + constexpr T operator()(std::initializer_list r, Comp comp = {}, Proj proj = {}) const + { + auto first = r.begin(); + auto last = r.end(); + + auto largest = first; + while (++first != last) + { + if (etl::invoke(comp, etl::invoke(proj, *largest), etl::invoke(proj, *first))) + { + largest = first; + } + } + return *largest; + } + + template >> + constexpr ranges::range_value_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + auto first = ranges::begin(r); + auto last = ranges::end(r); + + auto largest = first; + while (++first != last) + { + if (etl::invoke(comp, etl::invoke(proj, *largest), etl::invoke(proj, *first))) + { + largest = first; + } + } + return *largest; + } + }; + + inline constexpr max_fn max{}; + + struct max_element_fn + { + template >> + constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + if (first == last) + { + return first; + } + + I largest = first; + ++first; + + for (; first != last; ++first) + { + if (etl::invoke(comp, etl::invoke(proj, *largest), etl::invoke(proj, *first))) + { + largest = first; + } + } + + return largest; + } + + template >> + constexpr ranges::borrowed_iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr max_element_fn max_element{}; + + struct minmax_fn + { + template + constexpr ranges::minmax_result operator()(const T& a, const T& b, Comp comp = {}, Proj proj = {}) const + { + if (etl::invoke(comp, etl::invoke(proj, b), etl::invoke(proj, a))) + { + return {b, a}; + } + return {a, b}; + } + + template + constexpr ranges::minmax_result operator()(std::initializer_list r, Comp comp = {}, Proj proj = {}) const + { + auto first = r.begin(); + auto last = r.end(); + + auto smallest = first; + auto largest = first; + + while (++first != last) + { + if (etl::invoke(comp, etl::invoke(proj, *first), etl::invoke(proj, *smallest))) + { + smallest = first; + } + if (etl::invoke(comp, etl::invoke(proj, *largest), etl::invoke(proj, *first))) + { + largest = first; + } + } + return {*smallest, *largest}; + } + + template >> + constexpr ranges::minmax_result> operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + auto first = ranges::begin(r); + auto last = ranges::end(r); + + auto smallest = first; + auto largest = first; + + while (++first != last) + { + if (etl::invoke(comp, etl::invoke(proj, *first), etl::invoke(proj, *smallest))) + { + smallest = first; + } + if (etl::invoke(comp, etl::invoke(proj, *largest), etl::invoke(proj, *first))) + { + largest = first; + } + } + return {*smallest, *largest}; + } + }; + + inline constexpr minmax_fn minmax{}; + + struct minmax_element_fn + { + template >> + constexpr ranges::minmax_element_result operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + if (first == last) + { + return {first, first}; + } + + I smallest = first; + I largest = first; + ++first; + + for (; first != last; ++first) + { + if (etl::invoke(comp, etl::invoke(proj, *first), etl::invoke(proj, *smallest))) + { + smallest = first; + } + if (etl::invoke(comp, etl::invoke(proj, *largest), etl::invoke(proj, *first))) + { + largest = first; + } + } + + return {smallest, largest}; + } + + template >> + constexpr ranges::minmax_element_result> operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr minmax_element_fn minmax_element{}; + + struct clamp_fn + { + template + constexpr const T& operator()(const T& value, const T& low, const T& high, Comp comp = {}, Proj proj = {}) const + { + auto&& projected_value = etl::invoke(proj, value); + + return etl::invoke(comp, projected_value, etl::invoke(proj, low)) ? low + : etl::invoke(comp, etl::invoke(proj, high), projected_value) ? high + : value; + } + }; + + inline constexpr clamp_fn clamp{}; + + struct next_permutation_fn + { + template >> + constexpr ranges::next_permutation_result operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + I last_it = ranges::next(first, last); + + // Empty or single-element range: already at last permutation + if (first == last_it) + { + return {etl::move(last_it), false}; + } + + I i = last_it; + --i; + + if (i == first) + { + return {etl::move(last_it), false}; + } + + for (;;) + { + I i1 = i; + --i; + + // Find the rightmost element where projected *i < projected *i1 + if (etl::invoke(comp, etl::invoke(proj, *i), etl::invoke(proj, *i1))) + { + // Find the rightmost element j where projected *j > projected *i + I j = last_it; + while (!etl::invoke(comp, etl::invoke(proj, *i), etl::invoke(proj, *--j))) + { + } + + etl::iter_swap(i, j); + + // Reverse from i1 to last + I left = i1; + I right = last_it; + while (left != right && left != --right) + { + etl::iter_swap(left, right); + ++left; + } + + return {etl::move(last_it), true}; + } + + if (i == first) + { + // Already at last (ascending) permutation: wrap to first + // (descending) + I left = first; + I right = last_it; + while (left != right && left != --right) + { + etl::iter_swap(left, right); + ++left; + } + + return {etl::move(last_it), false}; + } + } + } + + template >> + constexpr ranges::next_permutation_result> operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr next_permutation_fn next_permutation{}; + + struct prev_permutation_fn + { + template >> + constexpr ranges::prev_permutation_result operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + { + I last_it = ranges::next(first, last); + + // Empty or single-element range: already at last permutation + if (first == last_it) + { + return {etl::move(last_it), false}; + } + + I i = last_it; + --i; + + if (i == first) + { + return {etl::move(last_it), false}; + } + + for (;;) + { + I i1 = i; + --i; + + // Find the rightmost element where projected *i > projected *i1 + if (etl::invoke(comp, etl::invoke(proj, *i1), etl::invoke(proj, *i))) + { + // Find the rightmost element j where projected *j < projected *i + I j = last_it; + while (!etl::invoke(comp, etl::invoke(proj, *--j), etl::invoke(proj, *i))) + { + } + + etl::iter_swap(i, j); + + // Reverse from i1 to last + I left = i1; + I right = last_it; + while (left != right && left != --right) + { + etl::iter_swap(left, right); + ++left; + } + + return {etl::move(last_it), true}; + } + + if (i == first) + { + // Already at last (descending) permutation: wrap to first + // (ascending) + I left = first; + I right = last_it; + while (left != right && left != --right) + { + etl::iter_swap(left, right); + ++left; + } + + return {etl::move(last_it), false}; + } + } + } + + template >> + constexpr ranges::prev_permutation_result> operator()(R&& r, Comp comp = {}, Proj proj = {}) const + { + return (*this)(ranges::begin(r), ranges::end(r), etl::move(comp), etl::move(proj)); + } + }; + + inline constexpr prev_permutation_fn prev_permutation{}; + } // namespace ranges +#endif + +} // namespace etl #include "private/minmax_pop.h" diff --git a/include/etl/alignment.h b/include/etl/alignment.h index 41e8a20c..023acac2 100644 --- a/include/etl/alignment.h +++ b/include/etl/alignment.h @@ -32,12 +32,11 @@ SOFTWARE. #define ETL_ALIGNMENT_INCLUDED #include "platform.h" -#include "type_traits.h" -#include "static_assert.h" #include "error_handler.h" #include "exception.h" +#include "static_assert.h" +#include "type_traits.h" #include "utility.h" -#include "algorithm.h" #include @@ -125,28 +124,28 @@ namespace etl // Matching alignment. template - class type_with_alignment_matcher + class type_with_alignment_matcher { public: - + typedef T1 type; }; // Non-matching alignment template - class type_with_alignment_matcher + class type_with_alignment_matcher { public: - - typedef typename type_with_alignment_matcher < Alignment <= etl::alignment_of::value , Alignment, T2, TRest... > ::type type; + + typedef typename type_with_alignment_matcher< Alignment <= etl::alignment_of::value, Alignment, T2, TRest... >::type type; }; // Non-matching alignment, none left. template - class type_with_alignment_matcher + class type_with_alignment_matcher { public: - + typedef char type; }; @@ -154,23 +153,23 @@ namespace etl // Helper. //*************************************************************************** template - class type_with_alignment_helper + class type_with_alignment_helper { public: - + typedef typename type_with_alignment_matcher::value, Alignment, T1, T...>::type type; }; #else //*************************************************************************** // Matcher. //*************************************************************************** - template + template class type_with_alignment_matcher; // Matching alignment. template - class type_with_alignment_matcher + class type_with_alignment_matcher { public: @@ -179,16 +178,17 @@ namespace etl // Non-matching alignment. template - class type_with_alignment_matcher + class type_with_alignment_matcher { public: - typedef typename type_with_alignment_matcher::value, Alignment, T2, T3, T4, T5, T6, T7, T8, void>::type type; + typedef + typename type_with_alignment_matcher< Alignment <= etl::alignment_of::value, Alignment, T2, T3, T4, T5, T6, T7, T8, void>::type type; }; // Non-matching alignment, none left. template - class type_with_alignment_matcher + class type_with_alignment_matcher { public: @@ -198,16 +198,16 @@ namespace etl //*************************************************************************** // Helper. //*************************************************************************** - template + template class type_with_alignment_helper { public: - typedef typename type_with_alignment_matcher::value, Alignment, T1, T2, T3, T4, T5, T6, T7, T8>::type type; + typedef typename type_with_alignment_matcher< Alignment <= etl::alignment_of::value, Alignment, T1, T2, T3, T4, T5, T6, T7, T8>::type type; }; #endif - } + } // namespace private_alignment //*************************************************************************** /// Gets a type that has the same as the specified alignment. @@ -219,12 +219,17 @@ namespace etl public: #if ETL_USING_CPP11 - typedef struct { alignas(Alignment) char dummy; } type; + typedef struct + { + alignas(Alignment) char dummy; + } type; #else #if ETL_NOT_USING_64BIT_TYPES - typedef typename private_alignment::type_with_alignment_helper::type type; + typedef typename private_alignment::type_with_alignment_helper< Alignment, int_least8_t, int_least16_t, int32_t, float, double, void*>::type type; #else - typedef typename private_alignment::type_with_alignment_helper::type type; + typedef + typename private_alignment::type_with_alignment_helper< Alignment, int_least8_t, int_least16_t, int32_t, int64_t, float, double, void*>::type + type; #endif #endif @@ -248,35 +253,35 @@ namespace etl { /// Convert to T reference. template - operator T& () + operator T&() { - ETL_STATIC_ASSERT((etl::is_same:: value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); + ETL_STATIC_ASSERT((etl::is_same::value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); T* t = *this; return *t; } /// Convert to const T reference. template - operator const T& () const + operator const T&() const { - ETL_STATIC_ASSERT((etl::is_same:: value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); + ETL_STATIC_ASSERT((etl::is_same::value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); const T* t = *this; return *t; } /// Convert to T pointer. template - operator T* () + operator T*() { - ETL_STATIC_ASSERT((etl::is_same:: value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); + ETL_STATIC_ASSERT((etl::is_same::value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); return reinterpret_cast(data); } /// Convert to const T pointer. template - operator const T* () const + operator const T*() const { - ETL_STATIC_ASSERT((etl::is_same:: value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); + ETL_STATIC_ASSERT((etl::is_same::value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); return reinterpret_cast(data); } @@ -284,7 +289,7 @@ namespace etl template T& get_reference() { - ETL_STATIC_ASSERT((etl::is_same:: value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); + ETL_STATIC_ASSERT((etl::is_same::value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); T* t = *this; return *t; } @@ -293,7 +298,7 @@ namespace etl template const T& get_reference() const { - ETL_STATIC_ASSERT((etl::is_same:: value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); + ETL_STATIC_ASSERT((etl::is_same::value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); const T* t = *this; return *t; } @@ -302,7 +307,7 @@ namespace etl template T* get_address() { - ETL_STATIC_ASSERT((etl::is_same:: value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); + ETL_STATIC_ASSERT((etl::is_same::value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); return reinterpret_cast(data); } @@ -310,7 +315,7 @@ namespace etl template const T* get_address() const { - ETL_STATIC_ASSERT((etl::is_same:: value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); + ETL_STATIC_ASSERT((etl::is_same::value || ((Alignment % etl::alignment_of::value) == 0)), "Incompatible alignment"); return reinterpret_cast(data); } @@ -319,8 +324,9 @@ namespace etl #else union { - char data[Length]; - typename etl::type_with_alignment::type etl_alignment_type; // A POD type that has the same alignment as Alignment. + char data[Length]; + typename etl::type_with_alignment::type etl_alignment_type; // A POD type that has the same alignment + // as Alignment. }; #endif }; @@ -374,7 +380,8 @@ namespace etl #if ETL_USING_CPP11 //*************************************************************************** - /// Constructs the instance of T forwarding the given \p args to its constructor. + /// Constructs the instance of T forwarding the given \p args to its + /// constructor. //*************************************************************************** template typed_storage(TArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) @@ -425,8 +432,8 @@ namespace etl #endif //*************************************************************************** - /// Default destructor which will NOT call the destructor of the object which - /// was created by calling create(). + /// Default destructor which will NOT call the destructor of the object + /// which was created by calling create(). //*************************************************************************** ~typed_storage() ETL_NOEXCEPT { @@ -444,67 +451,72 @@ namespace etl #if ETL_USING_CPP11 //*************************************************************************** - /// Constructs the instance of T forwarding the given \p args to its constructor. - /// \returns the instance of T which has been constructed in the internal byte array. + /// Constructs the instance of T forwarding the given \p args to its + /// constructor. \returns the instance of T which has been constructed in + /// the internal byte array. //*************************************************************************** template reference create(TArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (&storage.value) value_type(etl::forward(args)...); - valid = true; + valid = true; return *p; } #else //*************************************************************************** /// Constructs the instance of T with type T1 - /// \returns the instance of T which has been constructed in the internal byte array. + /// \returns the instance of T which has been constructed in the internal + /// byte array. //*************************************************************************** template reference create(const T1& t1) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (&storage.value) value_type(t1); - valid = true; + valid = true; return *p; } //*************************************************************************** /// Constructs the instance of T with types T1, T2 - /// \returns the instance of T which has been constructed in the internal byte array. + /// \returns the instance of T which has been constructed in the internal + /// byte array. //*************************************************************************** template reference create(const T1& t1, const T2& t2) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (&storage.value) value_type(t1, t2); - valid = true; + valid = true; return *p; } //*************************************************************************** /// Constructs the instance of T with types T1, T2, T3 - /// \returns the instance of T which has been constructed in the internal byte array. + /// \returns the instance of T which has been constructed in the internal + /// byte array. //*************************************************************************** template reference create(const T1& t1, const T2& t2, const T3& t3) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (&storage.value) value_type(t1, t2, t3); - valid = true; + valid = true; return *p; } //*************************************************************************** /// Constructs the instance of T with types T1, T2, T3, T4 - /// \returns the instance of T which has been constructed in the internal byte array. + /// \returns the instance of T which has been constructed in the internal + /// byte array. //*************************************************************************** template reference create(const T1& t1, const T2& t2, const T3& t3, const T4& t4) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (&storage.value) value_type(t1, t2, t3, t4); - valid = true; + valid = true; return *p; } #endif @@ -537,7 +549,7 @@ namespace etl const_pointer operator->() const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) { ETL_ASSERT(has_value(), ETL_ERROR(etl::typed_storage_error)); - + return &storage.value; } @@ -560,11 +572,13 @@ namespace etl private: typed_storage(etl::typed_storage&) ETL_DELETE; - typed_storage& operator =(etl::typed_storage&) ETL_DELETE; + typed_storage& operator=(etl::typed_storage&) ETL_DELETE; - struct dummy_t {}; + struct dummy_t + { + }; - //******************************* + //******************************* union union_type { ETL_CONSTEXPR union_type() ETL_NOEXCEPT @@ -572,9 +586,7 @@ namespace etl { } - ~union_type() ETL_NOEXCEPT - { - } + ~union_type() ETL_NOEXCEPT {} dummy_t dummy; value_type value; @@ -601,7 +613,7 @@ namespace etl typedef const T& const_reference; typedef T* pointer; typedef const T* const_pointer; - + template friend ETL_CONSTEXPR14 void swap(typed_storage_ext& lhs, typed_storage_ext& rhs) ETL_NOEXCEPT; @@ -609,15 +621,16 @@ namespace etl /// Constructor. //*************************************************************************** typed_storage_ext(void* pbuffer_) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) - : pbuffer(reinterpret_cast(pbuffer_)), - valid(false) + : pbuffer(reinterpret_cast(pbuffer_)) + , valid(false) { ETL_ASSERT(etl::is_aligned(pbuffer_, etl::alignment_of::value), ETL_ERROR(etl::alignment_error)); } #if ETL_USING_CPP11 //*************************************************************************** - /// Constructs the instance of T forwarding the given \p args to its constructor. + /// Constructs the instance of T forwarding the given \p args to its + /// constructor. //*************************************************************************** template typed_storage_ext(void* pbuffer_, TArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) @@ -690,8 +703,8 @@ namespace etl #endif //*************************************************************************** - /// Default destructor which will NOT call the destructor of the object which - /// was created by calling create(). + /// Default destructor which will NOT call the destructor of the object + /// which was created by calling create(). //*************************************************************************** ~typed_storage_ext() ETL_NOEXCEPT { @@ -709,67 +722,72 @@ namespace etl #if ETL_USING_CPP11 //*************************************************************************** - /// Constructs the instance of T forwarding the given \p args to its constructor. - /// \returns the instance of T which has been constructed in the external buffer. + /// Constructs the instance of T forwarding the given \p args to its + /// constructor. \returns the instance of T which has been constructed in + /// the external buffer. //*************************************************************************** template reference create(TArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (pbuffer) value_type(etl::forward(args)...); - valid = true; + valid = true; return *p; } #else //*************************************************************************** /// Constructs the instance of T with type T1 - /// \returns the instance of T which has been constructed in the external buffer. + /// \returns the instance of T which has been constructed in the external + /// buffer. //*************************************************************************** template reference create(const T1& t1) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (pbuffer) value_type(t1); - valid = true; + valid = true; return *p; } //*************************************************************************** /// Constructs the instance of T with types T1, T2 - /// \returns the instance of T which has been constructed in the external buffer. + /// \returns the instance of T which has been constructed in the external + /// buffer. //*************************************************************************** template reference create(const T1& t1, const T2& t2) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (pbuffer) value_type(t1, t2); - valid = true; + valid = true; return *p; } //*************************************************************************** /// Constructs the instance of T with types T1, T2, T3 - /// \returns the instance of T which has been constructed in the external buffer. + /// \returns the instance of T which has been constructed in the external + /// buffer. //*************************************************************************** template reference create(const T1& t1, const T2& t2, const T3& t3) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (pbuffer) value_type(t1, t2, t3); - valid = true; + valid = true; return *p; } //*************************************************************************** /// Constructs the instance of T with types T1, T2, T3, T4 - /// \returns the instance of T which has been constructed in the external buffer. + /// \returns the instance of T which has been constructed in the external + /// buffer. //*************************************************************************** template reference create(const T1& t1, const T2& t2, const T3& t3, const T4& t4) { ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error)); pointer p = ::new (pbuffer) value_type(t1, t2, t3, t4); - valid = true; + valid = true; return *p; } #endif @@ -825,10 +843,10 @@ namespace etl private: typed_storage_ext(etl::typed_storage_ext&) ETL_DELETE; - typed_storage_ext& operator =(etl::typed_storage_ext&) ETL_DELETE; + typed_storage_ext& operator=(etl::typed_storage_ext&) ETL_DELETE; pointer pbuffer; - bool valid; + bool valid; }; //*************************************************************************** @@ -840,8 +858,8 @@ namespace etl using ETL_OR_STD::swap; swap(lhs.pbuffer, rhs.pbuffer); - swap(lhs.valid, rhs.valid); + swap(lhs.valid, rhs.valid); } -} +} // namespace etl #endif diff --git a/include/etl/array.h b/include/etl/array.h index f1624209..2051807b 100644 --- a/include/etl/array.h +++ b/include/etl/array.h @@ -33,20 +33,20 @@ SOFTWARE. #include "platform.h" #include "algorithm.h" -#include "iterator.h" -#include "functional.h" +#include "error_handler.h" #include "exception.h" -#include "type_traits.h" +#include "functional.h" +#include "initializer_list.h" +#include "iterator.h" +#include "nth_type.h" #include "parameter_type.h" #include "static_assert.h" -#include "error_handler.h" -#include "nth_type.h" -#include "initializer_list.h" +#include "type_traits.h" #include ///\defgroup array array -/// A replacement for std::array if you haven't got C++0x11. +/// A replacement for std::array if you haven't got C++11. ///\ingroup containers namespace etl @@ -81,7 +81,7 @@ namespace etl //*************************************************************************** ///\ingroup array - /// A replacement for std::array if you haven't got C++0x11. + /// A replacement for std::array if you haven't got C++11. //*************************************************************************** template class array @@ -94,15 +94,15 @@ namespace etl static ETL_CONSTANT size_t SIZE = SIZE_; - typedef T value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef T* iterator; - typedef const T* const_iterator; + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef T* iterator; + typedef const T* const_iterator; typedef ETL_OR_STD::reverse_iterator reverse_iterator; typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; @@ -114,9 +114,7 @@ namespace etl /// Returns a reference to the value at index 'i'. ///\param i The index of the element to access. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reference at(size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) + ETL_NODISCARD ETL_CONSTEXPR14 reference at(size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) { ETL_ASSERT(i < SIZE, ETL_ERROR(array_out_of_range)); @@ -127,9 +125,7 @@ namespace etl /// Returns a const reference to the value at index 'i'. ///\param i The index of the element to access. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const_reference at(size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) + ETL_NODISCARD ETL_CONSTEXPR14 const_reference at(size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS) { ETL_ASSERT(i < SIZE, ETL_ERROR(array_out_of_range)); @@ -141,9 +137,7 @@ namespace etl /// Returns a reference to the value at index 'i'. ///\param i The index of the element to access. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reference operator[](size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR) + ETL_NODISCARD ETL_CONSTEXPR14 reference operator[](size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR) { ETL_ASSERT_CHECK_INDEX_OPERATOR(i < SIZE, ETL_ERROR(array_out_of_range)); @@ -155,8 +149,7 @@ namespace etl /// Returns a const reference to the value at index 'i'. ///\param i The index of the element to access. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reference operator[](size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR) + ETL_NODISCARD ETL_CONSTEXPR const_reference operator[](size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR) { // Throwing from c++11 constexpr requires special syntax #if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_INDEX_OPERATOR @@ -171,9 +164,7 @@ namespace etl //************************************************************************* /// Returns a reference to the first element. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reference front() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reference front() ETL_NOEXCEPT { ETL_STATIC_ASSERT(SIZE > 0, "Array is empty."); @@ -183,8 +174,7 @@ namespace etl //************************************************************************* /// Returns a const reference to the first element. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reference front() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reference front() const ETL_NOEXCEPT { ETL_STATIC_ASSERT(SIZE > 0, "Array is empty."); @@ -194,9 +184,7 @@ namespace etl //************************************************************************* /// Returns a reference to the last element. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reference back() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reference back() ETL_NOEXCEPT { ETL_STATIC_ASSERT(SIZE > 0, "Array is empty."); @@ -206,8 +194,7 @@ namespace etl //************************************************************************* /// Returns a const reference to the last element. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reference back() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reference back() const ETL_NOEXCEPT { ETL_STATIC_ASSERT(SIZE > 0, "Array is empty."); @@ -217,9 +204,7 @@ namespace etl //************************************************************************* /// Returns a pointer to the first element of the internal buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - pointer data() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 pointer data() ETL_NOEXCEPT { return _buffer; } @@ -227,8 +212,7 @@ namespace etl //************************************************************************* /// Returns a const pointer to the first element of the internal buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_pointer data() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_pointer data() const ETL_NOEXCEPT { return _buffer; } @@ -240,9 +224,7 @@ namespace etl //************************************************************************* /// Returns an iterator to the beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - iterator begin() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 iterator begin() ETL_NOEXCEPT { return _buffer; } @@ -250,8 +232,7 @@ namespace etl //************************************************************************* /// Returns a const iterator to the beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_iterator begin() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_iterator begin() const ETL_NOEXCEPT { return _buffer; } @@ -259,8 +240,7 @@ namespace etl //************************************************************************* /// Returns a const iterator to the beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_iterator cbegin() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_iterator cbegin() const ETL_NOEXCEPT { return begin(); } @@ -268,9 +248,7 @@ namespace etl //************************************************************************* /// Returns an iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - iterator end() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 iterator end() ETL_NOEXCEPT { return _buffer + SIZE; } @@ -278,8 +256,7 @@ namespace etl //************************************************************************* /// Returns a const iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_iterator end() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_iterator end() const ETL_NOEXCEPT { return _buffer + SIZE; } @@ -287,8 +264,7 @@ namespace etl //************************************************************************* // Returns a const iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_iterator cend() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_iterator cend() const ETL_NOEXCEPT { return _buffer + SIZE; } @@ -296,9 +272,7 @@ namespace etl //************************************************************************* // Returns an reverse iterator to the reverse beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reverse_iterator rbegin() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reverse_iterator rbegin() ETL_NOEXCEPT { return reverse_iterator(end()); } @@ -306,8 +280,7 @@ namespace etl //************************************************************************* /// Returns a const reverse iterator to the reverse beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reverse_iterator rbegin() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator rbegin() const ETL_NOEXCEPT { return const_reverse_iterator(end()); } @@ -315,8 +288,7 @@ namespace etl //************************************************************************* /// Returns a const reverse iterator to the reverse beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reverse_iterator crbegin() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator crbegin() const ETL_NOEXCEPT { return const_reverse_iterator(end()); } @@ -324,9 +296,7 @@ namespace etl //************************************************************************* /// Returns a reverse iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reverse_iterator rend() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reverse_iterator rend() ETL_NOEXCEPT { return reverse_iterator(begin()); } @@ -334,8 +304,7 @@ namespace etl //************************************************************************* /// Returns a const reverse iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reverse_iterator rend() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator rend() const ETL_NOEXCEPT { return const_reverse_iterator(begin()); } @@ -343,8 +312,7 @@ namespace etl //************************************************************************* /// Returns a const reverse iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reverse_iterator crend() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator crend() const ETL_NOEXCEPT { return const_reverse_iterator(begin()); } @@ -356,8 +324,7 @@ namespace etl //************************************************************************* /// Returns true if the array size is zero. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT { return (SIZE == 0); } @@ -365,8 +332,7 @@ namespace etl //************************************************************************* /// Returns the size of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT { return SIZE; } @@ -374,8 +340,7 @@ namespace etl //************************************************************************* /// Returns the maximum possible size of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR size_t max_size() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR size_t max_size() const ETL_NOEXCEPT { return SIZE; } @@ -409,7 +374,8 @@ namespace etl //************************************************************************* /// Fills the array from the range. - /// If the range is smaller than the array then the unused array elements are left unmodified. + /// If the range is smaller than the array then the unused array elements + /// are left unmodified. ///\param first The iterator to the first item in the range. ///\param last The iterator to one past the final item in the range. ///\return An iterator to the first unassigned array element, or end(). @@ -422,7 +388,8 @@ namespace etl //************************************************************************* /// Fills the array from the range. - /// If the range is smaller than the array then the unused array elements are initialised with the supplied value. + /// If the range is smaller than the array then the unused array elements + /// are initialised with the supplied value. ///\param first The iterator to the first item in the range. ///\param last The iterator to one past the final item in the range. ///\return An iterator to the first array element set to 'value', or end(). @@ -496,13 +463,13 @@ namespace etl iterator p = to_iterator(position); iterator result(p); - size_t source_size = etl::distance(first, last); - size_t destination_space = etl::distance(position, cend()); + size_t source_size = static_cast(etl::distance(first, last)); + size_t destination_space = static_cast(etl::distance(position, cend())); // Do we need to move anything? if (source_size < destination_space) { - size_t length = SIZE - (etl::distance(begin(), p) + source_size); + size_t length = SIZE - (static_cast(etl::distance(begin(), p)) + source_size); etl::move_backward(p, p + length, end()); } @@ -570,7 +537,8 @@ namespace etl //************************************************************************* /// Erases a value from the array. ///\param position The index of the position to erase at. - ///\param value The value to use to overwrite the last element in the array. + ///\param value The value to use to overwrite the last element in the + /// array. //************************************************************************* inline iterator erase_at(size_t position, parameter_t value) { @@ -582,7 +550,8 @@ namespace etl //************************************************************************* /// Erases a value from the array. ///\param position The iterator to the position to erase at. - ///\param value The value to use to overwrite the last element in the array. + ///\param value The value to use to overwrite the last element in the + /// array. //************************************************************************* iterator erase(const_iterator position, parameter_t value) { @@ -600,7 +569,8 @@ namespace etl /// Erases a range of values from the array. ///\param first The first item to erase. ///\param last The one past the last item to erase. - ///\param value The value to use to overwrite the last elements in the array. + ///\param value The value to use to overwrite the last elements in the + /// array. //************************************************************************* iterator erase_range(size_t first, size_t last, parameter_t value) { @@ -613,7 +583,8 @@ namespace etl /// Erases a range of values from the array. ///\param first The first item to erase. ///\param last The one past the last item to erase. - ///\param value The value to use to overwrite the last elements in the array. + ///\param value The value to use to overwrite the last elements in the + /// array. //************************************************************************* iterator erase(const_iterator first, const_iterator last, parameter_t value) { @@ -646,7 +617,7 @@ namespace etl //*************************************************************************** ///\ingroup array - /// A replacement for std::array if you haven't got C++0x11. + /// A replacement for std::array if you haven't got C++11. /// Specialisation for zero sized array. //*************************************************************************** template @@ -660,15 +631,15 @@ namespace etl static ETL_CONSTANT size_t SIZE = 0; - typedef T value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef T* iterator; - typedef const T* const_iterator; + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef T* iterator; + typedef const T* const_iterator; typedef ETL_OR_STD::reverse_iterator reverse_iterator; typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; @@ -680,9 +651,7 @@ namespace etl /// Returns a reference to the value at index 'i'. ///\param i The index of the element to access. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reference at(size_t) ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reference at(size_t) ETL_NOEXCEPT { return *data(); } @@ -691,9 +660,7 @@ namespace etl /// Returns a const reference to the value at index 'i'. ///\param i The index of the element to access. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const_reference at(size_t) const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 const_reference at(size_t) const ETL_NOEXCEPT { return *data(); } @@ -703,9 +670,7 @@ namespace etl /// Returns a reference to the value at index 'i'. ///\param i The index of the element to access. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reference operator[](size_t) ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reference operator[](size_t) ETL_NOEXCEPT { return *data(); } @@ -715,8 +680,7 @@ namespace etl /// Returns a const reference to the value at index 'i'. ///\param i The index of the element to access. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reference operator[](size_t) const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reference operator[](size_t) const ETL_NOEXCEPT { return *data(); } @@ -724,9 +688,7 @@ namespace etl //************************************************************************* /// Returns a reference to the first element. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reference front() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reference front() ETL_NOEXCEPT { return *data(); } @@ -734,8 +696,7 @@ namespace etl //************************************************************************* /// Returns a const reference to the first element. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reference front() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reference front() const ETL_NOEXCEPT { return *data(); } @@ -743,9 +704,7 @@ namespace etl //************************************************************************* /// Returns a reference to the last element. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reference back() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reference back() ETL_NOEXCEPT { return *data(); } @@ -753,8 +712,7 @@ namespace etl //************************************************************************* /// Returns a const reference to the last element. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reference back() const + ETL_NODISCARD ETL_CONSTEXPR const_reference back() const { return *data(); } @@ -762,9 +720,7 @@ namespace etl //************************************************************************* /// Returns a pointer to the first element of the internal buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - pointer data() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 pointer data() ETL_NOEXCEPT { return (T*)0; } @@ -772,8 +728,7 @@ namespace etl //************************************************************************* /// Returns a const pointer to the first element of the internal buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_pointer data() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_pointer data() const ETL_NOEXCEPT { return (const T*)0; } @@ -785,9 +740,7 @@ namespace etl //************************************************************************* /// Returns an iterator to the beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - iterator begin() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 iterator begin() ETL_NOEXCEPT { return iterator(); } @@ -795,8 +748,7 @@ namespace etl //************************************************************************* /// Returns a const iterator to the beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_iterator begin() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_iterator begin() const ETL_NOEXCEPT { return const_iterator(); } @@ -804,8 +756,7 @@ namespace etl //************************************************************************* /// Returns a const iterator to the beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_iterator cbegin() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_iterator cbegin() const ETL_NOEXCEPT { return const_iterator(); } @@ -813,9 +764,7 @@ namespace etl //************************************************************************* /// Returns an iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - iterator end() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 iterator end() ETL_NOEXCEPT { return iterator(); } @@ -823,8 +772,7 @@ namespace etl //************************************************************************* /// Returns a const iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_iterator end() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_iterator end() const ETL_NOEXCEPT { return const_iterator(); } @@ -832,8 +780,7 @@ namespace etl //************************************************************************* // Returns a const iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_iterator cend() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_iterator cend() const ETL_NOEXCEPT { return const_iterator(); } @@ -841,9 +788,7 @@ namespace etl //************************************************************************* // Returns an reverse iterator to the reverse beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reverse_iterator rbegin() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reverse_iterator rbegin() ETL_NOEXCEPT { return reverse_iterator(end()); } @@ -851,8 +796,7 @@ namespace etl //************************************************************************* /// Returns a const reverse iterator to the reverse beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reverse_iterator rbegin() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator rbegin() const ETL_NOEXCEPT { return const_reverse_iterator(end()); } @@ -860,8 +804,7 @@ namespace etl //************************************************************************* /// Returns a const reverse iterator to the reverse beginning of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reverse_iterator crbegin() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator crbegin() const ETL_NOEXCEPT { return const_reverse_iterator(end()); } @@ -869,9 +812,7 @@ namespace etl //************************************************************************* /// Returns a reverse iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - reverse_iterator rend() ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR14 reverse_iterator rend() ETL_NOEXCEPT { return reverse_iterator(begin()); } @@ -879,8 +820,7 @@ namespace etl //************************************************************************* /// Returns a const reverse iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reverse_iterator rend() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator rend() const ETL_NOEXCEPT { return const_reverse_iterator(begin()); } @@ -888,8 +828,7 @@ namespace etl //************************************************************************* /// Returns a const reverse iterator to the end of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR const_reverse_iterator crend() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator crend() const ETL_NOEXCEPT { return const_reverse_iterator(begin()); } @@ -901,8 +840,7 @@ namespace etl //************************************************************************* /// Returns true if the array size is zero. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT { return true; } @@ -910,8 +848,7 @@ namespace etl //************************************************************************* /// Returns the size of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT { return 0; } @@ -919,8 +856,7 @@ namespace etl //************************************************************************* /// Returns the maximum possible size of the array. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR size_t max_size() const ETL_NOEXCEPT + ETL_NODISCARD ETL_CONSTEXPR size_t max_size() const ETL_NOEXCEPT { return 0; } @@ -947,7 +883,8 @@ namespace etl //************************************************************************* /// Fills the array from the range. - /// If the range is smaller than the array then the unused array elements are left unmodified. + /// If the range is smaller than the array then the unused array elements + /// are left unmodified. ///\param first The iterator to the first item in the range. ///\param last The iterator to one past the final item in the range. ///\return An iterator to the first unassigned array element, or end(). @@ -960,7 +897,8 @@ namespace etl //************************************************************************* /// Fills the array from the range. - /// If the range is smaller than the array then the unused array elements are initialised with the supplied value. + /// If the range is smaller than the array then the unused array elements + /// are initialised with the supplied value. ///\param first The iterator to the first item in the range. ///\param last The iterator to one past the final item in the range. ///\return An iterator to the first array element set to 'value', or end(). @@ -1060,7 +998,8 @@ namespace etl //************************************************************************* /// Erases a value from the array. ///\param position The index of the position to erase at. - ///\param value The value to use to overwrite the last element in the array. + ///\param value The value to use to overwrite the last element in the + /// array. //************************************************************************* inline iterator erase_at(size_t, parameter_t) ETL_NOEXCEPT { @@ -1070,7 +1009,8 @@ namespace etl //************************************************************************* /// Erases a value from the array. ///\param position The iterator to the position to erase at. - ///\param value The value to use to overwrite the last element in the array. + ///\param value The value to use to overwrite the last element in the + /// array. //************************************************************************* iterator erase(const_iterator, parameter_t) ETL_NOEXCEPT { @@ -1081,7 +1021,8 @@ namespace etl /// Erases a range of values from the array. ///\param first The first item to erase. ///\param last The one past the last item to erase. - ///\param value The value to use to overwrite the last elements in the array. + ///\param value The value to use to overwrite the last elements in the + /// array. //************************************************************************* iterator erase_range(size_t, size_t, parameter_t) ETL_NOEXCEPT { @@ -1091,7 +1032,8 @@ namespace etl //************************************************************************* /// Erases a range of values from the array. ///\param position The iterator to the position to erase at. - ///\param value The value to use to overwrite the last elements in the array. + ///\param value The value to use to overwrite the last elements in the + /// array. //************************************************************************* iterator erase(const_iterator, const_iterator, parameter_t) ETL_NOEXCEPT { @@ -1105,7 +1047,7 @@ namespace etl #if ETL_USING_CPP17 template array(T...) -> array::type, sizeof...(T)>; -#endif +#endif //************************************************************************* /// Make @@ -1114,7 +1056,7 @@ namespace etl template constexpr auto make_array(TValues&&... values) ETL_NOEXCEPT -> etl::array { - return { etl::forward(values)... }; + return {etl::forward(values)...}; } #endif @@ -1124,7 +1066,7 @@ namespace etl ///\param rhs The second array. //************************************************************************* template - void swap(etl::array &lhs, etl::array &rhs) + void swap(etl::array& lhs, etl::array& rhs) { lhs.swap(rhs); } @@ -1136,7 +1078,7 @@ namespace etl ///\return true if the arrays are equal, otherwise false //************************************************************************* template - ETL_CONSTEXPR14 bool operator ==(const etl::array& lhs, const etl::array& rhs) + ETL_CONSTEXPR14 bool operator==(const etl::array& lhs, const etl::array& rhs) { return etl::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()); } @@ -1148,7 +1090,7 @@ namespace etl ///\return true if the arrays are not equal, otherwise false //************************************************************************* template - ETL_CONSTEXPR14 bool operator !=(const etl::array& lhs, const etl::array& rhs) + ETL_CONSTEXPR14 bool operator!=(const etl::array& lhs, const etl::array& rhs) { return !(lhs == rhs); } @@ -1157,25 +1099,25 @@ namespace etl /// Less than operator. ///\param lhs The first array. ///\param rhs The second array. - ///\return true if the first array is lexicographically less than the second, otherwise false + ///\return true if the first array is lexicographically less than the + /// second, otherwise false //************************************************************************* template - bool operator <(const etl::array& lhs, const etl::array& rhs) + bool operator<(const etl::array& lhs, const etl::array& rhs) { - return etl::lexicographical_compare(lhs.cbegin(), - lhs.cend(), - rhs.cbegin(), - rhs.cend()); + return etl::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend()); } //************************************************************************* /// Less than or equal operator. ///\param lhs The first array. ///\param rhs The second array. - ///\return true if the first array is lexicographically less than or equal to the second, otherwise false + ///\return true if the first array is lexicographically less than or + /// equal to the second, otherwise + ///< b>false //************************************************************************* template - bool operator <=(const etl::array& lhs, const etl::array& rhs) + bool operator<=(const etl::array& lhs, const etl::array& rhs) { return !(lhs > rhs); } @@ -1184,10 +1126,11 @@ namespace etl /// Greater than operator. ///\param lhs The first array. ///\param rhs The second array. - ///\return true if the first array is lexicographically greater than the second, otherwise false + ///\return true if the first array is lexicographically greater than + /// the second, otherwise false template //************************************************************************* - bool operator >(const etl::array& lhs, const etl::array& rhs) + bool operator>(const etl::array& lhs, const etl::array& rhs) { return (rhs < lhs); } @@ -1196,10 +1139,12 @@ namespace etl /// Greater than or equal operator. ///\param lhs The first array. ///\param rhs The second array. - ///\return true if the first array is lexicographically greater than or equal to the second, otherwise false + ///\return true if the first array is lexicographically greater than or + /// equal to the second, otherwise + ///< b>false //************************************************************************* template - bool operator >=(const etl::array& lhs, const etl::array& rhs) + bool operator>=(const etl::array& lhs, const etl::array& rhs) { return !(lhs < rhs); } @@ -1233,6 +1178,6 @@ namespace etl ETL_STATIC_ASSERT(Index < Size, "Index out of bounds"); return a[Index]; } -} +} // namespace etl #endif diff --git a/include/etl/array_view.h b/include/etl/array_view.h index 5015d55e..bb25dac0 100644 --- a/include/etl/array_view.h +++ b/include/etl/array_view.h @@ -32,18 +32,18 @@ SOFTWARE. #define ETL_ARRAY_VIEW_INCLUDED #include "platform.h" -#include "memory.h" +#include "algorithm.h" #include "array.h" -#include "iterator.h" #include "error_handler.h" #include "exception.h" -#include "nullptr.h" #include "hash.h" -#include "algorithm.h" +#include "iterator.h" +#include "memory.h" +#include "nullptr.h" #include "type_traits.h" #if ETL_USING_STL && ETL_USING_CPP11 -#include + #include #endif ///\defgroup array array @@ -93,6 +93,19 @@ namespace etl } }; + //*************************************************************************** + /// The exception thrown when the view is empty. + //*************************************************************************** + class array_view_empty : public array_view_exception + { + public: + + array_view_empty(string_type file_name_, numeric_type line_number_) + : array_view_exception(ETL_ERROR_TEXT("array_view:empty", ETL_ARRAY_VIEW_FILE_ID"C"), file_name_, line_number_) + { + } + }; + //*************************************************************************** /// Array view. //*************************************************************************** @@ -101,22 +114,22 @@ namespace etl { public: - typedef T value_type; - typedef size_t size_type; - typedef const T& const_reference; - typedef const T* const_pointer; - typedef const T* const_iterator; + typedef T value_type; + typedef size_t size_type; + typedef const T& const_reference; + typedef const T* const_pointer; + typedef const T* const_iterator; typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; #if defined(ETL_ARRAY_VIEW_IS_MUTABLE) - typedef T* pointer; - typedef T& reference; - typedef T* iterator; + typedef T* pointer; + typedef T& reference; + typedef T* iterator; typedef ETL_OR_STD::reverse_iterator reverse_iterator; #else - typedef const_pointer pointer; - typedef const_reference reference; - typedef const_pointer iterator; + typedef const_pointer pointer; + typedef const_reference reference; + typedef const_pointer iterator; typedef const_reverse_iterator reverse_iterator; #endif @@ -124,8 +137,8 @@ namespace etl /// Default constructor. //************************************************************************* ETL_CONSTEXPR array_view() ETL_NOEXCEPT - : mbegin(ETL_NULLPTR), - mend(ETL_NULLPTR) + : mbegin(ETL_NULLPTR) + , mend(ETL_NULLPTR) { } @@ -133,7 +146,8 @@ namespace etl //************************************************************************* /// Construct from etl::array. //************************************************************************* - template , etl::remove_cv_t>::value, void>::type> + template < typename U, size_t Size, + typename = typename etl::enable_if< etl::is_same, etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR array_view(etl::array& a) ETL_NOEXCEPT : mbegin(a.data()) , mend(a.data() + a.size()) @@ -143,7 +157,8 @@ namespace etl //************************************************************************* /// Construct from etl::array. //************************************************************************* - template , etl::remove_cv_t>::value, void>::type> + template < typename U, size_t Size, + typename = typename etl::enable_if< etl::is_same, etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR array_view(const etl::array& a) ETL_NOEXCEPT : mbegin(a.data()) , mend(a.data() + a.size()) @@ -154,7 +169,9 @@ namespace etl /// Construct from etl::array. //************************************************************************* template - ETL_CONSTEXPR array_view(etl::array& a, typename etl::enable_if::type, typename etl::remove_cv::type>::value, void>::type* = 0) ETL_NOEXCEPT + ETL_CONSTEXPR array_view( + etl::array& a, + typename etl::enable_if< etl::is_same::type, typename etl::remove_cv::type>::value, void>::type* = 0) ETL_NOEXCEPT : mbegin(a.data()) , mend(a.data() + a.size()) { @@ -164,7 +181,9 @@ namespace etl /// Construct from etl::array. //************************************************************************* template - ETL_CONSTEXPR array_view(const etl::array& a, typename etl::enable_if::type, typename etl::remove_cv::type>::value, void>::type* = 0) ETL_NOEXCEPT + ETL_CONSTEXPR array_view( + const etl::array& a, + typename etl::enable_if< etl::is_same::type, typename etl::remove_cv::type>::value, void>::type* = 0) ETL_NOEXCEPT : mbegin(a.data()) , mend(a.data() + a.size()) { @@ -175,7 +194,8 @@ namespace etl //************************************************************************* /// Construct from std::array. //************************************************************************* - template , etl::remove_cv_t>::value, void>::type> + template < typename U, size_t Size, + typename = typename etl::enable_if< etl::is_same, etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR array_view(std::array& a) ETL_NOEXCEPT : mbegin(a.data()) , mend(a.data() + a.size()) @@ -185,7 +205,8 @@ namespace etl //************************************************************************* /// Construct from std::array. //************************************************************************* - template , etl::remove_cv_t>::value, void>::type> + template < typename U, size_t Size, + typename = typename etl::enable_if< etl::is_same, etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR array_view(const std::array& a) ETL_NOEXCEPT : mbegin(a.data()) , mend(a.data() + a.size()) @@ -198,10 +219,12 @@ namespace etl /// Construct from a container or other type that supports /// data() and size() member functions. //************************************************************************* - template >::value && - !etl::is_array>::value && - etl::is_same, etl::remove_cv_t::value_type>>::value, void>::type> - ETL_CONSTEXPR array_view(TContainer&& a) ETL_NOEXCEPT + template < typename TContainer, + typename = typename etl::enable_if< + !etl::is_pointer>::value && !etl::is_array>::value + && etl::is_same, etl::remove_cv_t::value_type>>::value, + void>::type> + ETL_CONSTEXPR array_view(TContainer&& a) ETL_NOEXCEPT : mbegin(a.data()) , mend(a.data() + a.size()) { @@ -212,9 +235,12 @@ namespace etl /// data() and size() member functions. //************************************************************************* template - ETL_CONSTEXPR array_view(TContainer& a, typename etl::enable_if::type>::value && - !etl::is_array::value && - etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT + ETL_CONSTEXPR array_view(TContainer& a, + typename etl::enable_if< + !etl::is_pointer< typename etl::remove_reference::type>::value && !etl::is_array::value + && etl::is_same< typename etl::remove_cv::type, + typename etl::remove_cv::type::value_type>::type>::value, + void>::type* = 0) ETL_NOEXCEPT : mbegin(a.data()) , mend(a.data() + a.size()) { @@ -225,9 +251,12 @@ namespace etl /// data() and size() member functions. //************************************************************************* template - ETL_CONSTEXPR array_view(const TContainer& a, typename etl::enable_if::type>::value && - !etl::is_array::value && - etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT + ETL_CONSTEXPR array_view(const TContainer& a, + typename etl::enable_if< + !etl::is_pointer< typename etl::remove_reference::type>::value && !etl::is_array::value + && etl::is_same< typename etl::remove_cv::type, + typename etl::remove_cv::type::value_type>::type>::value, + void>::type* = 0) ETL_NOEXCEPT : mbegin(a.data()) , mend(a.data() + a.size()) { @@ -239,29 +268,28 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR array_view(const TIterator begin_, const TIterator end_) ETL_NOEXCEPT - : mbegin(etl::to_address(begin_)), - mend(etl::to_address(begin_) + etl::distance(begin_, end_)) + : mbegin(etl::to_address(begin_)) + , mend(etl::to_address(begin_) + etl::distance(begin_, end_)) { } //************************************************************************* /// Construct from iterator and size //************************************************************************* - template + template ETL_CONSTEXPR array_view(const TIterator begin_, const TSize size_) ETL_NOEXCEPT - : mbegin(etl::to_address(begin_)), - mend(etl::to_address(begin_) + size_) + : mbegin(etl::to_address(begin_)) + , mend(etl::to_address(begin_) + size_) { } //************************************************************************* /// Construct from C array //************************************************************************* - template - ETL_CONSTEXPR array_view(T(&begin_)[Array_Size]) ETL_NOEXCEPT - : mbegin(begin_), - mend(begin_ + Array_Size) + template + ETL_CONSTEXPR array_view(T (&begin_)[Array_Size]) ETL_NOEXCEPT + : mbegin(begin_) + , mend(begin_ + Array_Size) { } @@ -269,40 +297,52 @@ namespace etl /// Copy constructor //************************************************************************* ETL_CONSTEXPR array_view(const array_view& other) ETL_NOEXCEPT - : mbegin(other.mbegin), - mend(other.mend) + : mbegin(other.mbegin) + , mend(other.mend) { } //************************************************************************* /// Returns a reference to the first element. + /// If asserts or exceptions are enabled, throws an etl::array_view_empty if + /// the view is empty. //************************************************************************* reference front() { + ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(array_view_empty)); return *mbegin; } //************************************************************************* /// Returns a const reference to the first element. + /// If asserts or exceptions are enabled, throws an etl::array_view_empty if + /// the view is empty. //************************************************************************* const_reference front() const { + ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(array_view_empty)); return *mbegin; } //************************************************************************* /// Returns a reference to the last element. + /// If asserts or exceptions are enabled, throws an etl::array_view_empty if + /// the view is empty. //************************************************************************* reference back() { + ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(array_view_empty)); return *(mend - 1); } //************************************************************************* /// Returns a const reference to the last element. + /// If asserts or exceptions are enabled, throws an etl::array_view_empty if + /// the view is empty. //************************************************************************* const_reference back() const { + ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(array_view_empty)); return *(mend - 1); } @@ -465,8 +505,7 @@ namespace etl //************************************************************************* /// Assign from iterator and size. //************************************************************************* - template + template void assign(const TIterator begin_, const TSize size_) { mbegin = etl::to_address(begin_); @@ -476,18 +515,26 @@ namespace etl #if defined(ETL_ARRAY_VIEW_IS_MUTABLE) //************************************************************************* /// Returns a reference to the indexed value. + /// If asserts or exceptions are enabled, throws an etl::array_view_bounds + /// if the index is out of bounds. //************************************************************************* - reference operator[](const size_t i) ETL_NOEXCEPT + reference operator[](const size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR) { + ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(array_view_bounds)); + return mbegin[i]; } #endif //************************************************************************* /// Returns a const reference to the indexed value. + /// If asserts or exceptions are enabled, throws an etl::array_view_bounds + /// if the index is out of bounds. //************************************************************************* - const_reference operator[](const size_t i) const ETL_NOEXCEPT + const_reference operator[](const size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR) { + ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(array_view_bounds)); + return mbegin[i]; } @@ -529,10 +576,10 @@ namespace etl //************************************************************************* void remove_prefix(const size_type n) ETL_NOEXCEPT { - if (n < size()) - mbegin += n; - else - mbegin = mend; + if (n < size()) + mbegin += n; + else + mbegin = mend; } //************************************************************************* @@ -540,10 +587,10 @@ namespace etl //************************************************************************* void remove_suffix(const size_type n) ETL_NOEXCEPT { - if (n < size()) - mend -= n; - else - mend = mbegin; + if (n < size()) + mend -= n; + else + mend = mbegin; } //************************************************************************* @@ -557,16 +604,15 @@ namespace etl //************************************************************************* /// Equality for array views. //************************************************************************* - friend bool operator == (const array_view& lhs, const array_view& rhs) + friend bool operator==(const array_view& lhs, const array_view& rhs) { - return (lhs.size() == rhs.size()) && - etl::equal(lhs.begin(), lhs.end(), rhs.begin()); + return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin()); } //************************************************************************* /// Inequality for array views. //************************************************************************* - friend bool operator != (const array_view& lhs, const array_view& rhs) + friend bool operator!=(const array_view& lhs, const array_view& rhs) { return !(lhs == rhs); } @@ -574,7 +620,7 @@ namespace etl //************************************************************************* /// Less-than for array views. //************************************************************************* - friend bool operator < (const array_view& lhs, const array_view& rhs) + friend bool operator<(const array_view& lhs, const array_view& rhs) { return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } @@ -582,7 +628,7 @@ namespace etl //************************************************************************* /// Greater-than for array views. //************************************************************************* - friend bool operator > (const array_view& lhs, const array_view& rhs) + friend bool operator>(const array_view& lhs, const array_view& rhs) { return rhs < lhs; } @@ -590,7 +636,7 @@ namespace etl //************************************************************************* /// Less-than-equal for array views. //************************************************************************* - friend bool operator <= (const array_view& lhs, const array_view& rhs) + friend bool operator<=(const array_view& lhs, const array_view& rhs) { return !(lhs > rhs); } @@ -598,7 +644,7 @@ namespace etl //************************************************************************* /// Greater-than-equal for array views. //************************************************************************* - friend bool operator >= (const array_view& lhs, const array_view& rhs) + friend bool operator>=(const array_view& lhs, const array_view& rhs) { return !(lhs < rhs); } @@ -614,18 +660,14 @@ namespace etl //************************************************************************* #if ETL_USING_CPP17 template - array_view(TArray& a) - -> array_view; + array_view(TArray& a) -> array_view; template - array_view(const TIterator begin_, const TIterator end_) - -> array_view>; + array_view(const TIterator begin_, const TIterator end_) -> array_view>; - template - array_view(const TIterator begin_, const TSize size_) - -> array_view>; -#endif + template + array_view(const TIterator begin_, const TSize size_) -> array_view>; +#endif //************************************************************************* /// Hash function. @@ -641,7 +683,7 @@ namespace etl } }; #endif -} +} // namespace etl //************************************************************************* /// Swaps the values. diff --git a/include/etl/array_wrapper.h b/include/etl/array_wrapper.h index b422634d..2c434a05 100644 --- a/include/etl/array_wrapper.h +++ b/include/etl/array_wrapper.h @@ -32,12 +32,12 @@ SOFTWARE. #define ETL_ARRAY_WRAPPER_INCLUDED #include "platform.h" -#include "iterator.h" +#include "algorithm.h" #include "error_handler.h" #include "exception.h" #include "hash.h" +#include "iterator.h" #include "parameter_type.h" -#include "algorithm.h" ///\defgroup array array /// A wrapper for arrays @@ -75,19 +75,19 @@ namespace etl //*************************************************************************** /// Array wrapper. //*************************************************************************** - template + template class array_wrapper { public: - typedef T value_type; - typedef size_t size_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef T* iterator; - typedef const T* const_iterator; + typedef T value_type; + typedef size_t size_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef T* iterator; + typedef const T* const_iterator; typedef ETL_OR_STD::reverse_iterator reverse_iterator; typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; @@ -268,18 +268,29 @@ namespace etl //************************************************************************* /// Returns a reference to the indexed value. + /// If asserts or exceptions are enabled, throws an + /// etl::array_wrapper_bounds if the index is out of bounds. //************************************************************************* - reference operator[](size_t i) ETL_NOEXCEPT + reference operator[](size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR) { + ETL_ASSERT_CHECK_INDEX_OPERATOR(i < SIZE, ETL_ERROR(etl::array_wrapper_bounds)); return ARRAY_[i]; } //************************************************************************* /// Returns a const reference to the indexed value. + /// If asserts or exceptions are enabled, throws an + /// etl::array_wrapper_bounds if the index is out of bounds. //************************************************************************* - ETL_CONSTEXPR const_reference operator[](size_t i) const ETL_NOEXCEPT + ETL_CONSTEXPR const_reference operator[](size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR) { + // Throwing from c++11 constexpr requires special syntax +#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_INDEX_OPERATOR + return i < SIZE ? ARRAY_[i] : throw(ETL_ERROR(etl::array_wrapper_bounds)); +#else + ETL_ASSERT_CHECK_INDEX_OPERATOR(i < SIZE, ETL_ERROR(etl::array_wrapper_bounds)); return ARRAY_[i]; +#endif } //************************************************************************* @@ -311,9 +322,8 @@ namespace etl //************************************************************************* /// Swaps the contents of arrays. //************************************************************************* - template - typename etl::enable_if::value, void>::type - swap(etl::array_wrapper& other) + template + typename etl::enable_if::value, void>::type swap(etl::array_wrapper& other) { using ETL_OR_STD::swap; // Allow ADL @@ -327,9 +337,8 @@ namespace etl //************************************************************************* /// Equality for array wrappers. //************************************************************************* - template - bool operator == (const etl::array_wrapper& lhs, - const etl::array_wrapper& rhs) + template + bool operator==(const etl::array_wrapper& lhs, const etl::array_wrapper& rhs) { return (SIZEL == SIZER) && etl::equal(lhs.begin(), lhs.end(), rhs.begin()); } @@ -337,9 +346,8 @@ namespace etl //************************************************************************* /// Inequality for array wrapper. //************************************************************************* - template - bool operator != (const etl::array_wrapper& lhs, - const etl::array_wrapper& rhs) + template + bool operator!=(const etl::array_wrapper& lhs, const etl::array_wrapper& rhs) { return !(lhs == rhs); } @@ -347,9 +355,8 @@ namespace etl //************************************************************************* /// Less-than for array wrapper. //************************************************************************* - template - bool operator < (const etl::array_wrapper& lhs, - const etl::array_wrapper& rhs) + template + bool operator<(const etl::array_wrapper& lhs, const etl::array_wrapper& rhs) { return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } @@ -357,9 +364,8 @@ namespace etl //************************************************************************* /// Greater-than for array wrapper. //************************************************************************* - template - bool operator > (const etl::array_wrapper& lhs, - const etl::array_wrapper& rhs) + template + bool operator>(const etl::array_wrapper& lhs, const etl::array_wrapper& rhs) { return rhs < lhs; } @@ -367,9 +373,8 @@ namespace etl //************************************************************************* /// Less-than-equal for array wrapper. //************************************************************************* - template - bool operator <= (const etl::array_wrapper& lhs, - const etl::array_wrapper& rhs) + template + bool operator<=(const etl::array_wrapper& lhs, const etl::array_wrapper& rhs) { return !(lhs > rhs); } @@ -377,9 +382,8 @@ namespace etl //************************************************************************* /// Greater-than-equal for array wrapper. //************************************************************************* - template - bool operator >= (const etl::array_wrapper& lhs, - const etl::array_wrapper& rhs) + template + bool operator>=(const etl::array_wrapper& lhs, const etl::array_wrapper& rhs) { return !(lhs < rhs); } @@ -388,7 +392,7 @@ namespace etl /// Hash function. //************************************************************************* #if ETL_USING_8BIT_TYPES - template + template struct hash > { size_t operator()(const etl::array_wrapper& aw) const @@ -400,19 +404,17 @@ namespace etl } }; #endif -} +} // namespace etl //************************************************************************* /// Swap. //************************************************************************* -template -void swap(etl::array_wrapper& lhs, - etl::array_wrapper& rhs) +template +void swap(etl::array_wrapper& lhs, etl::array_wrapper& rhs) { lhs.swap(rhs); } -#define ETL_ARRAY_WRAPPER(arraytype, arrayobject) etl::array_wrapper +#define ETL_ARRAY_WRAPPER(arraytype, arrayobject) etl::array_wrapper #endif - diff --git a/include/etl/atomic.h b/include/etl/atomic.h index 9d18ee5a..b3a556a5 100644 --- a/include/etl/atomic.h +++ b/include/etl/atomic.h @@ -32,7 +32,7 @@ SOFTWARE. #include "platform.h" #if ETL_HAS_ATOMIC - #if (ETL_USING_CPP11 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))) + #if (ETL_USING_CPP11 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))) #include "atomic/atomic_std.h" #elif defined(ETL_COMPILER_ARM5) #include "atomic/atomic_arm.h" diff --git a/include/etl/atomic/atomic_gcc_sync.h b/include/etl/atomic/atomic_gcc_sync.h index de7b8d5a..087489aa 100644 --- a/include/etl/atomic/atomic_gcc_sync.h +++ b/include/etl/atomic/atomic_gcc_sync.h @@ -30,11 +30,11 @@ SOFTWARE. #define ETL_ATOMIC_GCC_SYNC_INCLUDED #include "../platform.h" -#include "../type_traits.h" -#include "../static_assert.h" -#include "../nullptr.h" #include "../char_traits.h" #include "../mutex.h" +#include "../nullptr.h" +#include "../static_assert.h" +#include "../type_traits.h" #include #include @@ -75,12 +75,20 @@ namespace etl { #if defined(ETL_USE_ATOMIC_BUILTINS) -#define ETL_BUILTIN_LOCK do { while (__atomic_test_and_set(&flag, etl::memory_order_seq_cst)) {} } while (0) -#define ETL_BUILTIN_UNLOCK do { __atomic_clear(&flag, etl::memory_order_seq_cst); } while (0) + #define ETL_BUILTIN_LOCK \ + do { \ + while (__atomic_test_and_set(&flag, etl::memory_order_seq_cst)) \ + { \ + } \ + } while (0) + #define ETL_BUILTIN_UNLOCK \ + do { \ + __atomic_clear(&flag, etl::memory_order_seq_cst); \ + } while (0) //*************************************************************************** - // Atomic type for pre C++11 GCC compilers that support the builtin '__atomic' functions. - // Only integral and pointer types are supported. + // Atomic type for pre C++11 GCC compilers that support the builtin '__atomic' + // functions. Only integral and pointer types are supported. //*************************************************************************** typedef enum memory_order @@ -121,14 +129,14 @@ namespace etl } // Assignment - T operator =(T v) + T operator=(T v) { store(v); return v; } - T operator =(T v) volatile + T operator=(T v) volatile { store(v); @@ -136,106 +144,106 @@ namespace etl } // Pre-increment - T operator ++() + T operator++() { return __atomic_add_fetch(&value, 1, etl::memory_order_seq_cst); } - T operator ++() volatile + T operator++() volatile { return __atomic_add_fetch(&value, 1, etl::memory_order_seq_cst); } // Post-increment - T operator ++(int) + T operator++(int) { return __atomic_fetch_add(&value, 1, etl::memory_order_seq_cst); } - T operator ++(int) volatile + T operator++(int) volatile { return __atomic_fetch_add(&value, 1, etl::memory_order_seq_cst); } // Pre-decrement - T operator --() + T operator--() { return __atomic_sub_fetch(&value, 1, etl::memory_order_seq_cst); } - T operator --() volatile + T operator--() volatile { return __atomic_sub_fetch(&value, 1, etl::memory_order_seq_cst); } // Post-decrement - T operator --(int) + T operator--(int) { return __atomic_fetch_sub(&value, 1, etl::memory_order_seq_cst); } - T operator --(int) volatile + T operator--(int) volatile { return __atomic_fetch_sub(&value, 1, etl::memory_order_seq_cst); } // Add - T operator +=(T v) + T operator+=(T v) { return __atomic_fetch_add(&value, v, etl::memory_order_seq_cst); } - T operator +=(T v) volatile + T operator+=(T v) volatile { return __atomic_fetch_add(&value, v, etl::memory_order_seq_cst); } // Subtract - T operator -=(T v) + T operator-=(T v) { return __atomic_fetch_sub(&value, v, etl::memory_order_seq_cst); } - T operator -=(T v) volatile + T operator-=(T v) volatile { return __atomic_fetch_sub(&value, v, etl::memory_order_seq_cst); } // And - T operator &=(T v) + T operator&=(T v) { return __atomic_fetch_and(&value, v, etl::memory_order_seq_cst); } - T operator &=(T v) volatile + T operator&=(T v) volatile { return __atomic_fetch_and(&value, v, etl::memory_order_seq_cst); } // Or - T operator |=(T v) + T operator|=(T v) { return __atomic_fetch_or(&value, v, etl::memory_order_seq_cst); } - T operator |=(T v) volatile + T operator|=(T v) volatile { return __atomic_fetch_or(&value, v, etl::memory_order_seq_cst); } // Exclusive or - T operator ^=(T v) + T operator^=(T v) { return __atomic_fetch_xor(&value, v, etl::memory_order_seq_cst); } - T operator ^=(T v) volatile + T operator^=(T v) volatile { return __atomic_fetch_xor(&value, v, etl::memory_order_seq_cst); } // Conversion operator - operator T () const + operator T() const { return __atomic_fetch_add(&value, 0, etl::memory_order_seq_cst); } @@ -388,8 +396,8 @@ namespace etl private: - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; + atomic& operator=(const atomic&) ETL_DELETE; + atomic& operator=(const atomic&) volatile ETL_DELETE; mutable T value; }; @@ -413,14 +421,14 @@ namespace etl } // Assignment - T* operator =(T* v) + T* operator=(T* v) { store(v); return v; } - T* operator =(T* v) volatile + T* operator=(T* v) volatile { store(v); @@ -428,73 +436,77 @@ namespace etl } // Pre-increment - T* operator ++() + T* operator++() { return reinterpret_cast(__atomic_add_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); } - T* operator ++() volatile + T* operator++() volatile { return reinterpret_cast(__atomic_add_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); } // Post-increment - T* operator ++(int) + T* operator++(int) { return reinterpret_cast(__atomic_fetch_add(&value, sizeof(T), etl::memory_order_seq_cst)); } - T* operator ++(int) volatile + T* operator++(int) volatile { return reinterpret_cast(__atomic_fetch_add(&value, sizeof(T), etl::memory_order_seq_cst)); } // Pre-decrement - T* operator --() + T* operator--() { return reinterpret_cast(__atomic_sub_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); } - T* operator --() volatile + T* operator--() volatile { return reinterpret_cast(__atomic_sub_fetch(&value, sizeof(T), etl::memory_order_seq_cst)); } // Post-decrement - T* operator --(int) + T* operator--(int) { return reinterpret_cast(__atomic_fetch_sub(&value, sizeof(T), etl::memory_order_seq_cst)); } - T* operator --(int) volatile + T* operator--(int) volatile { return reinterpret_cast(__atomic_fetch_sub(&value, sizeof(T), etl::memory_order_seq_cst)); } // Add - T* operator +=(ptrdiff_t v) + T* operator+=(ptrdiff_t v) { - return reinterpret_cast(__atomic_fetch_add(&value, v * sizeof(T), etl::memory_order_seq_cst)); + return reinterpret_cast( + __atomic_fetch_add(&value, static_cast(v * static_cast(sizeof(T))), etl::memory_order_seq_cst)); } - T* operator +=(ptrdiff_t v) volatile + T* operator+=(ptrdiff_t v) volatile { - return reinterpret_cast(__atomic_fetch_add(&value, v * sizeof(T), etl::memory_order_seq_cst)); + return reinterpret_cast( + __atomic_fetch_add(&value, static_cast(v * static_cast(sizeof(T))), etl::memory_order_seq_cst)); } // Subtract - T* operator -=(ptrdiff_t v) + T* operator-=(ptrdiff_t v) { - return reinterpret_cast(__atomic_fetch_sub(&value, v * sizeof(T), etl::memory_order_seq_cst)); + return reinterpret_cast( + __atomic_fetch_sub(&value, static_cast(v * static_cast(sizeof(T))), etl::memory_order_seq_cst)); } - T* operator -=(ptrdiff_t v) volatile + T* operator-=(ptrdiff_t v) volatile { - return reinterpret_cast(__atomic_fetch_sub(&value, v * sizeof(T), etl::memory_order_seq_cst)); + return reinterpret_cast( + __atomic_fetch_sub(&value, static_cast(v * static_cast(sizeof(T))), etl::memory_order_seq_cst)); } // Conversion operator - operator T* () const + operator T*() const { return reinterpret_cast(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst)); } @@ -540,23 +552,23 @@ namespace etl // Fetch add T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) { - return reinterpret_cast(__atomic_fetch_add(&value, v, order)); + return reinterpret_cast(__atomic_fetch_add(&value, static_cast(v * static_cast(sizeof(T))), order)); } T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile { - return reinterpret_cast(__atomic_fetch_add(&value, v, order)); + return reinterpret_cast(__atomic_fetch_add(&value, static_cast(v * static_cast(sizeof(T))), order)); } // Fetch subtract T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) { - return reinterpret_cast(__atomic_fetch_sub(&value, v, order)); + return reinterpret_cast(__atomic_fetch_sub(&value, static_cast(v * static_cast(sizeof(T))), order)); } T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile { - return reinterpret_cast(__atomic_fetch_sub(&value, v, order)); + return reinterpret_cast(__atomic_fetch_sub(&value, static_cast(v * static_cast(sizeof(T))), order)); } // Exchange @@ -630,8 +642,8 @@ namespace etl private: - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; + atomic& operator=(const atomic&) ETL_DELETE; + atomic& operator=(const atomic&) volatile ETL_DELETE; mutable uintptr_t value; }; @@ -655,14 +667,14 @@ namespace etl } // Assignment - bool operator =(bool v) + bool operator=(bool v) { store(v); return v; } - bool operator =(bool v) volatile + bool operator=(bool v) volatile { store(v); @@ -670,7 +682,7 @@ namespace etl } // Conversion operator - operator bool () const + operator bool() const { return static_cast(__atomic_fetch_add(&value, 0, etl::memory_order_seq_cst)); } @@ -728,7 +740,7 @@ namespace etl bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) { char expected_v = char(expected); - char desired_v = char(desired); + char desired_v = char(desired); return __atomic_compare_exchange_n(&value, &expected_v, desired_v, true, order, order); } @@ -736,7 +748,7 @@ namespace etl bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order order = etl::memory_order_seq_cst) volatile { char expected_v = char(expected); - char desired_v = char(desired); + char desired_v = char(desired); return __atomic_compare_exchange_n(&value, &expected_v, desired_v, true, order, order); } @@ -744,7 +756,7 @@ namespace etl bool compare_exchange_weak(bool& expected, bool desired, etl::memory_order success, etl::memory_order failure) { char expected_v = char(expected); - char desired_v = char(desired); + char desired_v = char(desired); return __atomic_compare_exchange_n(&value, &expected_v, desired_v, true, success, failure); } @@ -792,8 +804,8 @@ namespace etl private: - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; + atomic& operator=(const atomic&) ETL_DELETE; + atomic& operator=(const atomic&) volatile ETL_DELETE; mutable char value; }; @@ -807,6 +819,13 @@ namespace etl { public: + ETL_STATIC_ASSERT((etl::is_trivially_copyable::value), "atomic requires that T is trivially copyable"); + ETL_STATIC_ASSERT((etl::is_copy_constructible::value), "atomic requires that T is copy constructible"); + ETL_STATIC_ASSERT((etl::is_copy_assignable::value), "atomic requires that T is copy assignable"); + ETL_STATIC_ASSERT((etl::is_move_constructible::value), "atomic requires that T is move constructible"); + ETL_STATIC_ASSERT((etl::is_move_assignable::value), "atomic requires that T is move assignable"); + ETL_STATIC_ASSERT((etl::is_same::type>::value), "atomic requires that T is not const or volatile"); + atomic() : flag(0) , value(T()) @@ -820,14 +839,7 @@ namespace etl } // Assignment - T operator =(T v) - { - store(v); - - return v; - } - - T operator =(T v) volatile + T operator=(T v) { store(v); @@ -835,16 +847,7 @@ namespace etl } // Conversion operator - operator T () const - { - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - operator T() volatile const + operator T() const { ETL_BUILTIN_LOCK; T result = value; @@ -859,11 +862,6 @@ namespace etl return false; } - bool is_lock_free() const volatile - { - return false; - } - // Store void store(T v, etl::memory_order order = etl::memory_order_seq_cst) { @@ -873,25 +871,6 @@ namespace etl ETL_BUILTIN_UNLOCK; } - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - ETL_BUILTIN_LOCK; - value = v; - ETL_BUILTIN_UNLOCK; - } - - // Load - T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - (void)order; - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - // Load T load(etl::memory_order order = etl::memory_order_seq_cst) const { @@ -909,18 +888,7 @@ namespace etl (void)order; ETL_BUILTIN_LOCK; T result = value; - value = v; - ETL_BUILTIN_UNLOCK; - - return result; - } - - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - ETL_BUILTIN_LOCK; - T result = value; - value = v; + value = v; ETL_BUILTIN_UNLOCK; return result; @@ -935,27 +903,7 @@ namespace etl ETL_BUILTIN_LOCK; if (memcmp(&value, &expected, sizeof(T)) == 0) { - value = desired; - result = true; - } - else - { - result = false; - } - ETL_BUILTIN_UNLOCK; - - return result; - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - bool result; - - (void)order; - ETL_BUILTIN_LOCK; - if (memcmp(&value, &expected, sizeof(T)) == 0) - { - value = desired; + value = desired; result = true; } else @@ -974,13 +922,6 @@ namespace etl return compare_exchange_weak(expected, desired); } - bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - (void)success; - (void)failure; - return compare_exchange_weak(expected, desired); - } - // Compare exchange strong bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) { @@ -988,12 +929,6 @@ namespace etl return compare_exchange_weak(expected, desired); } - bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - (void)order; - return compare_exchange_weak(expected, desired); - } - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) { (void)success; @@ -1001,32 +936,36 @@ namespace etl return compare_exchange_weak(expected, desired); } - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - (void)success; - (void)failure; - return compare_exchange_weak(expected, desired); - } - private: + atomic& operator=(const atomic&) ETL_DELETE; + atomic& operator=(const atomic&) volatile ETL_DELETE; + mutable char flag; - mutable T value; + mutable T value; }; -#undef ETL_BUILTIN_LOCK -#undef ETL_BUILTIN_UNLOCK + #undef ETL_BUILTIN_LOCK + #undef ETL_BUILTIN_UNLOCK #endif #if defined(ETL_USE_SYNC_BUILTINS) -#define ETL_BUILTIN_LOCK do { while (__sync_lock_test_and_set(&flag, 1U)) {} } while(0) -#define ETL_BUILTIN_UNLOCK do { __sync_lock_release(&flag); } while(0) + #define ETL_BUILTIN_LOCK \ + do { \ + while (__sync_lock_test_and_set(&flag, 1U)) \ + { \ + } \ + } while (0) + #define ETL_BUILTIN_UNLOCK \ + do { \ + __sync_lock_release(&flag); \ + } while (0) //*************************************************************************** - // Atomic type for pre C++11 GCC compilers that support the builtin '__sync' functions. - // Only integral and pointer types are supported. + // Atomic type for pre C++11 GCC compilers that support the builtin '__sync' + // functions. Only integral and pointer types are supported. //*************************************************************************** typedef enum memory_order @@ -1069,14 +1008,14 @@ namespace etl } // Assignment - T operator =(T v) + T operator=(T v) { store(v); return v; } - T operator =(T v) volatile + T operator=(T v) volatile { store(v); @@ -1084,106 +1023,106 @@ namespace etl } // Pre-increment - T operator ++() + T operator++() { return __sync_add_and_fetch(&value, 1); } - T operator ++() volatile + T operator++() volatile { return __sync_add_and_fetch(&value, 1); } // Post-increment - T operator ++(int) + T operator++(int) { return __sync_fetch_and_add(&value, 1); } - T operator ++(int) volatile + T operator++(int) volatile { return __sync_fetch_and_add(&value, 1); } // Pre-decrement - T operator --() + T operator--() { return __sync_sub_and_fetch(&value, 1); } - T operator --() volatile + T operator--() volatile { return __sync_sub_and_fetch(&value, 1); } // Post-decrement - T operator --(int) + T operator--(int) { return __sync_fetch_and_sub(&value, 1); } - T operator --(int) volatile + T operator--(int) volatile { return __sync_fetch_and_sub(&value, 1); } // Add - T operator +=(T v) + T operator+=(T v) { return __sync_fetch_and_add(&value, v); } - T operator +=(T v) volatile + T operator+=(T v) volatile { return __sync_fetch_and_add(&value, v); } // Subtract - T operator -=(T v) + T operator-=(T v) { return __sync_fetch_and_sub(&value, v); } - T operator -=(T v) volatile + T operator-=(T v) volatile { return __sync_fetch_and_sub(&value, v); } // And - T operator &=(T v) + T operator&=(T v) { return __sync_fetch_and_and(&value, v); } - T operator &=(T v) volatile + T operator&=(T v) volatile { return __sync_fetch_and_and(&value, v); } // Or - T operator |=(T v) + T operator|=(T v) { return __sync_fetch_and_or(&value, v); } - T operator |=(T v) volatile + T operator|=(T v) volatile { return __sync_fetch_and_or(&value, v); } // Exclusive or - T operator ^=(T v) + T operator^=(T v) { return __sync_fetch_and_xor(&value, v); } - T operator ^=(T v) volatile + T operator^=(T v) volatile { return __sync_fetch_and_xor(&value, v); } // Conversion operator - operator T () const + operator T() const { return __sync_fetch_and_add(&value, 0); } @@ -1448,8 +1387,8 @@ namespace etl private: - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; + atomic& operator=(const atomic&) ETL_DELETE; + atomic& operator=(const atomic&) volatile ETL_DELETE; mutable volatile T value; }; @@ -1473,14 +1412,14 @@ namespace etl } // Assignment - T* operator =(T* v) + T* operator=(T* v) { store(v); return v; } - T* operator =(T* v) volatile + T* operator=(T* v) volatile { store(v); @@ -1488,78 +1427,78 @@ namespace etl } // Pre-increment - T* operator ++() + T* operator++() { return reinterpret_cast(__sync_add_and_fetch(&value, sizeof(T))); } - T* operator ++() volatile + T* operator++() volatile { return reinterpret_cast(__sync_add_and_fetch(&value, sizeof(T))); } // Post-increment - T* operator ++(int) + T* operator++(int) { return reinterpret_cast(__sync_fetch_and_add(&value, sizeof(T))); } - T* operator ++(int) volatile + T* operator++(int) volatile { return reinterpret_cast(__sync_fetch_and_add(&value, sizeof(T))); } // Pre-decrement - T* operator --() + T* operator--() { return reinterpret_cast(__sync_sub_and_fetch(&value, sizeof(T))); } - T* operator --() volatile + T* operator--() volatile { return reinterpret_cast(__sync_sub_and_fetch(&value, sizeof(T))); } // Post-decrement - T* operator --(int) + T* operator--(int) { return reinterpret_cast(__sync_fetch_and_sub(&value, sizeof(T))); } - T* operator --(int) volatile + T* operator--(int) volatile { return reinterpret_cast(__sync_fetch_and_sub(&value, sizeof(T))); } // Add - T* operator +=(ptrdiff_t v) + T* operator+=(ptrdiff_t v) { return reinterpret_cast(__sync_fetch_and_add(&value, v * sizeof(T))); } - T* operator +=(ptrdiff_t v) volatile + T* operator+=(ptrdiff_t v) volatile { return reinterpret_cast(__sync_fetch_and_add(&value, v * sizeof(T))); } // Subtract - T* operator -=(ptrdiff_t v) + T* operator-=(ptrdiff_t v) { return reinterpret_cast(__sync_fetch_and_sub(&value, v * sizeof(T))); } - T* operator -=(ptrdiff_t v) volatile + T* operator-=(ptrdiff_t v) volatile { return reinterpret_cast(__sync_fetch_and_sub(&value, v * sizeof(T))); } // Conversion operator - operator T* () const + operator T*() const { return reinterpret_cast(__sync_fetch_and_add(&value, 0)); } - operator T* () volatile const + operator T*() volatile const { return reinterpret_cast(__sync_fetch_and_add(&value, 0)); } @@ -1758,8 +1697,8 @@ namespace etl private: - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; + atomic& operator=(const atomic&) ETL_DELETE; + atomic& operator=(const atomic&) volatile ETL_DELETE; mutable uintptr_t value; }; @@ -1783,14 +1722,14 @@ namespace etl } // Assignment - bool operator =(bool v) + bool operator=(bool v) { store(v); return v; } - bool operator =(bool v) volatile + bool operator=(bool v) volatile { store(v); @@ -1980,8 +1919,8 @@ namespace etl private: - atomic& operator =(const atomic&) ETL_DELETE; - atomic& operator =(const atomic&) volatile ETL_DELETE; + atomic& operator=(const atomic&) ETL_DELETE; + atomic& operator=(const atomic&) volatile ETL_DELETE; mutable char value; }; @@ -1995,6 +1934,13 @@ namespace etl { public: + ETL_STATIC_ASSERT((etl::is_trivially_copyable::value), "atomic requires that T is trivially copyable"); + ETL_STATIC_ASSERT((etl::is_copy_constructible::value), "atomic requires that T is copy constructible"); + ETL_STATIC_ASSERT((etl::is_copy_assignable::value), "atomic requires that T is copy assignable"); + ETL_STATIC_ASSERT((etl::is_move_constructible::value), "atomic requires that T is move constructible"); + ETL_STATIC_ASSERT((etl::is_move_assignable::value), "atomic requires that T is move assignable"); + ETL_STATIC_ASSERT((etl::is_same::type>::value), "atomic requires that T is not const or volatile"); + atomic() : flag(0) , value(T()) @@ -2008,14 +1954,7 @@ namespace etl } // Assignment - T operator =(T v) - { - store(v); - - return v; - } - - T operator =(T v) volatile + T operator=(T v) { store(v); @@ -2023,16 +1962,7 @@ namespace etl } // Conversion operator - operator T () const - { - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - - operator T() volatile const + operator T() const { ETL_BUILTIN_LOCK; T result = value; @@ -2047,11 +1977,6 @@ namespace etl return false; } - bool is_lock_free() const volatile - { - return false; - } - // Store void store(T v, etl::memory_order order = etl::memory_order_seq_cst) { @@ -2060,23 +1985,6 @@ namespace etl ETL_BUILTIN_UNLOCK; } - void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - ETL_BUILTIN_LOCK; - value = v; - ETL_BUILTIN_UNLOCK; - } - - // Load - T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile - { - ETL_BUILTIN_LOCK; - T result = value; - ETL_BUILTIN_UNLOCK; - - return result; - } - // Load T load(etl::memory_order order = etl::memory_order_seq_cst) const { @@ -2092,17 +2000,7 @@ namespace etl { ETL_BUILTIN_LOCK; T result = value; - value = v; - ETL_BUILTIN_UNLOCK; - - return result; - } - - T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - ETL_BUILTIN_LOCK; - T result = value; - value = v; + value = v; ETL_BUILTIN_UNLOCK; return result; @@ -2116,26 +2014,7 @@ namespace etl ETL_BUILTIN_LOCK; if (memcmp(&value, &expected, sizeof(T)) == 0) { - value = desired; - result = true; - } - else - { - result = false; - } - ETL_BUILTIN_UNLOCK; - - return result; - } - - bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - bool result; - - ETL_BUILTIN_LOCK; - if (memcmp(&value, &expected, sizeof(T)) == 0) - { - value = desired; + value = desired; result = true; } else @@ -2152,104 +2031,91 @@ namespace etl return compare_exchange_weak(expected, desired); } - bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - return compare_exchange_weak(expected, desired); - } - // Compare exchange strong bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) { return compare_exchange_weak(expected, desired); } - bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile - { - return compare_exchange_weak(expected, desired); - } - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) { return compare_exchange_weak(expected, desired); } - bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile - { - return compare_exchange_weak(expected, desired); - } - private: + atomic& operator=(const atomic&) ETL_DELETE; + atomic& operator=(const atomic&) volatile ETL_DELETE; + mutable char flag; - mutable T value; + mutable T value; }; -#undef ETL_SYNC_BUILTIN_LOCK -#undef ETL_SYNC_BUILTIN_UNLOCK + #undef ETL_SYNC_BUILTIN_LOCK + #undef ETL_SYNC_BUILTIN_UNLOCK #endif - typedef etl::atomic atomic_bool; - typedef etl::atomic atomic_char; - typedef etl::atomic atomic_schar; - typedef etl::atomic atomic_uchar; - typedef etl::atomic atomic_short; - typedef etl::atomic atomic_ushort; - typedef etl::atomic atomic_int; - typedef etl::atomic atomic_uint; - typedef etl::atomic atomic_long; - typedef etl::atomic atomic_ulong; - typedef etl::atomic atomic_llong; - typedef etl::atomic atomic_ullong; - typedef etl::atomic atomic_wchar_t; + typedef etl::atomic atomic_bool; + typedef etl::atomic atomic_char; + typedef etl::atomic atomic_schar; + typedef etl::atomic atomic_uchar; + typedef etl::atomic atomic_short; + typedef etl::atomic atomic_ushort; + typedef etl::atomic atomic_int; + typedef etl::atomic atomic_uint; + typedef etl::atomic atomic_long; + typedef etl::atomic atomic_ulong; + typedef etl::atomic atomic_llong; + typedef etl::atomic atomic_ullong; + typedef etl::atomic atomic_wchar_t; #if ETL_HAS_NATIVE_CHAR8_T - typedef etl::atomic atomic_char8_t; + typedef etl::atomic atomic_char8_t; #endif #if ETL_HAS_NATIVE_CHAR16_T - typedef etl::atomic atomic_char16_t; + typedef etl::atomic atomic_char16_t; #endif #if ETL_HAS_NATIVE_CHAR32_T - typedef etl::atomic atomic_char32_t; + typedef etl::atomic atomic_char32_t; #endif #if ETL_USING_8BIT_TYPES - typedef etl::atomic atomic_uint8_t; - typedef etl::atomic atomic_int8_t; + typedef etl::atomic atomic_uint8_t; + typedef etl::atomic atomic_int8_t; #endif - typedef etl::atomic atomic_uint16_t; - typedef etl::atomic atomic_int16_t; - typedef etl::atomic atomic_uint32_t; - typedef etl::atomic atomic_int32_t; + typedef etl::atomic atomic_uint16_t; + typedef etl::atomic atomic_int16_t; + typedef etl::atomic atomic_uint32_t; + typedef etl::atomic atomic_int32_t; #if ETL_USING_64BIT_TYPES - typedef etl::atomic atomic_uint64_t; - typedef etl::atomic atomic_int64_t; + typedef etl::atomic atomic_uint64_t; + typedef etl::atomic atomic_int64_t; #endif - typedef etl::atomic atomic_int_least8_t; - typedef etl::atomic atomic_uint_least8_t; - typedef etl::atomic atomic_int_least16_t; - typedef etl::atomic atomic_uint_least16_t; - typedef etl::atomic atomic_int_least32_t; - typedef etl::atomic atomic_uint_least32_t; + typedef etl::atomic atomic_int_least8_t; + typedef etl::atomic atomic_uint_least8_t; + typedef etl::atomic atomic_int_least16_t; + typedef etl::atomic atomic_uint_least16_t; + typedef etl::atomic atomic_int_least32_t; + typedef etl::atomic atomic_uint_least32_t; #if ETL_USING_64BIT_TYPES - typedef etl::atomic atomic_int_least64_t; - typedef etl::atomic atomic_uint_least64_t; + typedef etl::atomic atomic_int_least64_t; + typedef etl::atomic atomic_uint_least64_t; #endif - typedef etl::atomic atomic_int_fast8_t; - typedef etl::atomic atomic_uint_fast8_t; - typedef etl::atomic atomic_int_fast16_t; - typedef etl::atomic atomic_uint_fast16_t; - typedef etl::atomic atomic_int_fast32_t; - typedef etl::atomic atomic_uint_fast32_t; + typedef etl::atomic atomic_int_fast8_t; + typedef etl::atomic atomic_uint_fast8_t; + typedef etl::atomic atomic_int_fast16_t; + typedef etl::atomic atomic_uint_fast16_t; + typedef etl::atomic atomic_int_fast32_t; + typedef etl::atomic atomic_uint_fast32_t; #if ETL_USING_64BIT_TYPES - typedef etl::atomic atomic_int_fast64_t; - typedef etl::atomic atomic_uint_fast64_t; + typedef etl::atomic atomic_int_fast64_t; + typedef etl::atomic atomic_uint_fast64_t; #endif - typedef etl::atomic atomic_intptr_t; - typedef etl::atomic atomic_uintptr_t; - typedef etl::atomic atomic_size_t; - typedef etl::atomic atomic_ptrdiff_t; - typedef etl::atomic atomic_intmax_t; - typedef etl::atomic atomic_uintmax_t; -} + typedef etl::atomic atomic_intptr_t; + typedef etl::atomic atomic_uintptr_t; + typedef etl::atomic atomic_size_t; + typedef etl::atomic atomic_ptrdiff_t; + typedef etl::atomic atomic_intmax_t; + typedef etl::atomic atomic_uintmax_t; +} // namespace etl #endif - diff --git a/include/etl/atomic/atomic_std.h b/include/etl/atomic/atomic_std.h index bea19d50..ee765a70 100644 --- a/include/etl/atomic/atomic_std.h +++ b/include/etl/atomic/atomic_std.h @@ -30,8 +30,8 @@ SOFTWARE. #define ETL_ATOMIC_STD_INCLUDED #include "../platform.h" -#include "../nullptr.h" #include "../char_traits.h" +#include "../nullptr.h" #include #include @@ -55,39 +55,39 @@ namespace etl static ETL_CONSTANT etl::memory_order memory_order_acq_rel = std::memory_order_acq_rel; static ETL_CONSTANT etl::memory_order memory_order_seq_cst = std::memory_order_seq_cst; - using atomic_bool = std::atomic; - using atomic_char = std::atomic; - using atomic_schar = std::atomic; - using atomic_uchar = std::atomic; - using atomic_short = std::atomic; - using atomic_ushort = std::atomic; - using atomic_int = std::atomic; - using atomic_uint = std::atomic; - using atomic_long = std::atomic; - using atomic_ulong = std::atomic; - using atomic_llong = std::atomic; - using atomic_ullong = std::atomic; - using atomic_wchar_t = std::atomic; + using atomic_bool = std::atomic; + using atomic_char = std::atomic; + using atomic_schar = std::atomic; + using atomic_uchar = std::atomic; + using atomic_short = std::atomic; + using atomic_ushort = std::atomic; + using atomic_int = std::atomic; + using atomic_uint = std::atomic; + using atomic_long = std::atomic; + using atomic_ulong = std::atomic; + using atomic_llong = std::atomic; + using atomic_ullong = std::atomic; + using atomic_wchar_t = std::atomic; #if ETL_HAS_NATIVE_CHAR8_T using atomic_char8_t = std::atomic; #endif #if ETL_HAS_NATIVE_CHAR16_T - using atomic_char16_t = std::atomic; + using atomic_char16_t = std::atomic; #endif #if ETL_HAS_NATIVE_CHAR32_T - using atomic_char32_t = std::atomic; + using atomic_char32_t = std::atomic; #endif #if ETL_USING_8BIT_TYPES - using atomic_uint8_t = std::atomic; - using atomic_int8_t = std::atomic; + using atomic_uint8_t = std::atomic; + using atomic_int8_t = std::atomic; #endif - using atomic_uint16_t = std::atomic; - using atomic_int16_t = std::atomic; - using atomic_uint32_t = std::atomic; - using atomic_int32_t = std::atomic; + using atomic_uint16_t = std::atomic; + using atomic_int16_t = std::atomic; + using atomic_uint32_t = std::atomic; + using atomic_int32_t = std::atomic; #if ETL_USING_64BIT_TYPES - using atomic_uint64_t = std::atomic; - using atomic_int64_t = std::atomic; + using atomic_uint64_t = std::atomic; + using atomic_int64_t = std::atomic; #endif using atomic_int_least8_t = std::atomic; using atomic_uint_least8_t = std::atomic; @@ -99,22 +99,22 @@ namespace etl using atomic_int_least64_t = std::atomic; using atomic_uint_least64_t = std::atomic; #endif - using atomic_int_fast8_t = std::atomic; - using atomic_uint_fast8_t = std::atomic; - using atomic_int_fast16_t = std::atomic; - using atomic_uint_fast16_t = std::atomic; - using atomic_int_fast32_t = std::atomic; - using atomic_uint_fast32_t = std::atomic; + using atomic_int_fast8_t = std::atomic; + using atomic_uint_fast8_t = std::atomic; + using atomic_int_fast16_t = std::atomic; + using atomic_uint_fast16_t = std::atomic; + using atomic_int_fast32_t = std::atomic; + using atomic_uint_fast32_t = std::atomic; #if ETL_USING_64BIT_TYPES - using atomic_int_fast64_t = std::atomic; - using atomic_uint_fast64_t = std::atomic; + using atomic_int_fast64_t = std::atomic; + using atomic_uint_fast64_t = std::atomic; #endif - using atomic_intptr_t = std::atomic; - using atomic_uintptr_t = std::atomic; - using atomic_size_t = std::atomic; - using atomic_ptrdiff_t = std::atomic; - using atomic_intmax_t = std::atomic; - using atomic_uintmax_t = std::atomic; -} + using atomic_intptr_t = std::atomic; + using atomic_uintptr_t = std::atomic; + using atomic_size_t = std::atomic; + using atomic_ptrdiff_t = std::atomic; + using atomic_intmax_t = std::atomic; + using atomic_uintmax_t = std::atomic; +} // namespace etl #endif diff --git a/include/etl/base64.h b/include/etl/base64.h index 4034248d..4ce98b3c 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -27,27 +27,29 @@ SOFTWARE. #define ETL_BASE64_INCLUDED #include "platform.h" -#include "static_assert.h" -#include "exception.h" -#include "error_handler.h" -#include "type_traits.h" #include "enum_type.h" +#include "error_handler.h" +#include "exception.h" #include "integral_limits.h" +#include "static_assert.h" +#include "type_traits.h" #include /************************************************************************************************************************************************************************** -* See https://en.wikipedia.org/wiki/Base64 -* -* Encoding Encoding characters Separate encoding of lines Decoding non-encoding characters -* 62nd 63rd Pad Separators Length Checksum -* RFC 1421 : Base64 for Privacy - Enhanced Mail(deprecated) + / = mandatory CR + LF 64, or lower for the last line No No -* RFC 2045 : Base64 transfer encoding for MIME + / = mandatory CR + LF At most 76 No Discarded -* RFC 2152 : Base64 for UTF - 7 + / No No No -* RFC 3501 : Base64 encoding for IMAP mailbox names + , No No No -* RFC 4648 : base64(standard)[a] + / = optional No No -* RFC 4648 : base64url(URL - and filename - safe standard) - _ = optional No No -**************************************************************************************************************************************************************************/ + * See https://en.wikipedia.org/wiki/Base64 + * + * Encoding Encoding characters + *Separate encoding of lines Decoding non-encoding characters 62nd 63rd Pad + *Separators Length Checksum RFC 1421 : Base64 for + *Privacy - Enhanced Mail(deprecated) + / = mandatory CR + LF 64, + *or lower for the last line No No RFC 2045 : Base64 transfer encoding for MIME + *+ / = mandatory CR + LF At most 76 No Discarded RFC 2152 : Base64 + *for UTF - 7 + / No No No RFC + *3501 : Base64 encoding for IMAP mailbox names + , No + *No No RFC 4648 : base64(standard)[a] + / = optional No No RFC 4648 : + *base64url(URL - and filename - safe standard) - _ = optional No No + **************************************************************************************************************************************************************************/ namespace etl { @@ -114,8 +116,8 @@ namespace etl { enum enum_type { - //RFC_1421, // Not implemented - //RFC_2045, // Not implemented + // RFC_1421, // Not implemented + // RFC_2045, // Not implemented RFC_2152, RFC_3501, RFC_4648, @@ -125,8 +127,8 @@ namespace etl }; ETL_DECLARE_ENUM_TYPE(Encoding, int) - //ETL_ENUM_TYPE(RFC_1421, "RFC_1421") // Not implemented - //ETL_ENUM_TYPE(RFC_2045, "RFC_2045") // Not implemented + // ETL_ENUM_TYPE(RFC_1421, "RFC_1421") // Not implemented + // ETL_ENUM_TYPE(RFC_2045, "RFC_2045") // Not implemented ETL_ENUM_TYPE(RFC_2152, "RFC_2152") ETL_ENUM_TYPE(RFC_3501, "RFC_3501") ETL_ENUM_TYPE(RFC_4648, "RFC_4648") @@ -166,16 +168,14 @@ namespace etl enum { - Invalid_Data = etl::integral_limits::max, + Invalid_Data = etl::integral_limits::max, Min_Encode_Buffer_Size = 4, Min_Decode_Buffer_Size = 3 }; protected: - ETL_CONSTEXPR14 - base64(const char* encoder_table_, - bool use_padding_) + ETL_CONSTEXPR14 base64(const char* encoder_table_, bool use_padding_) : encoder_table(encoder_table_) , use_padding(use_padding_) { @@ -184,9 +184,7 @@ namespace etl //************************************************************************* // Character set for RFC-1421, RFC-2045, RFC-2152 and RFC-4648 //************************************************************************* - static - ETL_CONSTEXPR14 - const char* character_set_1() + static ETL_CONSTEXPR14 const char* character_set_1() { return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; } @@ -194,9 +192,7 @@ namespace etl //************************************************************************* // Character set for RFC-4648-URL //************************************************************************* - static - ETL_CONSTEXPR14 - const char* character_set_2() + static ETL_CONSTEXPR14 const char* character_set_2() { return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; } @@ -204,9 +200,7 @@ namespace etl //************************************************************************* // Character set for RFC-3501-URL //************************************************************************* - static - ETL_CONSTEXPR14 - const char* character_set_3() + static ETL_CONSTEXPR14 const char* character_set_3() { return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; } @@ -214,5 +208,5 @@ namespace etl const char* encoder_table; const bool use_padding; }; -} +} // namespace etl #endif diff --git a/include/etl/base64_decoder.h b/include/etl/base64_decoder.h index 848c7e35..8e55d9dc 100644 --- a/include/etl/base64_decoder.h +++ b/include/etl/base64_decoder.h @@ -1,5 +1,5 @@ //************************************************************************* -///Decode from Base64 from and to pointer/length +/// Decode from Base64 from and to pointer/length //*************************************************************************///\file /****************************************************************************** @@ -29,16 +29,16 @@ SOFTWARE. #define ETL_BASE64_DECODER_INCLUDED #include "platform.h" -#include "static_assert.h" -#include "error_handler.h" -#include "type_traits.h" -#include "binary.h" #include "algorithm.h" +#include "binary.h" +#include "delegate.h" +#include "enum_type.h" +#include "error_handler.h" #include "integral_limits.h" #include "iterator.h" -#include "enum_type.h" -#include "delegate.h" #include "span.h" +#include "static_assert.h" +#include "type_traits.h" #include "base64.h" @@ -48,11 +48,12 @@ SOFTWARE. #include #endif -#define ETL_IS_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value && \ - (etl::integral_limits::type>::bits == 8U)) +#define ETL_IS_8_BIT_INTEGRAL(Type) \ + (etl::is_integral::type>::value && (etl::integral_limits::type>::bits == 8U)) -#define ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value_type>::value && \ - (etl::integral_limits::type>::value_type>::bits == 8U)) +#define ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(Type) \ + (etl::is_integral< typename etl::iterator_traits< typename etl::remove_cv::type>::value_type>::value \ + && (etl::integral_limits< typename etl::iterator_traits< typename etl::remove_cv::type>::value_type>::bits == 8U)) namespace etl { @@ -70,8 +71,7 @@ namespace etl /// Decode to Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool decode(T value) + ETL_CONSTEXPR14 bool decode(T value) { ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(T), "Input type must be an 8 bit integral"); @@ -101,8 +101,7 @@ namespace etl /// Decode from Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool decode(TInputIterator input_begin, TInputIterator input_end) + ETL_CONSTEXPR14 bool decode(TInputIterator input_begin, TInputIterator input_end) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -121,8 +120,7 @@ namespace etl /// Decode from Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool decode(TInputIterator input_begin, size_t input_length) + ETL_CONSTEXPR14 bool decode(TInputIterator input_begin, size_t input_length) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -141,8 +139,7 @@ namespace etl /// Decode from Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool decode_final(TInputIterator input_begin, TInputIterator input_end) + ETL_CONSTEXPR14 bool decode_final(TInputIterator input_begin, TInputIterator input_end) { return decode(input_begin, input_end) && flush(); } @@ -151,8 +148,7 @@ namespace etl /// Decode from Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool decode_final(TInputIterator input_begin, size_t input_length) + ETL_CONSTEXPR14 bool decode_final(TInputIterator input_begin, size_t input_length) { return decode(input_begin, input_length) && flush(); } @@ -160,8 +156,7 @@ namespace etl //************************************************************************* /// Flush any remaining data to the output. //************************************************************************* - ETL_CONSTEXPR14 - bool flush() + ETL_CONSTEXPR14 bool flush() { // Encode any remaining input data. bool success = decode_block(); @@ -193,32 +188,28 @@ namespace etl //************************************************************************* /// Reset the encoder. //************************************************************************* - ETL_CONSTEXPR14 - void restart() + ETL_CONSTEXPR14 void restart() { reset_input_buffer(); reset_output_buffer(); - overflow_detected = false; + overflow_detected = false; invalid_data_detected = false; - padding_received = false; + padding_received = false; } //************************************************************************* /// Returns the beginning of the output buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const unsigned char* begin() const + ETL_NODISCARD ETL_CONSTEXPR14 const unsigned char* begin() const { return p_output_buffer; } //************************************************************************* - /// This only returns a useful value if a callback has not been set or called. + /// This only returns a useful value if a callback has not been set or + /// called. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const unsigned char* end() const + ETL_NODISCARD ETL_CONSTEXPR14 const unsigned char* end() const { return p_output_buffer + output_buffer_length; } @@ -226,30 +217,26 @@ namespace etl //************************************************************************* /// Returns the beginning of the output buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const unsigned char* cbegin() const + ETL_NODISCARD ETL_CONSTEXPR14 const unsigned char* cbegin() const { return p_output_buffer; } //************************************************************************* - /// This only returns a useful value if a callback has not been set or called. + /// This only returns a useful value if a callback has not been set or + /// called. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const unsigned char* cend() const + ETL_NODISCARD ETL_CONSTEXPR14 const unsigned char* cend() const { return p_output_buffer + output_buffer_length; } //************************************************************************* /// Returns the size of the output buffer. - /// This only returns a useful value if a callback has not been set or called. + /// This only returns a useful value if a callback has not been set or + /// called. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - size_t size() const + ETL_NODISCARD ETL_CONSTEXPR14 size_t size() const { return output_buffer_length; } @@ -257,20 +244,17 @@ namespace etl //************************************************************************* /// Returns the maximum size of the output buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - size_t buffer_size() const + ETL_NODISCARD ETL_CONSTEXPR14 size_t buffer_size() const { return output_buffer_max_size; } //************************************************************************* /// Get a span of the output data. - /// This only returns a useful span if a callback has not been set or called. + /// This only returns a useful span if a callback has not been set or + /// called. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - span_type span() const + ETL_NODISCARD ETL_CONSTEXPR14 span_type span() const { return span_type(begin(), end()); } @@ -278,9 +262,7 @@ namespace etl //************************************************************************* /// Returns true if the output buffer has overflowed //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - bool overflow() const + ETL_NODISCARD ETL_CONSTEXPR14 bool overflow() const { return overflow_detected; } @@ -288,9 +270,7 @@ namespace etl //************************************************************************* /// Returns true if an invalid character was detected. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - bool invalid_data() const + ETL_NODISCARD ETL_CONSTEXPR14 bool invalid_data() const { return invalid_data_detected; } @@ -298,9 +278,7 @@ namespace etl //************************************************************************* /// Returns true if an error was detected. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - bool error() const + ETL_NODISCARD ETL_CONSTEXPR14 bool error() const { return overflow() || invalid_data(); } @@ -310,12 +288,8 @@ namespace etl //************************************************************************* /// Constructor //************************************************************************* - ETL_CONSTEXPR14 - ibase64_decoder(const char* encoder_table_, - bool use_padding_, - unsigned char* p_output_buffer_, - size_t ouput_buffer_max_size_, - callback_type callback_) + ETL_CONSTEXPR14 ibase64_decoder(const char* encoder_table_, bool use_padding_, unsigned char* p_output_buffer_, size_t ouput_buffer_max_size_, + callback_type callback_) : base64(encoder_table_, use_padding_) , input_buffer() , input_buffer_length(0) @@ -333,9 +307,7 @@ namespace etl /// Calculates the minimum buffer size required to decode from Base64 //************************************************************************* ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t decoded_size_from_valid_input_length(size_t input_length) + static ETL_CONSTEXPR14 size_t decoded_size_from_valid_input_length(size_t input_length) { return input_length - (input_length / 4U); } @@ -343,14 +315,13 @@ namespace etl private: //************************************************************************* - // Translates a sextet into an index + // Translates a sextet into an index //************************************************************************* template - ETL_CONSTEXPR14 - uint32_t get_index_from_sextet(T sextet) + ETL_CONSTEXPR14 uint32_t get_index_from_sextet(T sextet) { const char* encoder_table_end = encoder_table + 64; - const char* p_sextet = etl::find(encoder_table, encoder_table_end, static_cast(sextet)); + const char* p_sextet = etl::find(encoder_table, encoder_table_end, static_cast(sextet)); if (p_sextet != encoder_table_end) { @@ -369,8 +340,7 @@ namespace etl template ETL_NODISCARD static - ETL_CONSTEXPR14 - T padding() + ETL_CONSTEXPR14 T padding() { return static_cast('='); } @@ -378,51 +348,50 @@ namespace etl //************************************************************************* /// Decode one block of data. //************************************************************************* - ETL_CONSTEXPR14 - bool decode_block() + ETL_CONSTEXPR14 bool decode_block() { switch (input_buffer_length) { // Only triggered on call to flush(). case 2: - { - uint32_t sextets = (get_index_from_sextet(input_buffer[0]) << 6); - sextets = sextets | (get_index_from_sextet(input_buffer[1])); - push_to_output_buffer((sextets >> 4) & 0xFF); - break; - } + { + uint32_t sextets = (get_index_from_sextet(input_buffer[0]) << 6); + sextets = sextets | (get_index_from_sextet(input_buffer[1])); + push_to_output_buffer((sextets >> 4) & 0xFF); + break; + } // Only triggered on call to flush(). case 3: - { - uint32_t sextets = (get_index_from_sextet(input_buffer[0]) << 12); - sextets = sextets | (get_index_from_sextet(input_buffer[1]) << 6); - sextets = sextets | (get_index_from_sextet(input_buffer[2])); - push_to_output_buffer((sextets >> 10) & 0xFF); - push_to_output_buffer((sextets >> 2) & 0xFF); - break; - } + { + uint32_t sextets = (get_index_from_sextet(input_buffer[0]) << 12); + sextets = sextets | (get_index_from_sextet(input_buffer[1]) << 6); + sextets = sextets | (get_index_from_sextet(input_buffer[2])); + push_to_output_buffer((sextets >> 10) & 0xFF); + push_to_output_buffer((sextets >> 2) & 0xFF); + break; + } // Only triggered on call to decode(). case 4: - { - // Read in four sextets - uint32_t sextets = (get_index_from_sextet(input_buffer[0]) << 18); - sextets = sextets | (get_index_from_sextet(input_buffer[1]) << 12); - sextets = sextets | (get_index_from_sextet(input_buffer[2]) << 6); - sextets = sextets | (get_index_from_sextet(input_buffer[3])); + { + // Read in four sextets + uint32_t sextets = (get_index_from_sextet(input_buffer[0]) << 18); + sextets = sextets | (get_index_from_sextet(input_buffer[1]) << 12); + sextets = sextets | (get_index_from_sextet(input_buffer[2]) << 6); + sextets = sextets | (get_index_from_sextet(input_buffer[3])); - // Write out three octets - push_to_output_buffer((sextets >> 16) & 0xFF); - push_to_output_buffer((sextets >> 8) & 0xFF); - push_to_output_buffer((sextets >> 0) & 0xFF); - break; - } + // Write out three octets + push_to_output_buffer((sextets >> 16) & 0xFF); + push_to_output_buffer((sextets >> 8) & 0xFF); + push_to_output_buffer((sextets >> 0) & 0xFF); + break; + } default: - { - break; - } + { + break; + } } ETL_ASSERT(!invalid_data_detected, ETL_ERROR(etl::base64_invalid_data)); @@ -434,8 +403,7 @@ namespace etl //************************************************************************* // Push to the output buffer. //************************************************************************* - ETL_CONSTEXPR14 - void push_to_output_buffer(unsigned char c) + ETL_CONSTEXPR14 void push_to_output_buffer(unsigned char c) { if (output_buffer_length < output_buffer_max_size) { @@ -448,28 +416,25 @@ namespace etl } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - bool output_buffer_is_full() const + ETL_CONSTEXPR14 bool output_buffer_is_full() const { return output_buffer_length == output_buffer_max_size; } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - bool output_buffer_is_empty() const + ETL_CONSTEXPR14 bool output_buffer_is_empty() const { return output_buffer_length == 0; } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - void reset_output_buffer() + ETL_CONSTEXPR14 void reset_output_buffer() { output_buffer_length = 0; } @@ -478,8 +443,7 @@ namespace etl // Push to the input buffer. //************************************************************************* template - ETL_CONSTEXPR14 - void push_to_input_buffer(T value) + ETL_CONSTEXPR14 void push_to_input_buffer(T value) { if (value == padding()) { @@ -494,25 +458,23 @@ namespace etl } else { - input_buffer[input_buffer_length++] = static_cast(value); + input_buffer[input_buffer_length++] = static_cast(value); } } } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - bool input_buffer_is_full() const + ETL_CONSTEXPR14 bool input_buffer_is_full() const { return input_buffer_length == 4U; } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - void reset_input_buffer() + ETL_CONSTEXPR14 void reset_input_buffer() { input_buffer_length = 0; } @@ -544,13 +506,8 @@ namespace etl //************************************************************************* /// Base64 RFC-2152 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc2152_decoder() - : ibase64_decoder(etl::base64::character_set_1(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc2152_decoder() + : ibase64_decoder(etl::base64::character_set_1(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -558,13 +515,8 @@ namespace etl //************************************************************************* /// Base64 RFC-2152 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc2152_decoder(callback_type callback_) - : ibase64_decoder(etl::base64::character_set_1(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc2152_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_1(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -574,8 +526,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_decoder::decoded_size_from_valid_input_length(input_length); } @@ -599,13 +550,8 @@ namespace etl //************************************************************************* /// Base64 RFC-3501 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc3501_decoder() - : ibase64_decoder(etl::base64::character_set_3(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc3501_decoder() + : ibase64_decoder(etl::base64::character_set_3(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -613,13 +559,8 @@ namespace etl //************************************************************************* /// Base64 RFC-3501 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc3501_decoder(callback_type callback_) - : ibase64_decoder(etl::base64::character_set_3(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc3501_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_3(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -629,8 +570,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_decoder::decoded_size_from_valid_input_length(input_length); } @@ -654,13 +594,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_decoder() - : ibase64_decoder(etl::base64::character_set_1(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc4648_decoder() + : ibase64_decoder(etl::base64::character_set_1(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -668,13 +603,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_decoder(callback_type callback_) - : ibase64_decoder(etl::base64::character_set_1(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc4648_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_1(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -683,9 +613,8 @@ namespace etl /// Calculate the required output encode buffer size. //************************************************************************* ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + static + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_decoder::decoded_size_from_valid_input_length(input_length); } @@ -709,13 +638,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648-Padding constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_padding_decoder() - : ibase64_decoder(etl::base64::character_set_1(), - etl::base64::Padding::Use_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc4648_padding_decoder() + : ibase64_decoder(etl::base64::character_set_1(), etl::base64::Padding::Use_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -723,13 +647,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648-Padding constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_padding_decoder(callback_type callback_) - : ibase64_decoder(etl::base64::character_set_1(), - etl::base64::Padding::Use_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc4648_padding_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_1(), etl::base64::Padding::Use_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -739,8 +658,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_decoder::decoded_size_from_valid_input_length(input_length); } @@ -764,13 +682,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648-Padding constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_url_decoder() - : ibase64_decoder(etl::base64::character_set_2(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc4648_url_decoder() + : ibase64_decoder(etl::base64::character_set_2(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -778,13 +691,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648-Padding constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_url_decoder(callback_type callback_) - : ibase64_decoder(etl::base64::character_set_2(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc4648_url_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_2(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -794,8 +702,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_decoder::decoded_size_from_valid_input_length(input_length); } @@ -819,13 +726,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648-Padding constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_url_padding_decoder() - : ibase64_decoder(etl::base64::character_set_2(), - etl::base64::Padding::Use_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc4648_url_padding_decoder() + : ibase64_decoder(etl::base64::character_set_2(), etl::base64::Padding::Use_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -833,13 +735,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648-Padding constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_url_padding_decoder(callback_type callback_) - : ibase64_decoder(etl::base64::character_set_2(), - etl::base64::Padding::Use_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc4648_url_padding_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_2(), etl::base64::Padding::Use_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -849,8 +746,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_decoder::decoded_size_from_valid_input_length(input_length); } @@ -860,7 +756,7 @@ namespace etl /// The internal output buffer. unsigned char output_buffer[Buffer_Size]; }; -} +} // namespace etl #undef ETL_IS_TYPE_8_BIT_INTEGRAL #undef ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL diff --git a/include/etl/base64_encoder.h b/include/etl/base64_encoder.h index cf4735e2..75ccd83a 100644 --- a/include/etl/base64_encoder.h +++ b/include/etl/base64_encoder.h @@ -1,5 +1,5 @@ //************************************************************************* -///Decode from Base64 from and to pointer/length +/// Decode from Base64 from and to pointer/length //*************************************************************************///\file /****************************************************************************** @@ -29,16 +29,16 @@ SOFTWARE. #define ETL_BASE64_ENCODER_INCLUDED #include "platform.h" -#include "static_assert.h" -#include "error_handler.h" -#include "type_traits.h" -#include "binary.h" #include "algorithm.h" +#include "binary.h" +#include "delegate.h" +#include "enum_type.h" +#include "error_handler.h" #include "integral_limits.h" #include "iterator.h" -#include "enum_type.h" -#include "delegate.h" #include "span.h" +#include "static_assert.h" +#include "type_traits.h" #include "base64.h" @@ -48,11 +48,12 @@ SOFTWARE. #include #endif -#define ETL_IS_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value && \ - (etl::integral_limits::type>::bits == 8U)) +#define ETL_IS_8_BIT_INTEGRAL(Type) \ + (etl::is_integral::type>::value && (etl::integral_limits::type>::bits == 8U)) -#define ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value_type>::value && \ - (etl::integral_limits::type>::value_type>::bits == 8U)) +#define ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(Type) \ + (etl::is_integral< typename etl::iterator_traits< typename etl::remove_cv::type>::value_type>::value \ + && (etl::integral_limits< typename etl::iterator_traits< typename etl::remove_cv::type>::value_type>::bits == 8U)) namespace etl { @@ -70,8 +71,7 @@ namespace etl /// Encode to Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool encode(T value) + ETL_CONSTEXPR14 bool encode(T value) { ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(T), "Input type must be an 8 bit integral"); @@ -99,8 +99,7 @@ namespace etl /// Encode to Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool encode(TInputIterator input_begin, size_t input_length) + ETL_CONSTEXPR14 bool encode(TInputIterator input_begin, size_t input_length) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -119,8 +118,7 @@ namespace etl /// Encode to Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool encode(TInputIterator input_begin, TInputIterator input_end) + ETL_CONSTEXPR14 bool encode(TInputIterator input_begin, TInputIterator input_end) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -139,8 +137,7 @@ namespace etl /// Encode to Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool encode_final(TInputIterator input_begin, size_t input_length) + ETL_CONSTEXPR14 bool encode_final(TInputIterator input_begin, size_t input_length) { return encode(input_begin, input_length) && flush(); } @@ -149,8 +146,7 @@ namespace etl /// Encode to Base64 //************************************************************************* template - ETL_CONSTEXPR14 - bool encode_final(TInputIterator input_begin, TInputIterator input_end) + ETL_CONSTEXPR14 bool encode_final(TInputIterator input_begin, TInputIterator input_end) { return encode(input_begin, input_end) && flush(); } @@ -158,8 +154,7 @@ namespace etl //************************************************************************* /// Flush any remaining data to the output. //************************************************************************* - ETL_CONSTEXPR14 - bool flush() + ETL_CONSTEXPR14 bool flush() { // Encode any remaining input data. bool success = encode_block(); @@ -189,8 +184,7 @@ namespace etl //************************************************************************* /// Reset the encoder. //************************************************************************* - ETL_CONSTEXPR14 - void restart() + ETL_CONSTEXPR14 void restart() { reset_input_buffer(); reset_output_buffer(); @@ -199,19 +193,16 @@ namespace etl //************************************************************************* /// Returns the beginning of the output buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const char* begin() const + ETL_NODISCARD ETL_CONSTEXPR14 const char* begin() const { return p_output_buffer; } //************************************************************************* - /// This only returns a useful value if a callback has not been set or called. + /// This only returns a useful value if a callback has not been set or + /// called. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const char* end() const + ETL_NODISCARD ETL_CONSTEXPR14 const char* end() const { return p_output_buffer + output_buffer_length; } @@ -219,30 +210,26 @@ namespace etl //************************************************************************* /// Returns the beginning of the output buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const char* cbegin() const + ETL_NODISCARD ETL_CONSTEXPR14 const char* cbegin() const { return p_output_buffer; } //************************************************************************* - /// This only returns a useful value if a callback has not been set or called. + /// This only returns a useful value if a callback has not been set or + /// called. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - const char* cend() const + ETL_NODISCARD ETL_CONSTEXPR14 const char* cend() const { return p_output_buffer + output_buffer_length; } //************************************************************************* /// Returns the size of the output buffer. - /// This only returns a useful value if a callback has not been set or called. + /// This only returns a useful value if a callback has not been set or + /// called. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - size_t size() const + ETL_NODISCARD ETL_CONSTEXPR14 size_t size() const { return output_buffer_length; } @@ -250,20 +237,17 @@ namespace etl //************************************************************************* /// Returns the maximum size of the output buffer. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - size_t max_size() const + ETL_NODISCARD ETL_CONSTEXPR14 size_t max_size() const { return output_buffer_max_size; } //************************************************************************* /// Get a span of the output data. - /// This only returns a useful span if a callback has not been set or called. + /// This only returns a useful span if a callback has not been set or + /// called. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - span_type span() const + ETL_NODISCARD ETL_CONSTEXPR14 span_type span() const { return span_type(begin(), end()); } @@ -271,9 +255,7 @@ namespace etl //************************************************************************* /// Returns true if the output buffer has overflowed //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - bool overflow() const + ETL_NODISCARD ETL_CONSTEXPR14 bool overflow() const { return overflowed; } @@ -281,9 +263,7 @@ namespace etl //************************************************************************* /// Returns true if an error was detected. //************************************************************************* - ETL_NODISCARD - ETL_CONSTEXPR14 - bool error() const + ETL_NODISCARD ETL_CONSTEXPR14 bool error() const { return overflow(); } @@ -293,12 +273,8 @@ namespace etl //************************************************************************* /// Constructor //************************************************************************* - ETL_CONSTEXPR14 - ibase64_encoder(const char* encoder_table_, - bool use_padding_, - char* p_output_buffer_, - size_t ouput_buffer_max_size_, - callback_type callback_) + ETL_CONSTEXPR14 ibase64_encoder(const char* encoder_table_, bool use_padding_, char* p_output_buffer_, size_t ouput_buffer_max_size_, + callback_type callback_) : base64(encoder_table_, use_padding_) , input_buffer() , input_buffer_length(0) @@ -313,64 +289,65 @@ namespace etl //************************************************************************* /// Encode one block of data. //************************************************************************* - ETL_CONSTEXPR14 - bool encode_block() + ETL_CONSTEXPR14 bool encode_block() { switch (input_buffer_length) { // Only triggered on call to flush(). case 1: - { - uint32_t octets = input_buffer[0]; - octets = octets << 4; // Adjust one octet (8 bits) for two sextets worth of data (12 bits) - - // Write out two sextets + optional padding. - push_to_output_buffer(encoder_table[(octets >> 6) & 0x3F]); - push_to_output_buffer(encoder_table[(octets >> 0) & 0x3F]); - - if (use_padding) { - push_to_output_buffer('='); - push_to_output_buffer('='); - } - break; - } + uint32_t octets = input_buffer[0]; + octets = octets << 4; // Adjust one octet (8 bits) for two sextets + // worth of data (12 bits) + + // Write out two sextets + optional padding. + push_to_output_buffer(encoder_table[(octets >> 6) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 0) & 0x3F]); + + if (use_padding) + { + push_to_output_buffer('='); + push_to_output_buffer('='); + } + break; + } // Only triggered on call to flush(). case 2: - { - uint32_t octets = (input_buffer[0] << 8) | input_buffer[1]; - octets <<= 2; // Adjust two octets (16 bits) for three sextets worth of data (18 bits) - - // Write out three sextets + optional padding. - push_to_output_buffer(encoder_table[(octets >> 12) & 0x3F]); - push_to_output_buffer(encoder_table[(octets >> 6) & 0x3F]); - push_to_output_buffer(encoder_table[(octets >> 0) & 0x3F]); - - if (use_padding) { - push_to_output_buffer('='); + uint32_t octets = (static_cast(input_buffer[0]) << 8) | input_buffer[1]; + octets <<= 2; // Adjust two octets (16 bits) for three sextets worth + // of data (18 bits) + + // Write out three sextets + optional padding. + push_to_output_buffer(encoder_table[(octets >> 12) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 6) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 0) & 0x3F]); + + if (use_padding) + { + push_to_output_buffer('='); + } + break; } - break; - } // Only triggered on call to encode(). case 3: - { - uint32_t octets = (input_buffer[0] << 16) | (input_buffer[1] << 8) | input_buffer[2]; + { + uint32_t octets = (static_cast(input_buffer[0]) << 16) | (static_cast(input_buffer[1]) << 8) | input_buffer[2]; - // Write out four sextets - push_to_output_buffer(encoder_table[(octets >> 18) & 0x3F]); - push_to_output_buffer(encoder_table[(octets >> 12) & 0x3F]); - push_to_output_buffer(encoder_table[(octets >> 6) & 0x3F]); - push_to_output_buffer(encoder_table[(octets >> 0) & 0x3F]); - break; - } + // Write out four sextets + push_to_output_buffer(encoder_table[(octets >> 18) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 12) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 6) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 0) & 0x3F]); + break; + } default: - { - break; - } + { + break; + } } ETL_ASSERT(!overflowed, ETL_ERROR(etl::base64_overflow)); @@ -383,8 +360,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t encoded_size(size_t input_length, bool use_padding) + ETL_CONSTEXPR14 size_t encoded_size(size_t input_length, bool use_padding) { size_t required_output_length = 0; @@ -420,8 +396,7 @@ namespace etl //************************************************************************* // Push to the output buffer. //************************************************************************* - ETL_CONSTEXPR14 - void push_to_output_buffer(char c) + ETL_CONSTEXPR14 void push_to_output_buffer(char c) { if (output_buffer_length < output_buffer_max_size) { @@ -434,28 +409,25 @@ namespace etl } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - bool output_buffer_is_full() const + ETL_CONSTEXPR14 bool output_buffer_is_full() const { return output_buffer_length == output_buffer_max_size; } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - bool output_buffer_is_empty() const + ETL_CONSTEXPR14 bool output_buffer_is_empty() const { return output_buffer_length == 0; } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - void reset_output_buffer() + ETL_CONSTEXPR14 void reset_output_buffer() { output_buffer_length = 0; } @@ -464,26 +436,23 @@ namespace etl // Push to the input buffer. //************************************************************************* template - ETL_CONSTEXPR14 - void push_to_input_buffer(T value) + ETL_CONSTEXPR14 void push_to_input_buffer(T value) { input_buffer[input_buffer_length++] = static_cast(value); } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - bool input_buffer_is_full() const + ETL_CONSTEXPR14 bool input_buffer_is_full() const { return input_buffer_length == 3U; } //************************************************************************* - // + // //************************************************************************* - ETL_CONSTEXPR14 - void reset_input_buffer() + ETL_CONSTEXPR14 void reset_input_buffer() { input_buffer_length = 0; } @@ -496,7 +465,7 @@ namespace etl const size_t output_buffer_max_size; callback_type callback; - + bool overflowed; }; @@ -508,19 +477,15 @@ namespace etl { public: - ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); - ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), + "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); //************************************************************************* /// Base64 RFC-2152 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc2152_encoder() - : ibase64_encoder(etl::base64::character_set_1(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc2152_encoder() + : ibase64_encoder(etl::base64::character_set_1(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -528,13 +493,8 @@ namespace etl //************************************************************************* /// Base64 RFC-2152 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc2152_encoder(callback_type callback_) - : ibase64_encoder(etl::base64::character_set_1(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc2152_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_1(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -544,8 +504,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::No_Padding); } @@ -564,19 +523,15 @@ namespace etl { public: - ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); - ETL_STATIC_ASSERT(((Buffer_Size% etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), + "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); //************************************************************************* /// Base64 RFC-3501 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc3501_encoder() - : ibase64_encoder(etl::base64::character_set_3(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc3501_encoder() + : ibase64_encoder(etl::base64::character_set_3(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -584,13 +539,8 @@ namespace etl //************************************************************************* /// Base64 RFC-3501 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc3501_encoder(callback_type callback_) - : ibase64_encoder(etl::base64::character_set_3(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc3501_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_3(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -600,8 +550,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::No_Padding); } @@ -620,19 +569,15 @@ namespace etl { public: - ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); - ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), + "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); //************************************************************************* /// Base64 RFC-4648 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_encoder() - : ibase64_encoder(etl::base64::character_set_1(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc4648_encoder() + : ibase64_encoder(etl::base64::character_set_1(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -640,13 +585,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648 constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_encoder(callback_type callback_) - : ibase64_encoder(etl::base64::character_set_1(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc4648_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_1(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -656,8 +596,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::No_Padding); } @@ -676,19 +615,15 @@ namespace etl { public: - ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); - ETL_STATIC_ASSERT(((Buffer_Size% etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), + "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); //************************************************************************* /// Base64 RFC-4648-Padding constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_padding_encoder() - : ibase64_encoder(etl::base64::character_set_1(), - etl::base64::Padding::Use_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc4648_padding_encoder() + : ibase64_encoder(etl::base64::character_set_1(), etl::base64::Padding::Use_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -696,13 +631,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648-Padding constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_padding_encoder(callback_type callback_) - : ibase64_encoder(etl::base64::character_set_1(), - etl::base64::Padding::Use_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc4648_padding_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_1(), etl::base64::Padding::Use_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -712,8 +642,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::Use_Padding); } @@ -732,19 +661,15 @@ namespace etl { public: - ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); - ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), + "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); //************************************************************************* /// Base64 RFC-4648-URL constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_url_encoder() - : ibase64_encoder(etl::base64::character_set_2(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc4648_url_encoder() + : ibase64_encoder(etl::base64::character_set_2(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -752,13 +677,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648-URL constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_url_encoder(callback_type callback_) - : ibase64_encoder(etl::base64::character_set_2(), - etl::base64::Padding::No_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc4648_url_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_2(), etl::base64::Padding::No_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -768,8 +688,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::No_Padding); } @@ -788,19 +707,15 @@ namespace etl { public: - ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); - ETL_STATIC_ASSERT(((Buffer_Size% etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), + "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); //************************************************************************* /// Base64 RFC-4648-URL constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_url_padding_encoder() - : ibase64_encoder(etl::base64::character_set_2(), - etl::base64::Padding::Use_Padding, - output_buffer, - Buffer_Size, - callback_type()) + ETL_CONSTEXPR14 base64_rfc4648_url_padding_encoder() + : ibase64_encoder(etl::base64::character_set_2(), etl::base64::Padding::Use_Padding, output_buffer, Buffer_Size, callback_type()) , output_buffer() { } @@ -808,13 +723,8 @@ namespace etl //************************************************************************* /// Base64 RFC-4648-URL constructor. //************************************************************************* - ETL_CONSTEXPR14 - base64_rfc4648_url_padding_encoder(callback_type callback_) - : ibase64_encoder(etl::base64::character_set_2(), - etl::base64::Padding::Use_Padding, - output_buffer, - Buffer_Size, - callback_) + ETL_CONSTEXPR14 base64_rfc4648_url_padding_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_2(), etl::base64::Padding::Use_Padding, output_buffer, Buffer_Size, callback_) , output_buffer() { } @@ -824,8 +734,7 @@ namespace etl //************************************************************************* ETL_NODISCARD static - ETL_CONSTEXPR14 - size_t safe_output_buffer_size(size_t input_length) + ETL_CONSTEXPR14 size_t safe_output_buffer_size(size_t input_length) { return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::Use_Padding); } @@ -835,7 +744,7 @@ namespace etl /// The internal output buffer. char output_buffer[Buffer_Size]; }; -} +} // namespace etl #undef ETL_IS_TYPE_8_BIT_INTEGRAL #undef ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL diff --git a/include/etl/basic_format_spec.h b/include/etl/basic_format_spec.h index c374e35f..f80d0ec6 100644 --- a/include/etl/basic_format_spec.h +++ b/include/etl/basic_format_spec.h @@ -34,8 +34,8 @@ SOFTWARE. ///\ingroup string #include "platform.h" -#include "type_traits.h" #include "static_assert.h" +#include "type_traits.h" #include "utility.h" namespace etl @@ -131,7 +131,7 @@ namespace etl struct right_spec { }; - } + } // namespace private_basic_format_spec //*************************************************************************** // Stream formatting manipulators. @@ -222,14 +222,8 @@ namespace etl //*************************************************************************** /// Constructor. //*************************************************************************** - ETL_CONSTEXPR basic_format_spec(uint_least8_t base__, - uint_least8_t width__, - uint_least8_t precision__, - bool upper_case__, - bool left_justified__, - bool boolalpha__, - bool show_base__, - typename TString::value_type fill__) ETL_NOEXCEPT + ETL_CONSTEXPR basic_format_spec(uint_least8_t base__, uint_least8_t width__, uint_least8_t precision__, bool upper_case__, bool left_justified__, + bool boolalpha__, bool show_base__, typename TString::value_type fill__) ETL_NOEXCEPT : base_(base__) , width_(width__) , precision_(precision__) @@ -400,7 +394,7 @@ namespace etl //*************************************************************************** /// Gets the width. //*************************************************************************** - ETL_CONSTEXPR uint32_t get_width() const ETL_NOEXCEPT + ETL_CONSTEXPR uint32_t get_width() const ETL_NOEXCEPT { return width_; } @@ -570,36 +564,32 @@ namespace etl //*************************************************************************** /// Equality operator. //*************************************************************************** - ETL_CONSTEXPR friend bool operator ==(const basic_format_spec& lhs, const basic_format_spec& rhs) + ETL_CONSTEXPR friend bool operator==(const basic_format_spec& lhs, const basic_format_spec& rhs) { - return (lhs.base_ == rhs.base_) && - (lhs.width_ == rhs.width_) && - (lhs.precision_ == rhs.precision_) && - (lhs.upper_case_ == rhs.upper_case_) && - (lhs.left_justified_ == rhs.left_justified_) && - (lhs.boolalpha_ == rhs.boolalpha_) && - (lhs.show_base_ == rhs.show_base_) && - (lhs.fill_ == rhs.fill_); + return (lhs.base_ == rhs.base_) && (lhs.width_ == rhs.width_) && (lhs.precision_ == rhs.precision_) && (lhs.upper_case_ == rhs.upper_case_) + && (lhs.left_justified_ == rhs.left_justified_) && (lhs.boolalpha_ == rhs.boolalpha_) && (lhs.show_base_ == rhs.show_base_) + && (lhs.fill_ == rhs.fill_); } //*************************************************************************** /// Inequality operator. //*************************************************************************** - ETL_CONSTEXPR friend bool operator !=(const basic_format_spec& lhs, const basic_format_spec& rhs) + ETL_CONSTEXPR friend bool operator!=(const basic_format_spec& lhs, const basic_format_spec& rhs) { return !(lhs == rhs); } private: - uint_least8_t base_; - uint_least8_t width_; - uint_least8_t precision_; - bool upper_case_; - bool left_justified_; - bool boolalpha_; - bool show_base_; + + uint_least8_t base_; + uint_least8_t width_; + uint_least8_t precision_; + bool upper_case_; + bool left_justified_; + bool boolalpha_; + bool show_base_; typename TString::value_type fill_; }; -} +} // namespace etl #endif diff --git a/include/etl/basic_string.h b/include/etl/basic_string.h index 9dd93ead..1a38cc99 100644 --- a/include/etl/basic_string.h +++ b/include/etl/basic_string.h @@ -33,18 +33,18 @@ SOFTWARE. #include "platform.h" #include "algorithm.h" -#include "iterator.h" -#include "functional.h" #include "alignment.h" #include "array.h" -#include "type_traits.h" -#include "error_handler.h" -#include "integral_limits.h" -#include "exception.h" -#include "memory.h" #include "binary.h" +#include "error_handler.h" +#include "exception.h" #include "flags.h" +#include "functional.h" +#include "integral_limits.h" +#include "iterator.h" +#include "memory.h" #include "string_utilities.h" +#include "type_traits.h" #include #include @@ -71,7 +71,7 @@ SOFTWARE. //***************************************************************************** // Forward declaration of string_view -namespace etl +namespace etl { template class basic_string_view; @@ -165,7 +165,7 @@ namespace etl static ETL_CONSTANT uint_least8_t IS_TRUNCATED = etl::bit<0>::value; static ETL_CONSTANT uint_least8_t CLEAR_AFTER_USE = etl::bit<1>::value; - + static ETL_CONSTANT size_type npos = etl::integral_limits::max; }; @@ -177,7 +177,7 @@ namespace etl template ETL_CONSTANT typename string_base_statics::size_type string_base_statics::npos; - } + } // namespace private_basic_string //*************************************************************************** class string_base : public private_basic_string::string_base_statics<> @@ -329,12 +329,10 @@ namespace etl //************************************************************************* /// Destructor. //************************************************************************* - ~string_base() - { - } + ~string_base() {} - size_type current_size; ///< The current number of elements in the string. - const size_type CAPACITY; ///< The maximum number of elements in the string. + size_type current_size; ///< The current number of elements in the string. + const size_type CAPACITY; ///< The maximum number of elements in the string. #if ETL_HAS_STRING_TRUNCATION_CHECKS || ETL_HAS_STRING_CLEAR_AFTER_USE etl::flags flags; @@ -343,7 +341,8 @@ namespace etl //*************************************************************************** /// The base class for specifically sized strings. - /// Can be used as a reference type for all strings containing a specific type. + /// Can be used as a reference type for all strings containing a specific + /// type. ///\ingroup string //*************************************************************************** template @@ -353,13 +352,13 @@ namespace etl typedef ibasic_string interface_type; - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef T* iterator; - typedef const T* const_iterator; + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef T* iterator; + typedef const T* const_iterator; typedef ETL_OR_STD::reverse_iterator reverse_iterator; typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; @@ -486,7 +485,8 @@ namespace etl //********************************************************************* /// Resizes the string. ///\param new_size The new size. - ///\param value The value to fill new elements with. Default = default constructed value. + ///\param value The value to fill new elements with. Default = default + /// constructed value. //********************************************************************* void resize(size_type new_size, T value) { @@ -495,9 +495,9 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif #endif } @@ -509,7 +509,7 @@ namespace etl etl::fill(p_buffer + current_size, p_buffer + new_size, value); } - current_size = new_size; + current_size = new_size; p_buffer[new_size] = 0; cleanup(); } @@ -525,7 +525,7 @@ namespace etl ETL_ASSERT_FAIL(ETL_ERROR(string_out_of_bounds)); } - current_size = operation(p_buffer, new_size); + current_size = operation(p_buffer, new_size); p_buffer[current_size] = '\0'; cleanup(); } @@ -539,7 +539,7 @@ namespace etl { new_size = etl::min(new_size, CAPACITY); - current_size = new_size; + current_size = new_size; p_buffer[new_size] = 0; } @@ -558,7 +558,7 @@ namespace etl ///\param i The index. ///\return A reference to the value at index 'i' //********************************************************************* - reference operator [](size_type i) + reference operator[](size_type i) { ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(string_out_of_bounds)); return p_buffer[i]; @@ -569,7 +569,7 @@ namespace etl ///\param i The index. ///\return A const reference to the value at index 'i' //********************************************************************* - const_reference operator [](size_type i) const + const_reference operator[](size_type i) const { ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(string_out_of_bounds)); return p_buffer[i]; @@ -577,7 +577,8 @@ namespace etl //********************************************************************* /// Returns a reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range. + /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds + /// if the index is out of range. ///\param i The index. ///\return A reference to the value at index 'i' //********************************************************************* @@ -589,7 +590,8 @@ namespace etl //********************************************************************* /// Returns a const reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range. + /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds + /// if the index is out of range. ///\param i The index. ///\return A const reference to the value at index 'i' //********************************************************************* @@ -715,8 +717,9 @@ namespace etl //********************************************************************* /// Assigns values to the string. - /// If asserts or exceptions are enabled, emits string_iterator if the iterators are reversed. - /// Truncates if the string does not have enough free space. + /// If asserts or exceptions are enabled, emits string_iterator if the + /// iterators are reversed. Truncates if the string does not have enough + /// free space. ///\param first The iterator to the first element. ///\param last The iterator to the last element + 1. //********************************************************************* @@ -747,7 +750,7 @@ namespace etl append_impl(begin(), str, str + n, false, false); } - //********************************************************************* + //********************************************************************* /// Assigns values to the string from a view. //********************************************************************* template @@ -769,15 +772,15 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(n > CAPACITY); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); -#endif + #endif #endif n = etl::min(n, CAPACITY); etl::fill_n(begin(), n, c); - current_size = n; + current_size = n; p_buffer[current_size] = 0; } @@ -807,9 +810,9 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif #endif } } @@ -917,9 +920,9 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(n > free_space); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); -#endif + #endif #endif n = etl::min(n, size_t(free_space)); @@ -966,16 +969,16 @@ namespace etl if (position != end()) { // Insert in the middle. - etl::mem_move(insert_position, end() - 1, insert_position + 1); + etl::mem_move(insert_position, end() - 1, insert_position + 1); *insert_position = value; } #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif #endif } @@ -1002,8 +1005,8 @@ namespace etl } // Quick hack, as iterators are pointers. - iterator insert_position = to_iterator(position); - const size_type start = etl::distance(cbegin(), position); + iterator insert_position = to_iterator(position); + const size_type start = static_cast(etl::distance(cbegin(), position)); // No effect. if (start >= CAPACITY) @@ -1011,9 +1014,9 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif #endif return to_iterator(position); } @@ -1026,9 +1029,9 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif #endif } @@ -1038,11 +1041,11 @@ namespace etl else { // Lets do some shifting. - const size_type shift_amount = n; - const size_type to_position = start + shift_amount; + const size_type shift_amount = n; + const size_type to_position = start + shift_amount; const size_type remaining_characters = current_size - start; const size_type max_shift_characters = CAPACITY - start - shift_amount; - const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters); + const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters); // Will the string truncate? if ((start + shift_amount + remaining_characters) > CAPACITY) @@ -1052,9 +1055,9 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif #endif } else @@ -1073,7 +1076,8 @@ namespace etl //********************************************************************* /// Inserts a range of values to the string. - /// If asserts or exceptions are enabled, emits string_full if the string does not have enough free space. + /// If asserts or exceptions are enabled, emits string_full if the string + /// does not have enough free space. ///\param position The position to insert before. ///\param first The first element to add. ///\param last The last + 1 element to add. @@ -1083,7 +1087,7 @@ namespace etl { ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds)); ETL_ASSERT_CHECK_EXTRA(first <= last, ETL_ERROR(string_iterator)); - + iterator position_ = to_iterator(position); if (first == last) @@ -1091,8 +1095,8 @@ namespace etl return position_; } - const size_type start = etl::distance(begin(), position_); - const size_type n = etl::distance(first, last); + const size_type start = static_cast(etl::distance(begin(), position_)); + const size_type n = static_cast(etl::distance(first, last)); // No effect. if (start >= CAPACITY) @@ -1100,9 +1104,9 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif #endif return position_; } @@ -1115,24 +1119,24 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif #endif } current_size = CAPACITY; - position_ = copy_characters(first, etl::distance(position_, end()), position_); + position_ = copy_characters(first, static_cast(etl::distance(position_, end())), position_); } else { // Lets do some shifting. - const size_type shift_amount = n; - const size_type to_position = start + shift_amount; + const size_type shift_amount = n; + const size_type to_position = start + shift_amount; const size_type remaining_characters = current_size - start; const size_type max_shift_characters = CAPACITY - start - shift_amount; - const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters); + const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters); // Will the string truncate? if ((start + shift_amount + remaining_characters) > CAPACITY) @@ -1142,9 +1146,9 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif #endif } else @@ -1153,9 +1157,10 @@ namespace etl } etl::mem_move(position_, position_ + characters_to_shift, begin() + to_position); - //etl::copy_backward(position_, position_ + characters_to_shift, begin() + to_position + characters_to_shift); + // etl::copy_backward(position_, position_ + characters_to_shift, + // begin() + to_position + characters_to_shift); - position_ = copy_characters(first, etl::distance(first, last), position_); + position_ = copy_characters(first, static_cast(etl::distance(first, last)), position_); } p_buffer[current_size] = 0; @@ -1165,7 +1170,8 @@ namespace etl //********************************************************************* /// Inserts a view to the string. - /// If asserts or exceptions are enabled, emits string_full if the string does not have enough free space. + /// If asserts or exceptions are enabled, emits string_full if the string + /// does not have enough free space. ///\param position The position to insert before. ///\param view The view element to add. //********************************************************************* @@ -1191,9 +1197,9 @@ namespace etl { set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif } #endif @@ -1216,7 +1222,8 @@ namespace etl } //********************************************************************* - /// Inserts a string at the specified position from subposition for sublength. + /// Inserts a string at the specified position from subposition for + /// sublength. ///\param position The position to insert before. ///\param str The string to insert. ///\param subposition The subposition to start from. @@ -1224,7 +1231,7 @@ namespace etl //********************************************************************* etl::ibasic_string& insert(size_type position, const etl::ibasic_string& str, size_type subposition, size_type sublength) { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); if ((sublength == npos) || (subposition + sublength > str.size())) @@ -1239,9 +1246,9 @@ namespace etl { set_truncated(true); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); -#endif + #endif } #endif @@ -1258,7 +1265,7 @@ namespace etl template etl::ibasic_string& insert(size_type position, const etl::basic_string_view& view, size_type subposition, size_type sublength) { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); ETL_ASSERT(subposition <= view.size(), ETL_ERROR(string_out_of_bounds)); if ((sublength == npos) || (subposition + sublength > view.size())) @@ -1285,7 +1292,8 @@ namespace etl } //********************************************************************* - /// Inserts a string at the specified position from pointer for n characters. + /// Inserts a string at the specified position from pointer for n + /// characters. ///\param position The position to insert before. ///\param s The string to insert. ///\param n The number of characters to insert. @@ -1333,7 +1341,8 @@ namespace etl //********************************************************************* /// Erases an element. ///\param i_element Iterator to the element. - ///\return An iterator pointing to the element that followed the erased element. + ///\return An iterator pointing to the element that followed the erased + /// element. //********************************************************************* iterator erase(iterator i_element) { @@ -1348,12 +1357,13 @@ namespace etl //********************************************************************* /// Erases an element. ///\param i_element Iterator to the element. - ///\return An iterator pointing to the element that followed the erased element. + ///\return An iterator pointing to the element that followed the erased + /// element. //********************************************************************* iterator erase(const_iterator i_element) { ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(string_out_of_bounds)); - + iterator i_element_(to_iterator(i_element)); etl::mem_move(i_element + 1, end(), i_element_); @@ -1364,11 +1374,12 @@ namespace etl //********************************************************************* /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed by last. + /// The range includes all the elements between first and last, including + /// the element pointed by first, but not the one pointed by last. ///\param first Iterator to the first element. ///\param last Iterator to the last element. - ///\return An iterator pointing to the element that followed the erased element. + ///\return An iterator pointing to the element that followed the erased + /// element. //********************************************************************* iterator erase(const_iterator first, const_iterator last) { @@ -1383,7 +1394,7 @@ namespace etl } etl::mem_move(last_, end(), first_); - size_type n_delete = etl::distance(first_, last_); + size_type n_delete = static_cast(etl::distance(first_, last_)); current_size -= n_delete; p_buffer[current_size] = 0; @@ -1486,7 +1497,7 @@ namespace etl if (i != end()) { - return etl::distance(begin(), i); + return static_cast(etl::distance(begin(), i)); } else { @@ -1557,11 +1568,11 @@ namespace etl position = size() - position; - const_reverse_iterator i = etl::find(rbegin() + position, rend(), c); + const_reverse_iterator i = etl::find(rbegin() + static_cast(position), rend(), c); if (i != rend()) { - return size() - etl::distance(rbegin(), i) - 1; + return size() - static_cast(etl::distance(rbegin(), i)) - 1; } else { @@ -1572,7 +1583,7 @@ namespace etl //********************************************************************* /// Checks that the string is within this string //********************************************************************* - bool contains(const etl::ibasic_string& str) const + bool contains(const etl::ibasic_string& str) const { return find(str) != npos; } @@ -1581,7 +1592,7 @@ namespace etl /// Checks that the view is within this string //********************************************************************* template - bool contains(const etl::basic_string_view& view) const + bool contains(const etl::basic_string_view& view) const { return find(view) != npos; } @@ -1589,7 +1600,7 @@ namespace etl //********************************************************************* /// Checks that text is within this string //********************************************************************* - bool contains(const_pointer s) const + bool contains(const_pointer s) const { return find(s) != npos; } @@ -1597,7 +1608,7 @@ namespace etl //********************************************************************* /// Checks that character is within this string //********************************************************************* - bool contains(value_type c) const + bool contains(value_type c) const { return find(c) != npos; } @@ -1605,7 +1616,7 @@ namespace etl //********************************************************************* /// Checks that the string is the start of this string //********************************************************************* - bool starts_with(const etl::ibasic_string& str) const + bool starts_with(const etl::ibasic_string& str) const { return compare(0, str.size(), str) == 0; } @@ -1614,7 +1625,7 @@ namespace etl /// Checks that the view is the start of this string //********************************************************************* template - bool starts_with(const etl::basic_string_view& view) const + bool starts_with(const etl::basic_string_view& view) const { return compare(0, view.size(), view) == 0; } @@ -1622,7 +1633,7 @@ namespace etl //********************************************************************* /// Checks that the string is the start of this string //********************************************************************* - bool starts_with(const_pointer s) const + bool starts_with(const_pointer s) const { size_t len = etl::strlen(s); @@ -1632,7 +1643,7 @@ namespace etl //********************************************************************* /// Checks that the character is the start of this string //********************************************************************* - bool starts_with(value_type c) const + bool starts_with(value_type c) const { return !empty() && (front() == c); } @@ -1640,9 +1651,9 @@ namespace etl //********************************************************************* /// Checks that the string is the end of this string //********************************************************************* - bool ends_with(const etl::ibasic_string& str) const + bool ends_with(const etl::ibasic_string& str) const { - if (str.size() > size()) + if (str.size() > size()) { return false; } @@ -1654,9 +1665,9 @@ namespace etl /// Checks that the view is the end of this string //********************************************************************* template - bool ends_with(const etl::basic_string_view& view) const + bool ends_with(const etl::basic_string_view& view) const { - if (view.size() > size()) + if (view.size() > size()) { return false; } @@ -1667,11 +1678,11 @@ namespace etl //********************************************************************* /// Checks that the string is the end of this string //********************************************************************* - bool ends_with(const_pointer s) const + bool ends_with(const_pointer s) const { size_t len = etl::strlen(s); - if (len > size()) + if (len > size()) { return false; } @@ -1682,7 +1693,7 @@ namespace etl //********************************************************************* /// Checks that the character is the end of this string //********************************************************************* - bool ends_with(value_type c) const + bool ends_with(value_type c) const { return !empty() && (back() == c); } @@ -1744,7 +1755,8 @@ namespace etl } //********************************************************************* - /// Replace characters from 'position' of 'length' with 'str' from 'subposition' of 'sublength'. + /// Replace characters from 'position' of 'length' with 'str' from + /// 'subposition' of 'sublength'. //********************************************************************* ibasic_string& replace(size_type position, size_type length_, const ibasic_string& str, size_type subposition, size_type sublength) { @@ -1754,15 +1766,17 @@ namespace etl // Limit the lengths. length_ = etl::min(length_, size() - position); sublength = etl::min(sublength, str.size() - subposition); - + return replace_impl(begin() + position, begin() + position + length_, str.begin() + subposition, sublength, str.is_truncated()); } //********************************************************************* - /// Replace characters from 'position' of 'length' with 'view' from 'subposition' of 'sublength'. + /// Replace characters from 'position' of 'length' with 'view' from + /// 'subposition' of 'sublength'. //********************************************************************* template - ibasic_string& replace(size_type position, size_type length_, const etl::basic_string_view& view, size_type subposition, size_type sublength) + ibasic_string& replace(size_type position, size_type length_, const etl::basic_string_view& view, size_type subposition, + size_type sublength) { ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); ETL_ASSERT(subposition <= view.size(), ETL_ERROR(string_out_of_bounds)); @@ -1805,8 +1819,8 @@ namespace etl /// Replace characters from 'first' to 'last' with pointed to string. //********************************************************************* template - typename etl::enable_if::value, ibasic_string>::type& - replace(const_iterator first, const_iterator last, TIterator s) + typename etl::enable_if::value, ibasic_string>::type& replace(const_iterator first, const_iterator last, + TIterator s) { return replace_impl(first, last, s, etl::strlen(s), false); } @@ -1821,7 +1835,8 @@ namespace etl } //********************************************************************* - /// Replace characters from 'position' of 'length' with 'n' characters from pointed to string. + /// Replace characters from 'position' of 'length' with 'n' characters from + /// pointed to string. //********************************************************************* ibasic_string& replace(size_type position, size_type length_, const_pointer s, size_type n) { @@ -1871,7 +1886,8 @@ namespace etl } //********************************************************************* - /// Replace characters from 'first' of 'last' with characters from 'first_replace' to 'last_replace'. + /// Replace characters from 'first' of 'last' with characters from + /// 'first_replace' to 'last_replace'. //********************************************************************* template ibasic_string& replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace) @@ -1894,10 +1910,7 @@ namespace etl //************************************************************************* int compare(const ibasic_string& str) const { - return compare(p_buffer, - p_buffer + size(), - str.p_buffer, - str.p_buffer + str.size()); + return compare(p_buffer, p_buffer + size(), str.p_buffer, str.p_buffer + str.size()); } //************************************************************************* @@ -1906,10 +1919,7 @@ namespace etl template int compare(const etl::basic_string_view& view) const { - return compare(p_buffer, - p_buffer + size(), - view.data(), - view.data() + view.size()); + return compare(p_buffer, p_buffer + size(), view.data(), view.data() + view.size()); } //************************************************************************* @@ -1922,10 +1932,7 @@ namespace etl // Limit the length. length_ = etl::min(length_, size() - position); - return compare(p_buffer + position, - p_buffer + position + length_, - str.p_buffer, - str.p_buffer + str.size()); + return compare(p_buffer + position, p_buffer + position + length_, str.p_buffer, str.p_buffer + str.size()); } //************************************************************************* @@ -1934,10 +1941,7 @@ namespace etl template int compare(size_type position, size_type length_, const etl::basic_string_view& view) const { - return compare(p_buffer + position, - p_buffer + position + length_, - view.data(), - view.data() + view.size()); + return compare(p_buffer + position, p_buffer + position + length_, view.data(), view.data() + view.size()); } //************************************************************************* @@ -1949,20 +1953,19 @@ namespace etl ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); // Limit the lengths. - length_ = etl::min(length_, size() - position); + length_ = etl::min(length_, size() - position); sublength = etl::min(sublength, str.size() - subposition); - return compare(p_buffer + position, - p_buffer + position + length_, - str.p_buffer + subposition, - str.p_buffer + subposition + sublength); + return compare(p_buffer + position, p_buffer + position + length_, str.p_buffer + subposition, str.p_buffer + subposition + sublength); } //************************************************************************* - /// Compare position / length with etl::basic_string_view. / subposition / sublength. + /// Compare position / length with etl::basic_string_view. / subposition / + /// sublength. //************************************************************************* template - int compare(size_type position, size_type length_, const etl::basic_string_view& view, size_type subposition, size_type sublength) const + int compare(size_type position, size_type length_, const etl::basic_string_view& view, size_type subposition, + size_type sublength) const { ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); ETL_ASSERT(subposition <= view.size(), ETL_ERROR(string_out_of_bounds)); @@ -1971,10 +1974,7 @@ namespace etl length_ = etl::min(length_, size() - position); sublength = etl::min(sublength, view.size() - subposition); - return compare(p_buffer + position, - p_buffer + position + length_, - view.data() + subposition, - view.data() + subposition + sublength); + return compare(p_buffer + position, p_buffer + position + length_, view.data() + subposition, view.data() + subposition + sublength); } //************************************************************************* @@ -1982,10 +1982,7 @@ namespace etl //************************************************************************* int compare(const value_type* s) const { - return compare(p_buffer, - p_buffer + size(), - s, - s + etl::strlen(s)); + return compare(p_buffer, p_buffer + size(), s, s + etl::strlen(s)); } //************************************************************************* @@ -1993,10 +1990,7 @@ namespace etl //************************************************************************* int compare(size_type position, size_type length_, const_pointer s) const { - return compare(p_buffer + position, - p_buffer + position + length_, - s, - s + etl::strlen(s)); + return compare(p_buffer + position, p_buffer + position + length_, s, s + etl::strlen(s)); } //************************************************************************* @@ -2004,10 +1998,7 @@ namespace etl //************************************************************************* int compare(size_type position, size_type length_, const_pointer s, size_type n) const { - return compare(p_buffer + position, - p_buffer + position + length_, - s, - s + n); + return compare(p_buffer + position, p_buffer + position + length_, s, s + n); } //********************************************************************* @@ -2133,7 +2124,7 @@ namespace etl position = etl::min(position, size() - 1); - const_reverse_iterator it = rbegin() + size() - position - 1; + const_reverse_iterator it = rbegin() + static_cast(size() - position - 1); while (it != rend()) { @@ -2166,7 +2157,7 @@ namespace etl position = etl::min(position, size() - 1); - const_reverse_iterator it = rbegin() + size() - position - 1; + const_reverse_iterator it = rbegin() + static_cast(size() - position - 1); while (it != rend()) { @@ -2312,7 +2303,7 @@ namespace etl position = etl::min(position, size() - 1); - const_reverse_iterator it = rbegin() + size() - position - 1; + const_reverse_iterator it = rbegin() + static_cast(size() - position - 1); while (it != rend()) { @@ -2350,7 +2341,7 @@ namespace etl position = etl::min(position, size() - 1); - const_reverse_iterator it = rbegin() + size() - position - 1; + const_reverse_iterator it = rbegin() + static_cast(size() - position - 1); while (it != rend()) { @@ -2369,7 +2360,7 @@ namespace etl //************************************************************************* /// Assignment operator. //************************************************************************* - ibasic_string& operator = (const ibasic_string& rhs) + ibasic_string& operator=(const ibasic_string& rhs) { if (&rhs != this) { @@ -2382,7 +2373,7 @@ namespace etl //************************************************************************* /// Assignment operator. //************************************************************************* - ibasic_string& operator = (const_pointer rhs) + ibasic_string& operator=(const_pointer rhs) { assign(rhs); @@ -2393,7 +2384,7 @@ namespace etl /// Assignment operator. //************************************************************************* template - ibasic_string& operator = (const etl::basic_string_view& view) + ibasic_string& operator=(const etl::basic_string_view& view) { assign(view); @@ -2403,7 +2394,7 @@ namespace etl //************************************************************************* /// += operator. //************************************************************************* - ibasic_string& operator += (const ibasic_string& rhs) + ibasic_string& operator+=(const ibasic_string& rhs) { append(rhs); @@ -2414,7 +2405,7 @@ namespace etl /// += operator. //************************************************************************* template - ibasic_string& operator += (const etl::basic_string_view& rhs) + ibasic_string& operator+=(const etl::basic_string_view& rhs) { append(rhs); @@ -2424,7 +2415,7 @@ namespace etl //************************************************************************* /// += operator. //************************************************************************* - ibasic_string& operator += (const_pointer rhs) + ibasic_string& operator+=(const_pointer rhs) { append(rhs); @@ -2434,7 +2425,7 @@ namespace etl //************************************************************************* /// += operator. //************************************************************************* - ibasic_string& operator += (T rhs) + ibasic_string& operator+=(T rhs) { append(size_type(1), rhs); @@ -2471,7 +2462,7 @@ namespace etl #endif p_buffer[CAPACITY] = T(0); // Ensure a terminating null. - current_size = etl::strlen(p_buffer); + current_size = etl::strlen(p_buffer); } protected: @@ -2480,8 +2471,8 @@ namespace etl /// Constructor. //********************************************************************* ibasic_string(T* p_buffer_, size_type MAX_SIZE_) - : string_base(MAX_SIZE_), - p_buffer(p_buffer_) + : string_base(MAX_SIZE_) + , p_buffer(p_buffer_) { } @@ -2491,7 +2482,7 @@ namespace etl void initialise() { current_size = 0U; - p_buffer[0] = 0; + p_buffer[0] = 0; #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(false); #endif @@ -2532,9 +2523,7 @@ namespace etl // If source pointer is inside our current buffer we take the safe // (legacy) path to preserve correct semantics for overlapping self use. - const bool source_overlaps = (s != ETL_NULLPTR) && - (s >= p_buffer) && - (s < p_buffer + current_size); + const bool source_overlaps = (s != ETL_NULLPTR) && (s >= p_buffer) && (s < p_buffer + current_size); if (source_overlaps) { @@ -2553,9 +2542,10 @@ namespace etl // Calculate the remove parameters. const size_type remove_index = size_type(first_ - p_buffer); - const size_type remove_length = size_type(last_ - first_); - const size_type free_space = CAPACITY - remove_index; // Free space is the space from the remove index to the end of the buffer. - + const size_type remove_length = size_type(last_ - first_); + const size_type free_space = CAPACITY - remove_index; // Free space is the space from the remove + // index to the end of the buffer. + size_type insert_length = (s == ETL_NULLPTR) ? 0U : length; // Limit the insert length to the available free space. @@ -2568,12 +2558,13 @@ namespace etl size_type tail_index = remove_index + remove_length; size_type tail_length = current_size - tail_index; size_type tail_space = free_space - insert_length; - + #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated((insert_length != length) || (tail_space < tail_length) || is_truncated() || other_truncated); #endif - // The some or all of tail may be erased if the space remaining for it is smaller than the tail length. + // The some or all of tail may be erased if the space remaining for it is + // smaller than the tail length. if (tail_space < tail_length) { tail_length = tail_space; @@ -2604,7 +2595,7 @@ namespace etl etl::mem_move(&p_buffer[tail_index], tail_length, &p_buffer[remove_index + insert_length]); } - current_size = remove_index + insert_length + tail_length; + current_size = remove_index + insert_length + tail_length; p_buffer[current_size] = value_type(0); cleanup(); @@ -2615,8 +2606,7 @@ namespace etl //************************************************************************* /// Compare helper function //************************************************************************* - static int compare(const_pointer first1, const_pointer last1, - const_pointer first2, const_pointer last2) + static int compare(const_pointer first1, const_pointer last1, const_pointer first2, const_pointer last2) { typedef typename etl::make_unsigned::type type; @@ -2649,7 +2639,7 @@ namespace etl // First string is shorter. return -1; } - + if (length1 > length2) { // First string is longer. @@ -2687,12 +2677,15 @@ namespace etl /// Destructor. //************************************************************************* #if defined(ETL_POLYMORPHIC_STRINGS) || defined(ETL_POLYMORPHIC_CONTAINERS) || defined(ETL_ISTRING_REPAIR_ENABLE) + public: + virtual #else + protected: #endif - ~ibasic_string() + ~ibasic_string() { #if ETL_HAS_STRING_CLEAR_AFTER_USE if (is_secure()) @@ -2728,7 +2721,9 @@ namespace etl //********************************************************************* template static - typename etl::enable_if::type>::value && sizeof(typename etl::remove_pointer::type>::type) == sizeof(value_type), iterator>::type + typename etl::enable_if< etl::is_pointer::type>::value + && sizeof(typename etl::remove_pointer< typename etl::remove_cvref::type>::type) == sizeof(value_type), + iterator>::type copy_characters(TIterator1 from, size_t n, iterator to) { etl::mem_move(from, n, to); @@ -2742,14 +2737,16 @@ namespace etl //********************************************************************* template static - typename etl::enable_if::type>::value && sizeof(typename etl::remove_pointer::type>::type) == sizeof(value_type)), iterator>::type + typename etl::enable_if< !(etl::is_pointer::type>::value + && sizeof(typename etl::remove_pointer< typename etl::remove_cvref::type>::type) == sizeof(value_type)), + iterator>::type copy_characters(TIterator1 from, size_t n, iterator to) { size_t count = 0; - while (count != n) + while (count != n) { - *to++ = *from++; + *to++ = static_cast(*from++); ++count; } @@ -2757,26 +2754,27 @@ namespace etl } //********************************************************************* - /// Common implementation for 'assign' and 'append' for non-pointer iterators. + /// Common implementation for 'assign' and 'append' for non-pointer + /// iterators. //********************************************************************* template - typename etl::enable_if::type>::value>::type - append_impl(iterator position, TIterator first, TIterator last, bool truncated, bool secure) + typename etl::enable_if< !etl::is_pointer< typename etl::remove_reference::type>::value>::type + append_impl(iterator position, TIterator first, TIterator last, bool truncated, bool secure) { difference_type start = etl::distance(p_buffer, position); difference_type count = etl::distance(first, last); difference_type free_space = etl::distance(position, p_buffer + CAPACITY); -#if ETL_IS_DEBUG_BUILD +#if ETL_IS_DEBUG_BUILD ETL_ASSERT(count >= 0, ETL_ERROR(string_iterator)); #endif - + #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated((count > free_space) || this->is_truncated() || truncated); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); -#endif + #endif #else (void)truncated; #endif @@ -2793,7 +2791,7 @@ namespace etl // Limit the actual distance to the capacity. count = etl::min(count, free_space); copy_characters(first, size_t(count), position); - current_size = size_t(start + count); + current_size = size_t(start + count); p_buffer[current_size] = 0; cleanup(); @@ -2828,14 +2826,14 @@ namespace etl etl::mem_move(src, count, position); - current_size = start + count; + current_size = start + count; p_buffer[current_size] = 0; #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated((length > free_space) || truncated); -#if ETL_HAS_ERROR_ON_STRING_TRUNCATION + #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); -#endif + #endif #else (void)truncated; #endif @@ -2856,8 +2854,8 @@ namespace etl /// Common implementation for 'assign' and 'append' for pointer iterators. //********************************************************************* template - typename etl::enable_if::type>::value>::type - append_impl(iterator position, TIterator first, TIterator last, bool truncated, bool secure) + typename etl::enable_if< etl::is_pointer< typename etl::remove_reference::type>::value>::type + append_impl(iterator position, TIterator first, TIterator last, bool truncated, bool secure) { append_impl(position, first, size_t(etl::distance(first, last)), truncated || is_truncated(), secure); } @@ -2881,7 +2879,7 @@ namespace etl } else { - return etl::distance(begin(), iposition); + return static_cast(etl::distance(begin(), iposition)); } } @@ -2903,7 +2901,7 @@ namespace etl pos = size() - pos; - const_reverse_iterator iposition = etl::search(rbegin() + pos, rend(), rfirst, rlast); + const_reverse_iterator iposition = etl::search(rbegin() + static_cast(pos), rend(), rfirst, rlast); if (iposition == rend()) { @@ -2911,7 +2909,7 @@ namespace etl } else { - return size() - sz - etl::distance(rbegin(), iposition); + return size() - sz - static_cast(etl::distance(rbegin(), iposition)); } } @@ -2919,9 +2917,7 @@ namespace etl /// get_string_length, optimised for sizeof(U) == sizeof(char). //********************************************************************* template - static - typename etl::enable_if::type - get_string_length(const U* str) + static typename etl::enable_if::type get_string_length(const U* str) { return ::strlen(reinterpret_cast(str)); } @@ -2931,9 +2927,7 @@ namespace etl /// get_string_length, optimised for sizeof(U) == sizeof(wchar_t). //********************************************************************* template - static - typename etl::enable_if::type - get_string_length(const U* str) + static typename etl::enable_if::type get_string_length(const U* str) { return ::wcslen(reinterpret_cast(str)); } @@ -2945,9 +2939,9 @@ namespace etl template static #if ETL_USING_LIBC_WCHAR_H - typename etl::enable_if<(sizeof(U) != sizeof(char)) && (sizeof(U) != sizeof(wchar_t)), size_t>::type + typename etl::enable_if<(sizeof(U) != sizeof(char)) && (sizeof(U) != sizeof(wchar_t)), size_t>::type #else - typename etl::enable_if<(sizeof(U) != sizeof(char)), size_t>::type + typename etl::enable_if<(sizeof(U) != sizeof(char)), size_t>::type #endif get_string_length(const U* str) { @@ -2975,7 +2969,7 @@ namespace etl ///\ingroup string //*************************************************************************** template - bool operator ==(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + bool operator==(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) { return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin()); } @@ -2988,7 +2982,7 @@ namespace etl ///\ingroup string //*************************************************************************** template - bool operator ==(const etl::ibasic_string& lhs, const T* rhs) + bool operator==(const etl::ibasic_string& lhs, const T* rhs) { return (lhs.size() == etl::strlen(rhs)) && etl::equal(lhs.begin(), lhs.end(), rhs); } @@ -3001,7 +2995,7 @@ namespace etl ///\ingroup string //*************************************************************************** template - bool operator ==(const T* lhs, const etl::ibasic_string& rhs) + bool operator==(const T* lhs, const etl::ibasic_string& rhs) { return (rhs.size() == etl::strlen(lhs)) && etl::equal(rhs.begin(), rhs.end(), lhs); } @@ -3014,7 +3008,7 @@ namespace etl ///\ingroup string //*************************************************************************** template - bool operator !=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + bool operator!=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) { return !(lhs == rhs); } @@ -3027,7 +3021,7 @@ namespace etl ///\ingroup string //*************************************************************************** template - bool operator !=(const etl::ibasic_string& lhs, const T* rhs) + bool operator!=(const etl::ibasic_string& lhs, const T* rhs) { return !(lhs == rhs); } @@ -3040,7 +3034,7 @@ namespace etl ///\ingroup string //*************************************************************************** template - bool operator !=(const T* lhs, const etl::ibasic_string& rhs) + bool operator!=(const T* lhs, const etl::ibasic_string& rhs) { return !(lhs == rhs); } @@ -3049,11 +3043,11 @@ namespace etl /// Less than operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically less than the + /// second, otherwise false \ingroup string //*************************************************************************** template - bool operator <(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + bool operator<(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) { return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } @@ -3062,11 +3056,11 @@ namespace etl /// Less than operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically less than the + /// second, otherwise false \ingroup string //*************************************************************************** template - bool operator <(const etl::ibasic_string& lhs, const T* rhs) + bool operator<(const etl::ibasic_string& lhs, const T* rhs) { return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs, rhs + etl::strlen(rhs)); } @@ -3075,25 +3069,24 @@ namespace etl /// Less than operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically less than the + /// second, otherwise false \ingroup string //*************************************************************************** template - bool operator <(const T* lhs, const etl::ibasic_string& rhs) + bool operator<(const T* lhs, const etl::ibasic_string& rhs) { return etl::lexicographical_compare(lhs, lhs + etl::strlen(lhs), rhs.begin(), rhs.end()); } - //*************************************************************************** /// Greater than operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically greater than + /// the second, otherwise false \ingroup string //*************************************************************************** template - bool operator >(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + bool operator>(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) { return (rhs < lhs); } @@ -3102,11 +3095,11 @@ namespace etl /// Greater than operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically greater than + /// the second, otherwise false \ingroup string //*************************************************************************** template - bool operator >(const etl::ibasic_string& lhs, const T* rhs) + bool operator>(const etl::ibasic_string& lhs, const T* rhs) { return (rhs < lhs); } @@ -3115,25 +3108,25 @@ namespace etl /// Greater than operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically greater than + /// the second, otherwise false \ingroup string //*************************************************************************** template - bool operator >(const T* lhs, const etl::ibasic_string& rhs) + bool operator>(const T* lhs, const etl::ibasic_string& rhs) { return (rhs < lhs); } - //*************************************************************************** /// Less than or equal operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than or equal to the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically less than or + /// equal to the second, otherwise + ///< b>false \ingroup string //*************************************************************************** template - bool operator <=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + bool operator<=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) { return !(lhs > rhs); } @@ -3142,11 +3135,12 @@ namespace etl /// Less than or equal operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than or equal to the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically less than or + /// equal to the second, otherwise + ///< b>false \ingroup string //*************************************************************************** template - bool operator <=(const etl::ibasic_string& lhs, const T* rhs) + bool operator<=(const etl::ibasic_string& lhs, const T* rhs) { return !(lhs > rhs); } @@ -3155,25 +3149,26 @@ namespace etl /// Less than or equal operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than or equal to the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically less than or + /// equal to the second, otherwise + ///< b>false \ingroup string //*************************************************************************** template - bool operator <=(const T* lhs, const etl::ibasic_string& rhs) + bool operator<=(const T* lhs, const etl::ibasic_string& rhs) { return !(lhs > rhs); } - //*************************************************************************** /// Greater than or equal operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than or equal to the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically greater than + /// or equal to the second, otherwise + ///< b>false \ingroup string //*************************************************************************** template - bool operator >=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + bool operator>=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) { return !(lhs < rhs); } @@ -3182,11 +3177,12 @@ namespace etl /// Greater than or equal operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than or equal to the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically greater than + /// or equal to the second, otherwise + ///< b>false \ingroup string //*************************************************************************** template - bool operator >=(const etl::ibasic_string& lhs, const T* rhs) + bool operator>=(const etl::ibasic_string& lhs, const T* rhs) { return !(lhs < rhs); } @@ -3195,11 +3191,12 @@ namespace etl /// Greater than or equal operator. ///\param lhs Reference to the first string. ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than or equal to the second, otherwise false - ///\ingroup string + ///\return true if the first string is lexicographically greater than + /// or equal to the second, otherwise + ///< b>false \ingroup string //*************************************************************************** template - bool operator >=(const T* lhs, const etl::ibasic_string& rhs) + bool operator>=(const T* lhs, const etl::ibasic_string& rhs) { return !(lhs < rhs); } @@ -3213,14 +3210,13 @@ namespace etl //*************************************************************************** #if ETL_USING_STD_OSTREAM template - std::basic_ostream > &operator<<(std::basic_ostream > &os, - const etl::ibasic_string& str) + std::basic_ostream >& operator<<(std::basic_ostream >& os, const etl::ibasic_string& str) { - os.write(str.data(), str.size()); + os.write(str.data(), static_cast(str.size())); return os; } #endif -} +} // namespace etl #undef ETL_USING_WCHAR_T_H diff --git a/include/etl/basic_string_stream.h b/include/etl/basic_string_stream.h index 2aa1f28d..b8e1038b 100644 --- a/include/etl/basic_string_stream.h +++ b/include/etl/basic_string_stream.h @@ -35,9 +35,9 @@ SOFTWARE. #include "platform.h" #include "to_string.h" -#include "to_u8string.h" #include "to_u16string.h" #include "to_u32string.h" +#include "to_u8string.h" #include "to_wstring.h" namespace etl @@ -125,16 +125,17 @@ namespace etl //********************************* /// TFormat //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, const TFormat& fmt) + friend basic_string_stream& operator<<(basic_string_stream& ss, const TFormat& fmt) { ss.format = fmt; return ss; } //********************************* - /// etl::base_spec from etl::setbase, etl::bin, etl::oct, etl::dec & etl::hex stream manipulators + /// etl::base_spec from etl::setbase, etl::bin, etl::oct, etl::dec & + /// etl::hex stream manipulators //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::base_spec fmt) + friend basic_string_stream& operator<<(basic_string_stream& ss, etl::private_basic_format_spec::base_spec fmt) { ss.format.base(fmt.base); return ss; @@ -143,7 +144,7 @@ namespace etl //********************************* /// etl::width_spec from etl::setw stream manipulator //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::width_spec fmt) + friend basic_string_stream& operator<<(basic_string_stream& ss, etl::private_basic_format_spec::width_spec fmt) { ss.format.width(fmt.width); return ss; @@ -153,7 +154,7 @@ namespace etl /// etl::fill_spec from etl::setfill stream manipulator //********************************* template - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::fill_spec fmt) + friend basic_string_stream& operator<<(basic_string_stream& ss, etl::private_basic_format_spec::fill_spec fmt) { ss.format.fill(fmt.fill); return ss; @@ -162,34 +163,37 @@ namespace etl //********************************* /// etl::precision_spec from etl::setprecision stream manipulator //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::precision_spec fmt) + friend basic_string_stream& operator<<(basic_string_stream& ss, etl::private_basic_format_spec::precision_spec fmt) { ss.format.precision(fmt.precision); return ss; } //********************************* - /// etl::boolalpha_spec from etl::boolalpha & etl::noboolalpha stream manipulators + /// etl::boolalpha_spec from etl::boolalpha & etl::noboolalpha stream + /// manipulators //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::boolalpha_spec fmt) + friend basic_string_stream& operator<<(basic_string_stream& ss, etl::private_basic_format_spec::boolalpha_spec fmt) { ss.format.boolalpha(fmt.boolalpha); return ss; } //********************************* - /// etl::uppercase_spec from etl::uppercase & etl::nouppercase stream manipulators + /// etl::uppercase_spec from etl::uppercase & etl::nouppercase stream + /// manipulators //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::uppercase_spec fmt) + friend basic_string_stream& operator<<(basic_string_stream& ss, etl::private_basic_format_spec::uppercase_spec fmt) { ss.format.upper_case(fmt.upper_case); return ss; } //********************************* - /// etl::showbase_spec from etl::showbase & etl::noshowbase stream manipulators + /// etl::showbase_spec from etl::showbase & etl::noshowbase stream + /// manipulators //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::showbase_spec fmt) + friend basic_string_stream& operator<<(basic_string_stream& ss, etl::private_basic_format_spec::showbase_spec fmt) { ss.format.show_base(fmt.show_base); return ss; @@ -198,7 +202,7 @@ namespace etl //********************************* /// etl::left_spec from etl::left stream manipulator //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::left_spec /*fmt*/) + friend basic_string_stream& operator<<(basic_string_stream& ss, etl::private_basic_format_spec::left_spec /*fmt*/) { ss.format.left(); return ss; @@ -207,7 +211,7 @@ namespace etl //********************************* /// etl::right_spec from etl::left stream manipulator //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::right_spec /*fmt*/) + friend basic_string_stream& operator<<(basic_string_stream& ss, etl::private_basic_format_spec::right_spec /*fmt*/) { ss.format.right(); return ss; @@ -216,7 +220,7 @@ namespace etl //********************************* /// From a string view //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, TStringView view) + friend basic_string_stream& operator<<(basic_string_stream& ss, TStringView view) { etl::to_string(view, ss.text, ss.format, true); return ss; @@ -225,7 +229,7 @@ namespace etl //********************************* /// From a character pointer to a string //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, pointer p) + friend basic_string_stream& operator<<(basic_string_stream& ss, pointer p) { TStringView view(p); ss << view; @@ -235,7 +239,7 @@ namespace etl //********************************* /// From a const character pointer to a string //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, const_pointer p) + friend basic_string_stream& operator<<(basic_string_stream& ss, const_pointer p) { TStringView view(p); ss << view; @@ -245,7 +249,7 @@ namespace etl //********************************* /// From a string interface //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, const TIString& t) + friend basic_string_stream& operator<<(basic_string_stream& ss, const TIString& t) { etl::to_string(t, ss.text, ss.format, true); return ss; @@ -255,7 +259,7 @@ namespace etl /// From a string //********************************* template