.. _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