Portable module¶
Safe DDS’ portable module provides a unique point of access to the complete set of Safe DDS’ 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.
Needs to provide |
Description |
Default value |
|---|---|---|
|
Number of bits in a long |
|
|
Number of bits in a byte |
|
|
Shift division by 32 |
|
|
Shift by 24 bits |
|
|
Shift by 16 bits |
|
|
Shift by 8 bits |
|
|
Mask selecting bits 24th to 31st |
|
|
Mask selecting bits 16th to 23rd |
|
|
Mask selecting bits 8th to 15th |
|
|
Mask selecting bits 0th to 7th |
|
portable/CLZ.hpp¶
An implementation of the counting leading zeros function.
Needs to provide |
Description |
Default value |
|---|---|---|
|
Count leading zeros |
|
portable/Endianness.hpp¶
Endianness related definitions.
Needs to provide |
Description |
Default value |
|---|---|---|
|
Machine endianness as |
Using |
portable/TypeTraits.hpp¶
Dependencies with type traits to check type structure and/or serialization possibilities using memory copy.
Needs to provide |
Description |
Default value |
|---|---|---|
|
Check if a type is standard layout |
|
|
Check if a type is serializable by copy |
Using |
portable/MD5.hpp¶
An implementation of the MD5 hash algorithm.
Needs to provide |
Description |
Default value |
|---|---|---|
|
MD5 hash algorithm |
By default it is implemented as defined in portable::MD5. |
portable/New.hpp¶
A safe_new function to construct objects dynamically.
Needs to provide |
Description |
Default value |
|---|---|---|
|
Safe new in-place operator |
Using placement new operator |
portable/StdInt.hpp¶
Definition of common types and type bounds.
Needs to provide |
Description |
Default value |
|---|---|---|
|
Signed and unsigned integer types |
|
|
Minimum and maximum values for integer types |
|
|
Byte order |
|
|
Big endian order |
|
|
Unsigned integer type capable of holding a pointer |
|
portable/String.hpp¶
Definition of C standard library functions.
Needs to provide |
Description |
Default value |
|---|---|---|
|
Compare memory |
|
|
Copy memory |
|
|
Copy memory in reverse |
Custom implementation |
|
Set memory |
|
|
Clear memory |
|
|
Move memory |
|
portable/Logger.hpp¶
Definition of the portable::Logger class and logging macros.
For more information see Logging module.
Needs to provide |
Description |
Default value |
|---|---|---|
|
Logging macros |
|
portable/SafeCasts.hpp¶
Definition of safe casting functions and utilities.
Needs to provide |
Description |
Default value |
|---|---|---|
|
Offset (in bytes) of a member returned as an |
Using |
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 toolchain as follows:
# Add the custom include folder to override library headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include_overrides)
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 <cstdio> 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 overriding the portable module:
#include <safedds/portable/BaseLogger.hpp>
class CustomLogger :
public portable::BaseLogger
{
CustomLogger(
portable::LogLevel level)
: portable::BaseLogger(level)
{
}
//! BaseLogger implementation.
void logger_print(
const char* format,
...) noexcept override
{
// Will print info, warning and error messages in screen
// and store debug messages in a file
va_list args;
va_start(args, format);
if (level_ == portable::LogLevel::DEBUG)
{
char buffer[1000];
vsprintf(buffer, format, args);
save_in_file("debug.log", buffer);
}
else
{
vprintf(format, args);
}
va_end(args);
}
};
//! Log macro info.
#define SAFEDDS_LOG_INFO(message) \
CustomLogger(portable::LogLevel::INFO) << message;
//! Log macro warning.
#define SAFEDDS_LOG_WARNING(message) \
CustomLogger(portable::LogLevel::WARNING) << message;
//! Log macro error.
#define SAFEDDS_LOG_ERROR(message) \
CustomLogger(portable::LogLevel::ERROR) << message;
//! Log macro debug.
#define SAFEDDS_LOG_DEBUG(message) \
CustomLogger(portable::LogLevel::DEBUG) << message;