.. _architecture_portable: Portable module =============== .. raw:: html .. raw:: html :file: ../figures/svg_href_loader.html .. raw:: html :file: ../figures/stack_diagram.svg .. include:: ../safety_manual/rules/RULE_PORTABLE_MODULE_OVERRIDING.inc Safe DDS' portable module provides a unique point of access to the complete set of Safe DDS' :ref:`dependencies `. Following this approach, the dependency of Safe DDS on the C++ standard library is both limited and encapsulated. To facilitate customization, it is possible to override the contents of the ``include/portable`` folder, allowing for modifications or replacements of any headers found within this directory. This strategy enables the utilization of a custom C++ standard library, or even a tailored implementation to suit specific requirements. The list of dependencies that can be overwritten or customized in Safe DDS are: ``portable/BitConstants.hpp`` ----------------------------- By default it is implemented assuming a 32-bit architecture. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``BITS_IN_LONG`` - Number of bits in a long - ``32`` * - ``BITS_IN_BYTE`` - Number of bits in a byte - ``8`` * - ``SHIFT_DIVISION_32`` - Shift division by 32 - ``5`` * - ``SHIFT_24`` - Shift by 24 bits - ``24`` * - ``SHIFT_16`` - Shift by 16 bits - ``16`` * - ``SHIFT_8`` - Shift by 8 bits - ``8`` * - ``MASK_24_TO_32`` - Mask selecting bits 24th to 31st - ``0xFF000000`` * - ``MASK_16_TO_24`` - Mask selecting bits 16th to 23rd - ``0x00FF0000`` * - ``MASK_8_TO_16`` - Mask selecting bits 8th to 15th - ``0x0000FF00`` * - ``MASK_0_TO_8`` - Mask selecting bits 0th to 7th - ``0x000000FF`` ``portable/CLZ.hpp`` -------------------- An implementation of the counting leading zeros function. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``clz`` - Count leading zeros - ``__builtin_clz`` ``portable/Endianness.hpp`` --------------------------- Endianness related definitions. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``MACHINE_ENDIANNESS`` - Machine endianness as ``portable::Endianness`` - Using ``__BYTE_ORDER__`` and ``__ORDER_BIG_ENDIAN__`` ``portable/TypeTraits.hpp`` --------------------------- Dependencies with type traits to check type structure and/or serialization possibilities using memory copy. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``IsStandardLayout`` - Check if a type is standard layout - ``std::is_standard_layout`` * - ``IsSerializableByCopy`` - Check if a type is serializable by copy - Using ``IsStandardLayout`` and ``safe_sizeof`` ``portable/MD5.hpp`` -------------------- An implementation of the MD5 hash algorithm. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``MD5`` - MD5 hash algorithm - By default it is implemented as defined in `portable::MD5 <../doxygen/classeprosima_1_1safedds_1_1portable_1_1_m_d5.html>`__. ``portable/New.hpp`` -------------------- A ``safe_new`` function to construct objects dynamically. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``safe_new`` - Safe new in-place operator - Using placement new operator ``portable/StdInt.hpp`` ----------------------- Definition of common types and type bounds. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``int[N]_t`` and ``uint[N]_t`` - Signed and unsigned integer types - ``std::int[N]_t`` and ``std::uint[N]_t`` * - ``INT[N]_MIN``, ``INT[N]_MAX`` and ``UINT[N]_MAX`` - Minimum and maximum values for integer types - ``std::INT[N]_MIN``, ``std::INT[N]_MAX`` and ``std::UINT[N]_MAX`` * - ``__BYTE_ORDER__`` - Byte order - ``__BYTE_ORDER__`` * - ``__ORDER_BIG_ENDIAN__`` - Big endian order - ``__ORDER_BIG_ENDIAN__`` * - ``uintptr_t`` - Unsigned integer type capable of holding a pointer - ``std::uintptr_t`` ``portable/String.hpp`` ----------------------- Definition of C standard library functions. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``safe_memcmp`` - Compare memory - ``memcmp`` * - ``safe_memcpy`` - Copy memory - ``memcpy`` * - ``safe_memcpy_reverse`` - Copy memory in reverse - Custom implementation * - ``safe_memset`` - Set memory - ``memset`` * - ``safe_memclear`` - Clear memory - ``safe_memset`` * - ``safe_memmove`` - Move memory - ``memmove`` ``portable/Logger.hpp`` ----------------------- Definition of the ``portable::Logger`` class and logging macros. For more information see :ref:`portable_logging`. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``SAFEDDS_LOG_DEBUG``, ``SAFEDDS_LOG_INFO``, ``SAFEDDS_LOG_WARNING`` and ``SAFEDDS_LOG_ERROR`` - Logging macros - ``vprintf``-based implementation ``portable/SafeCasts.hpp`` -------------------------- Definition of safe casting functions and utilities. .. list-table:: :header-rows: 1 * - Needs to provide - Description - Default value * - ``safe_offsetof`` - Offset (in bytes) of a member returned as an ``uint32_t`` - Using ``offsetof`` .. _portable_override_portable: .. _architecture_portable_overrides: Override portable module ------------------------ Overriding the contents of the ``include/portable`` folder is done by providing a custom include directory. To illustrate this process, consider the example of overriding the usage of the builtin ``__builtin_clz()`` in the default implementation of ``portable::clz()``. This can be accomplished by rewriting the file ``include/portable/CLZ.hpp`` as ``include_overrides/safedds/portable/CLZ.hpp`` and subsequently incorporating it into the :ref:`toolchain ` as follows: .. literalinclude:: ../code/cortex_m3_crosscompilation/toolchain.cmake :language: cmake :start-after: # OVERRIDE_STL_TOOLCHAIN_CMAKE_EXAMPLE :end-before: #! OVERRIDE_STL_TOOLCHAIN_CMAKE_EXAMPLE .. _portable_logging: Logging module -------------- Safe DDS provides a logging mechanism based on a set of macros. The logging macros shall be defined in ``include/portable/Logger.hpp`` and are used throughout the codebase. For reference, the following macros are defined: * ``SAFEDDS_LOG_DEBUG``: Debug level logging. * ``SAFEDDS_LOG_INFO``: Information level logging. * ``SAFEDDS_LOG_WARNING``: Warning level logging. * ``SAFEDDS_LOG_ERROR``: Error level logging. A ``portable::BaseLogger`` class is provided to ease formatting of log messages. This class provides a set of implemented ``operator<<`` functions for Safe DDS types and exposes a virtual ``void logger_print(const char *msg, ...)`` function that shall be overwritten to provide an endpoint for logging strings. By default, the ``portable::Logger`` class is implemented using ```` to print messages to the standard output. An example of a custom logger as the following one can be injected into the library by means of :ref:`overriding the portable module `: .. literalinclude:: ../code/architecture_reference/main.cpp :language: c++ :start-after: // REFERENCE_LOGGER_IMPLEMENTATION :end-before: //! REFERENCE_LOGGER_IMPLEMENTATION :dedent: 0