mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-02-05 15:18:45 +00:00
181
export/interfaces/app.idl
Normal file
181
export/interfaces/app.idl
Normal file
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* @file app.idl
|
||||
* @brief This file provides the core interface definitions SDV framework administration.
|
||||
* @version 0.1
|
||||
* @date 2024.04.11
|
||||
* @author erik.verhoeven@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2023-2025
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
#include "toml.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module app
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The application operation state.
|
||||
*/
|
||||
enum EAppOperationState
|
||||
{
|
||||
not_started = 0, ///< The application hasn't been started yet.
|
||||
starting = 1, ///< The application is starting.
|
||||
started = 2, ///< The application has started.
|
||||
initializing = 10, ///< The application is initializing.
|
||||
initialized = 12, ///< The application has initialized.
|
||||
configuring = 20, ///< The application switched to configuration mode.
|
||||
running = 30, ///< The application is running/switched to running mode.
|
||||
shutting_down = 90, ///< The application is shutting down.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Event structure. Dependable on the event, can be derived to provide additional information.
|
||||
*/
|
||||
struct SAppEvent
|
||||
{
|
||||
uint32 uiEventID; ///< The event ID of the event
|
||||
uint32 uiInfo; ///< Additional information that can be used during a call to the event and as answer from
|
||||
///< the implemented event handler. The information depends on the event that is triggered.
|
||||
};
|
||||
|
||||
const uint32 EVENT_OPERATION_STATE_CHANGED = 1; ///< Information about the application operation state. The information
|
||||
///< section of the event structure contains the current operation mode
|
||||
///< represented by the EAppOperationMode enum. This event is
|
||||
///< informational only and will be called by the core library to
|
||||
///< inform the application.
|
||||
|
||||
const uint32 EVENT_RUNNING_LOOP = 8; ///< Triggered every 2ms to do idle operations during the running loop.
|
||||
|
||||
/**
|
||||
* @brief Application event system. To be implemented by the application.
|
||||
*/
|
||||
local interface IAppEvent
|
||||
{
|
||||
/**
|
||||
* @brief Process the event.
|
||||
* @param[inout] sEvent Event structure containing the information to process.
|
||||
*/
|
||||
void ProcessEvent(inout SAppEvent sEvent);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Application context types.
|
||||
*/
|
||||
enum EAppContext : uint32
|
||||
{
|
||||
no_context = 0, ///< The core hasn't started yet. No context available.
|
||||
standalone = 10, ///< Running as standalone application. No component isolation instantiated. Additional
|
||||
///< configurations can be loaded.
|
||||
external = 20, ///< External application. Component isolation in client mode.
|
||||
isolated = 30, ///< Isolated application. Component isolation in client mode.
|
||||
main = 100, ///< Main application. Component isolation in server mode.
|
||||
essential = 5, ///< Bare minunum configuration. Local services loaded only. Additional configurations can be
|
||||
///< loaded.
|
||||
maintenance = 80, ///< Maintenance application. Component isolation in client mode. Access to maintenance interfaces
|
||||
///< only.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Application context interface.
|
||||
*/
|
||||
local interface IAppContext
|
||||
{
|
||||
/**
|
||||
* @brief Return the application context.
|
||||
* @return The context mode.
|
||||
*/
|
||||
EAppContext GetContextType() const;
|
||||
|
||||
/**
|
||||
* @brief Return the core instance ID.
|
||||
* @return The instance ID.
|
||||
*/
|
||||
uint32 GetInstanceID() const;
|
||||
|
||||
/**
|
||||
* @brief Return the number of retries to establish a connection.
|
||||
* @return Number of retries.
|
||||
*/
|
||||
uint32 GetRetries() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Local application control.
|
||||
*/
|
||||
local interface IAppControl
|
||||
{
|
||||
/**
|
||||
* @brief Start the application.
|
||||
* @details The core will prepare for an application start based on the provided configuration. Per default, the
|
||||
* application will be in running mode after successful startup.
|
||||
* @param[in] ssConfig String containing the configuration to be used by the core during startup. This configuration
|
||||
* is optional. If not provided the application runs as standalone application without any RPC support.
|
||||
* @param[in] pEventHandler Pointer to the event handler receiving application events. For the handler to receive
|
||||
* events, the handler needs to expose the IAppEvent interface. This pointer is optionally and can be NULL.
|
||||
* @return Returns 'true' on successful start-up and 'false' on failed startup.
|
||||
*/
|
||||
boolean Startup(in u8string ssConfig, in IInterfaceAccess pEventHandler)
|
||||
raises(XAccessDenied, toml::XTOMLParseException);
|
||||
|
||||
/**
|
||||
* @brief Running loop until shutdown request is triggered.
|
||||
*/
|
||||
void RunLoop() raises(XAccessDenied, XInvalidState);
|
||||
|
||||
/**
|
||||
* @brief Initiate a shutdown of the application.
|
||||
* @details The objects will be called to shutdown allowing them to clean up and gracefully shutdown. If, for some
|
||||
* reason, the object cannot shut down (e.g. pointers are still in use or threads are not finalized), the object will
|
||||
* be kept alive and the application state will stay in shutting-down-state. In that case the exception is called. A
|
||||
* new call to the shutdown function using the force-flag might force a shutdown. Alternatively the application can
|
||||
* wait until the application state changes to not-started.
|
||||
* @remarks Application shutdown is only possible when all components are released.
|
||||
* @param[in] bForce When set, forces an application shutdown. This might result in loss of data and should only be
|
||||
* used as a last resort.
|
||||
*/
|
||||
void Shutdown(in boolean bForce) raises(XAccessDenied, XInvalidState, XTimeout);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Application operation control.
|
||||
*/
|
||||
interface IAppOperation
|
||||
{
|
||||
/**
|
||||
* @brief Get the current operation state. This information is also supplied through the event handler function.
|
||||
* @return Returns the operation state of the application.
|
||||
*/
|
||||
EAppOperationState GetOperationState() const;
|
||||
|
||||
/**
|
||||
* @brief Switch from running mode to the configuration mode.
|
||||
*/
|
||||
void SetConfigMode() raises(XAccessDenied, XInvalidState);
|
||||
|
||||
/**
|
||||
* @brief Switch from the configuration mode to the running mode.
|
||||
*/
|
||||
void SetRunningMode() raises(XAccessDenied, XInvalidState);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Request a shutdown (only for server).
|
||||
*/
|
||||
interface IAppShutdownRequest
|
||||
{
|
||||
/**
|
||||
* @brief Request a shutdown. The function will only place the request to shut down.
|
||||
*/
|
||||
void RequestShutdown() raises(XAccessDenied, XInvalidState);
|
||||
};
|
||||
|
||||
}; // module app
|
||||
}; // module sdv
|
||||
120
export/interfaces/can.idl
Normal file
120
export/interfaces/can.idl
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @file can.idl
|
||||
* @author Erik Verhoeven FRD DISS2 (mailto:erik.verhoeven@zf.com)
|
||||
* @brief This file provides the CAN abstraction interfaces
|
||||
* @version 1.0
|
||||
* @date 2024-02-07
|
||||
*
|
||||
* @copyright Copyright ZF Friedrichshafen AG (c) 2024
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief CAN abstraction interface.
|
||||
*/
|
||||
module can
|
||||
{
|
||||
/**
|
||||
* @brief CAN message structure
|
||||
*/
|
||||
struct SMessage
|
||||
{
|
||||
uint32 uiID; ///< CAN ID
|
||||
boolean bExtended; ///< When set, the message ID is extended.
|
||||
boolean bCanFd; ///< When set, the message is of CAN-FD.
|
||||
sequence<uint8> seqData; ///< The data for this message (max. 8 bytes for standard CAN and 64 bytes for CAN-FD).
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Error enum
|
||||
*/
|
||||
enum EError : uint32
|
||||
{
|
||||
no_error = 0, ///< No error
|
||||
bit_error = 1, ///< When the bit received is not the same as the bit transmitted.
|
||||
stuff_error = 2, ///< If more than five consecutive bits of the same level occur on the bus.
|
||||
form_error = 3, ///< Violation of fixed bit format.
|
||||
crc_error = 4, ///< If the received CRC does not match with the calculated code.
|
||||
ack_error = 5, ///< The transmitter does not receive a dominant acknowledgement bit in reply.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief CAN error frame structure
|
||||
*/
|
||||
struct SErrorFrame
|
||||
{
|
||||
uint32 uiID; ///< CAN ID; could be 0 when the error is not referring to a specific ID.
|
||||
EError eError; ///< The error.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to receive CAN messages; callback interface.
|
||||
*/
|
||||
local interface IReceive
|
||||
{
|
||||
/**
|
||||
* @brief Process a receive a CAN message.
|
||||
* @param[in] sMsg Message that was received.
|
||||
* @param[in] uiIfcIndex Interface index of the received message.
|
||||
*/
|
||||
void Receive(in SMessage sMsg, in uint32 uiIfcIndex);
|
||||
|
||||
/**
|
||||
* @brief Process an error frame.
|
||||
* @param[in] sError Error frame that was received.
|
||||
* @param[in] uiIfcIndex Interface index of the received message.
|
||||
*/
|
||||
void Error(in SErrorFrame sError, in uint32 uiIfcIndex);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to register the CAN receiver.
|
||||
*/
|
||||
local interface IRegisterReceiver
|
||||
{
|
||||
/**
|
||||
* @brief Register a CAN message receiver.
|
||||
* @param[in] pReceiver Pointer to the receiver interface.
|
||||
*/
|
||||
void RegisterReceiver(in IReceive pReceiver);
|
||||
|
||||
/**
|
||||
* @brief Unregister a previously registered CAN message receiver.
|
||||
* @param[in] pReceiver Pointer to the receiver interface.
|
||||
*/
|
||||
void UnregisterReceiver(in IReceive pReceiver);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to send CAN messagee.
|
||||
*/
|
||||
local interface ISend
|
||||
{
|
||||
/**
|
||||
* @brief Send a CAN message.
|
||||
* @param[in] sMsg Message that is to be sent.
|
||||
* @param[in] uiIfcIndex Interface index to use for sending.
|
||||
*/
|
||||
void Send(in SMessage sMsg, in uint32 uiIfcIndex);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to request the available interfaces and nodes.
|
||||
*/
|
||||
local interface IInformation
|
||||
{
|
||||
/**
|
||||
* @brief Get a list of interface names.
|
||||
* @return Sequence containing the names of the interfaces.
|
||||
*/
|
||||
sequence<u8string> GetInterfaces() const;
|
||||
};
|
||||
};
|
||||
};
|
||||
172
export/interfaces/com.idl
Normal file
172
export/interfaces/com.idl
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @file com.idl
|
||||
* @author Erik Verhoeven FRD DISDS1 (mailto:erik.verhoeven@zf.com) & Steffen Altmeier FRD DISS21 (mailto:steffen.altmeier@zf.com)
|
||||
* @brief This file includes all the interfaces used by the communication control service
|
||||
* @version 1.0
|
||||
* @date 2024-08-12
|
||||
*
|
||||
* @copyright Copyright ZF Friedrichshafen AG (c) 2024
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
#include "core_ps.idl"
|
||||
#include "process.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module com
|
||||
{
|
||||
/**
|
||||
* @brief Connection ID used for connection identification
|
||||
*/
|
||||
struct SConnectionID
|
||||
{
|
||||
uint32 uiIdent; ///< Identification value.
|
||||
uint32 uiControl; ///< Control value for 2nd pass identification.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Channel connection ID.
|
||||
*/
|
||||
typedef SConnectionID TConnectionID;
|
||||
|
||||
/**
|
||||
* @brief Request a channel to connect to the core application.
|
||||
*/
|
||||
interface IRequestChannel
|
||||
{
|
||||
/**
|
||||
* @brief Request a channel.
|
||||
* @param[in] ssConfig Configuration; currently not used.
|
||||
* @return The channel string needed to initialize the channel.
|
||||
*/
|
||||
u8string RequestChannel(in u8string ssConfig);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Connect to a remote system. Provided by the ConnectClient utility.
|
||||
*/
|
||||
interface IClientConnect
|
||||
{
|
||||
/**
|
||||
* @brief Connect to a remote system using the connection string to contact the system.
|
||||
* @remarks After a successful connection, the ConnectClient utility is not needed any more.
|
||||
* @param[in] ssConnectString Optional connection string to use for connection. If not provided, the connection will
|
||||
* automatically get the connection ID from the app-control service (default). The connection string for a local
|
||||
* connection can be of the form:
|
||||
* @code
|
||||
* [Client]
|
||||
* Type = "local"
|
||||
* Instance = 1234 # Optional: only use when connecting to a system with a different instance ID.
|
||||
* @endcode
|
||||
* And the following can be used for a remote connection:
|
||||
* @code
|
||||
* [Client]
|
||||
* Type = "remote"
|
||||
* Interface = "127.0.0.1"
|
||||
* Port = 2000
|
||||
* @endcode
|
||||
* @return Returns an interface to the repository of the remote system or a NULL pointer if not found.
|
||||
*/
|
||||
IInterfaceAccess Connect(in u8string ssConnectString) raises(XAccessDenied, XNotFound, XInvalidState, XTimeout);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Channel type
|
||||
*/
|
||||
enum EChannelType : uint32
|
||||
{
|
||||
local_channel = 0, ///< Local channel
|
||||
remote_channel = 1, ///< Remote channel
|
||||
custom_channel = 2, ///< Custom channel (not specifically defined as standard local or remote).
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface for creating a channel connection used for SDV communication.
|
||||
* @details The channel control interface is used to create a connection between two processes and start the initial
|
||||
* communication. The provided object will be accessible as initial object through the channel.
|
||||
* Using these interfaces the following connections can be made:
|
||||
* 1. The main application provides an endpoint with a channel to its repository and the isolated or external application
|
||||
* links its own repository to the repository of the main application.
|
||||
* 2. The main application provides a listener endpoint (IPC channel is configured as listener and assigned to the
|
||||
* channel control) with an object to create a new private connection. Connecting applications can then connect to the
|
||||
* main applications and after the initial connection create a private communication.
|
||||
* 3. The isolated application provides an object to create a private communication to another isolated or external
|
||||
* application
|
||||
*/
|
||||
local interface IConnectionControl
|
||||
{
|
||||
/**
|
||||
* @brief Create an IPC channel endpoint and use it for SDV communication.
|
||||
* @remarks The channel will be destroyed automatically when a timeout occurs (no initial connection took place within
|
||||
* the specified time).
|
||||
* @remarks The function doesn't wait until a connection has been made, but returns straight after the channel creation.
|
||||
* @param[in] eChannelType Type of channel to create. Must be local or remote.
|
||||
* @param[in] pObject Initial object to start the communication with.
|
||||
* @param[in] uiTimeoutMs Timeout for waiting for a connection.
|
||||
* @param[out] ssConnectionString String describing the connection details to connect to this channel.
|
||||
* @return Channel connection ID if successful or 0 if not.
|
||||
*/
|
||||
TConnectionID CreateServerConnection(in EChannelType eChannelType, in IInterfaceAccess pObject, in uint32 uiTimeoutMs,
|
||||
out u8string ssConnectionString);
|
||||
|
||||
/**
|
||||
* @brief Connect to an IPC channel managed by the channel control.
|
||||
* @remarks The connection will be destroyed automatically when a timeout occurs (no initial connection took place
|
||||
* within the specified time).
|
||||
* @param[in] ssConnectionString The string describing the connection details.
|
||||
* @param[in] uiTimeoutMs Timeout for waiting for a connection.
|
||||
* @param[out] pProxy Pointer to the object representing the remote object (a proxy to the remote object). Or nullptr
|
||||
* when a timeout occurred.
|
||||
* @return Channel connection ID if successful or 0 if not.
|
||||
*/
|
||||
TConnectionID CreateClientConnection(in u8string ssConnectionString, in uint32 uiTimeoutMs, out IInterfaceAccess pProxy);
|
||||
|
||||
/**
|
||||
* @brief Assign and take over an already initialized IPC channel server endpoint for use with SDV communication.
|
||||
* @remarks The channel will be destroyed automatically when a timeout occurs (no initial connection took place within
|
||||
* the specified time) unless the flag bAllowReconnect has been set.
|
||||
* @remarks The channel uses the interface sdv::IObjectLifetime to control the lifetime of the channel. If
|
||||
* IObjectLifetime is not available, IObjectDestroy will be used.
|
||||
* @remarks The function doesn't wait until a connection has been made, but returns straight after the assignment.
|
||||
* @param[in] pChannelEndpoint Pointer to the channel endpoint to be assigned.
|
||||
* @param[in] pObject Initial object to start the communication with.
|
||||
* @param[in] uiTimeoutMs Timeout for waiting for an initial connection. Not used when the bAllowReconnect flag has
|
||||
* been set.
|
||||
* @param[in] bAllowReconnect When set, the channel is allowed to be disconnected and reconnected again.
|
||||
* @return Channel connection ID if successful or 0 if not.
|
||||
*/
|
||||
TConnectionID AssignServerEndpoint(in IInterfaceAccess pChannelEndpoint, in IInterfaceAccess pObject,
|
||||
in uint32 uiTimeoutMs, in boolean bAllowReconnect);
|
||||
|
||||
/**
|
||||
* @brief Assign and take over an already initialized IPC channel client endpoint for use with SDV communication.
|
||||
* @remarks The connection will be destroyed automatically when a timeout occurs (no initial connection took place
|
||||
* within the specified time).
|
||||
* @remarks The channel uses the interface sdv::IObjectLifetime to control the lifetime of the channel. If
|
||||
* IObjectLifetime is not available, IObjectDestroy will be used.
|
||||
* @param[in] pChannelEndpoint Pointer to the channel endpoint to be assigned.
|
||||
* @param[in] uiTimeoutMs Timeout for waiting for an initial connection. Not used when the bAllowReconnect flag has
|
||||
* been set.
|
||||
* @param[out] pProxy Pointer to the object representing the remote object (a proxy to the remote object). Or nullptr
|
||||
* when a timeout occurred.
|
||||
* @return Channel connection ID if successful or 0 if not.
|
||||
*/
|
||||
TConnectionID AssignClientEndpoint(in IInterfaceAccess pChannelEndpoint, in uint32 uiTimeoutMs,
|
||||
out IInterfaceAccess pProxy);
|
||||
|
||||
/**
|
||||
* @brief Remove a connection with the provided connection ID.
|
||||
* @param[in] tConnectionID The connection ID of the connection to remove.
|
||||
*/
|
||||
void RemoveConnection(in TConnectionID tConnectionID);
|
||||
};
|
||||
|
||||
}; // module com
|
||||
}; // module sdv
|
||||
550
export/interfaces/config.idl
Normal file
550
export/interfaces/config.idl
Normal file
@@ -0,0 +1,550 @@
|
||||
/**
|
||||
* @file app.idl
|
||||
* @brief This file provides the core interface definitions SDV framework administration.
|
||||
* @version 0.1
|
||||
* @date 2024.04.11
|
||||
* @author erik.verhoeven@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2023-2025
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
#verbatim_begin
|
||||
#include "../support/string.h"
|
||||
#verbatim_end
|
||||
|
||||
|
||||
/**
|
||||
* @brief Failed to open a file.
|
||||
*/
|
||||
exception XCannotOpenFile : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Cannot open a file.";
|
||||
|
||||
u8string ssPath; ///< Path to the file that cannot be opened.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief File corruption detected.
|
||||
*/
|
||||
exception XFileCorrupt : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The inetrnal structure of the file is not as expected.";
|
||||
|
||||
u8string ssPath; ///< Path to the file that is corrupted.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Failed to read file times or attributes.
|
||||
*/
|
||||
exception XCannotReadFileTimesOrAttributes : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Cannot read file times or attributes.";
|
||||
|
||||
u8string ssPath; ///< Path to the file that cannot be changed.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Failed to change file times or attributes.
|
||||
*/
|
||||
exception XCannotChangeFileTimesOrAttributes : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Cannot change file times or attributes.";
|
||||
|
||||
u8string ssPath; ///< Path to the file that cannot be changed.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Cannot create a directory.
|
||||
*/
|
||||
exception XCannotCreateDir : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Cannot create a directory.";
|
||||
|
||||
u8string ssPath; ///< Path to the directory that cannot be created.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Cannot remove a directory.
|
||||
*/
|
||||
exception XCannotRemoveDir : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Cannot remove a directory.";
|
||||
|
||||
u8string ssPath; ///< Path to the directory that cannot be removed.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An invalid path was supplied.
|
||||
*/
|
||||
exception XInvalidPath : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "An invalid path was supplied.";
|
||||
|
||||
u8string ssPath; ///< Path.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A file with the same path already exists.
|
||||
*/
|
||||
exception XDuplicateFile : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "A file with the same path already exists.";
|
||||
|
||||
u8string ssFilePath; ///< Path to the file.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
/**
|
||||
* Configuration loading/processing result enumeration.
|
||||
*/
|
||||
enum EConfigProcessResult : int32
|
||||
{
|
||||
failed = 0, ///< Loading or processing the configuration failed.
|
||||
successful = 1, ///< Loading or processing the configuration was successful.
|
||||
partially_successful = -1, ///< Loading or processing the configuration was successful for some modules and/or
|
||||
///< components and not successful for other module and/or components.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Application configuration.
|
||||
* @attention This interface is available for the standalone and essential application. The main, isolated and maintenance
|
||||
* applications cannot use this interface.
|
||||
*/
|
||||
local interface IConfig
|
||||
{
|
||||
/**
|
||||
* @brief Process the provided configuration by loading modules and creating objects/stubs/proxies defined in the
|
||||
* configuration string. Processing a configuration resets the baseline before processing.
|
||||
* @attention Configuration changes can only occur when the system is in configuration mode.
|
||||
* @param[in] ssContent The contents of the configuration file (TOML).
|
||||
* @return Returns a config process result enum value.
|
||||
*/
|
||||
EConfigProcessResult ProcessConfig(in u8string ssContent);
|
||||
|
||||
/**
|
||||
* @brief Read file pointed to by the provided file path and load modules and create components as defined in the
|
||||
* configuration file. Loading a configuration resets the baseline before processing.
|
||||
* @attention Configuration changes can only occur when the system is in configuration mode.
|
||||
* @param[in] ssConfigPath Path to the file containing the configuration (TOML). The path can be an absolute as well as a
|
||||
* relative path. In case a relative path is provided, the executable directory is searched as well as all directories
|
||||
* supplied through the AddConfigSearchDir function.
|
||||
* @return Returns a config process result enum value.
|
||||
*/
|
||||
EConfigProcessResult LoadConfig(in u8string ssConfigPath);
|
||||
|
||||
/**
|
||||
* @brief Save a configuration file pointed to by the provided file path. All components are saved that were added after
|
||||
* the last baseline with the configuration specific settings.
|
||||
* @attention Configuration changes can only occur when the system is in configuration mode.
|
||||
* @param[in] ssConfigPath Path to the file containing the configuration (TOML). The path can be an absolute as well as a
|
||||
* relative path. In case a relative path is provided, the configuration is stored relative to the executable directory.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
boolean SaveConfig(in u8string ssConfigPath) const;
|
||||
|
||||
/**
|
||||
* @brief Add a search path to a folder where a config file can be found.
|
||||
* @param[in] ssDir Relative or absolute path to an existing folder.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
boolean AddConfigSearchDir(in u8string ssDir);
|
||||
|
||||
/**
|
||||
* @brief Reset the configuration baseline.
|
||||
* @details The configuration baseline determines what belongs to the current configuration. Any object being added
|
||||
* after this baseline will be stored in a configuration file.
|
||||
*/
|
||||
void ResetConfigBaseline();
|
||||
};
|
||||
}; // module core
|
||||
|
||||
/**
|
||||
* @brief Installation module.
|
||||
*/
|
||||
module installation
|
||||
{
|
||||
/**
|
||||
* @brief Package version struct.
|
||||
*/
|
||||
struct SPackageVersion
|
||||
{
|
||||
uint32 uiMajor; ///< Major version number
|
||||
uint32 uiMinor; ///< Minor version number
|
||||
uint32 uiPatch; ///< Patch level
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Installation package header V1.0.
|
||||
* @todo Add signature information to prevent change after creation.
|
||||
* @details The installation package is composed as follows:
|
||||
* @code
|
||||
* +--------------------------------------------------+
|
||||
* | package header structure |
|
||||
* | optional info |
|
||||
* | checksum |
|
||||
* +--------------------------------------------------+
|
||||
* | 1st BLOB header |
|
||||
* | BLOB content (e.g. file content) |
|
||||
* | BLOB checksum |
|
||||
* +--------------------------------------------------+
|
||||
* | 2nd BLOB header |
|
||||
* | BLOB content (e.g. file content) |
|
||||
* | BLOB checksum |
|
||||
* +--------------------------------------------------+
|
||||
* | ... |
|
||||
* +--------------------------------------------------+
|
||||
* | nth BLOB header |
|
||||
* | BLOB content (e.g. installation manifest) |
|
||||
* | BLOB checksum |
|
||||
* +--------------------------------------------------+
|
||||
* | package footer - checksum of package |
|
||||
* +--------------------------------------------------+
|
||||
* @endcode
|
||||
*/
|
||||
struct SPackageHeader
|
||||
{
|
||||
EEndian eEndian; ///< Describes whether the data is in big or in little endian.
|
||||
uint8 uiReserved; ///< Reserved for alignment measures. Mus be 0.
|
||||
uint16 uiVersion; ///< Structure version (major * 100 + minor).
|
||||
uint32 uiOffset; ///< Offset to the 1st package BLOB.
|
||||
uint8 rguiSignature[8]; ///< Signature 'SDV_IPCK'
|
||||
uint64 uiCreationDate; ///< Creation date (micro-seconds since 1st January 1970).
|
||||
u8string ssManifest; ///< Installation manifest
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Checksum over header following the header content
|
||||
*/
|
||||
struct SPackageHeaderChecksum
|
||||
{
|
||||
uint32 uiChecksum; ///< Checksum over header (CRC32c)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Footer at the end of the package.
|
||||
*/
|
||||
struct SPackageFooter
|
||||
{
|
||||
uint32 uiChecksum; ///< Checksum over complete package (CRC32c)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief File description structure.
|
||||
* @details The file description structure contaions all the information to create the file, including the content. The
|
||||
* file is stored in the installation package in a BLOB by using the serialization functions created by the IDL compiler.
|
||||
*/
|
||||
struct SFileDesc
|
||||
{
|
||||
u8string ssFileName; ///< File name.
|
||||
uint64 uiCreationDate; ///< Creation date (micro-seconds since 1st January 1970).
|
||||
uint64 uiChangeDate; ///< Last change date (micro-seconds since 1st January 1970).
|
||||
boolean bAttrReadonly; ///< Read only file flag when set.
|
||||
boolean bAttrExecutable; ///< Executable file flag when set.
|
||||
pointer<uint8> ptrContent; ///< The binary content of the file.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Installation package BLOB type.
|
||||
*/
|
||||
enum EPackageBLOBType : uint32
|
||||
{
|
||||
binary_file = 1, ///< The BLOB is a binary file using the serialized SFileDesc structure.
|
||||
final_entry = 0xffffffff, ///< Last BLOB entry; no more BLOBs available.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Installation package directory entry. Each BLOB is serialized using the serialization functions generated by IDL
|
||||
* compiler.
|
||||
*/
|
||||
struct SPackageBLOB
|
||||
{
|
||||
EPackageBLOBType eBLOBType; ///< The BLOB type, used for interpretation.
|
||||
uint32 uiChecksumInit; ///< Initial value of the checksum calculation (CRC32c)
|
||||
uint32 uiBLOBSize; ///< Size of the BLOB including header and checksum.
|
||||
|
||||
/// Anonymous union containing the BLOB content.
|
||||
union switch (eBLOBType)
|
||||
{
|
||||
case EPackageBLOBType::binary_file:
|
||||
SFileDesc sFileDesc; ///< File description
|
||||
case final_entry:
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Checksum over BLOB following the content
|
||||
*/
|
||||
struct SPackageBLOBChecksum
|
||||
{
|
||||
uint32 uiChecksum; ///< Checksum over BLOB (CRC32c)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The composure of an installation package failed.
|
||||
*/
|
||||
exception XFailedToCompose : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Faled to compose an installation package.";
|
||||
|
||||
u8string ssInstallName; ///< Name of the installation to compose.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The installation manifest is missing.
|
||||
*/
|
||||
exception XNoManifest : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The installation manifest could not be found or created.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The installation manifest is not readable.
|
||||
*/
|
||||
exception XInvalidManifest : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The installation manifest could not be loaded.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The installation manifest could not be saved.
|
||||
*/
|
||||
exception XFailedSaveManifest : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The installation manifest could not be saved.";
|
||||
|
||||
u8string ssInstallName; ///< Name of the installation.
|
||||
u8string ssPath; ///< Path to the target directory.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creating the installation manifest is not readable.
|
||||
*/
|
||||
exception XFailedManifestCreation : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The installation manifest could not be created.";
|
||||
|
||||
u8string ssInstallName; ///< Name of the installation.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Multiple installation manifests found.
|
||||
*/
|
||||
exception XDuplicateManifest : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "A duplicate installation manifest was found.";
|
||||
|
||||
u8string ssInstallName1; ///< Name of the 1st installation.
|
||||
u8string ssInstallName2; ///< Name of the 2nd installation.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An installation with the same name exists already.
|
||||
*/
|
||||
exception XDuplicateInstall : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "An installation exists already.";
|
||||
|
||||
u8string ssInstallName; ///< Name of the installation.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The installation doesn't contain a module.
|
||||
*/
|
||||
exception XModuleNotFound : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "A module with the supplied name could not be found.";
|
||||
|
||||
u8string ssPath; ///< Path to the component.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief One or more components within the installation cannot be loaded. It might be that companion files are missing.
|
||||
*/
|
||||
exception XComponentNotLoadable : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "One or more components cannot be loaded.";
|
||||
|
||||
sequence<u8string> seqComponents; ///< List of components that cannot be loaded.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief One or more files have an incorrect CRC.
|
||||
*/
|
||||
exception XIncorrectCRC : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The installation package has an invalid CRC.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The package is not compatible.
|
||||
*/
|
||||
exception XIncompatiblePackage : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The installation package is incompatible.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief One or more files have an incorrect relative path to store the files.
|
||||
*/
|
||||
exception XIncorrectPath : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Invalid module target path.";
|
||||
|
||||
u8string ssPath; ///< The module target path is invalid.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Missing base path.
|
||||
*/
|
||||
exception XMissingBasePath : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "A base path is required for processing.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The requested installation was not found.
|
||||
*/
|
||||
exception XInstallationNotFound : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "THe installation was not found.";
|
||||
|
||||
u8string ssInstallName; ///< Name of the installation.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The installed components cannot be unloaded and therefore the installation cannot be uninstalled.
|
||||
*/
|
||||
exception XUninstallCouldNotUnload : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Unable to unload the installation.";
|
||||
|
||||
u8string ssInstallName; ///< Name of the installation.
|
||||
};
|
||||
|
||||
/*
|
||||
TODO EVE
|
||||
Installation needs to be more flexible...
|
||||
- Components can have calibration values. They content is stored in the config.
|
||||
- A configuration can be made using the components and the names of the components (VSS???)
|
||||
- Installing and configuring devices and system and basic services is possible when sdv_core is started in update mode.
|
||||
- Installing and configuring complex services is possible at any time dynamically.
|
||||
- Installation and configuring only in config mode
|
||||
- extend the functionality of the sdv_packager utility to create more detailed config.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Application installation interface.
|
||||
* @attention This function is only available for the main application and part of the application config service.
|
||||
*/
|
||||
interface IAppInstall
|
||||
{
|
||||
/**
|
||||
* @brief Make an installation onto the system.
|
||||
* @details Make an installation with from component modules and supporting files. At least one component module must
|
||||
* be provided for this installation to be successful (component attribute flag must be set). Components are only
|
||||
* installed, not activated.
|
||||
* @remarks The system needs to run in configuration mode.
|
||||
* @param[in] ssInstallName Name of the installation. Must be unique to the system.
|
||||
* @param[in] seqFiles Files belonging to the installation. This could be component modules as well as supporting files.
|
||||
* @return Returns whether the installation was successful - installation name was unique and at least one loadable
|
||||
* component was provided.
|
||||
*/
|
||||
boolean Install(in u8string ssInstallName, in sequence<SFileDesc> seqFiles)
|
||||
raises(XDuplicateInstall, XModuleNotFound, XComponentNotLoadable, XIncorrectCRC,
|
||||
XIncorrectPath);
|
||||
|
||||
/**
|
||||
* @brief Update an installation.
|
||||
* @details Stops a component if the component is running, makes an update and if the component was running, starts
|
||||
* the component again.
|
||||
* @todo: Currently limited to complex services only.
|
||||
* @remarks The system needs to run in configuration mode.
|
||||
* @param[in] ssInstallName Name of the installation. Must be unique to the system.
|
||||
* @param[in] seqFiles Files belonging to the installation. This could be component modules as well as supporting files.
|
||||
* @return Returns whether the installation was successful - installation name was unique and at least one loadable
|
||||
* component was provided.
|
||||
*/
|
||||
boolean Update(in u8string ssInstallName, in sequence<SFileDesc> seqFiles)
|
||||
raises(XInstallationNotFound, XModuleNotFound, XComponentNotLoadable, XIncorrectCRC,
|
||||
XIncorrectPath);
|
||||
|
||||
/**
|
||||
* @brief Uninstall of a previous installation.
|
||||
* @details Stops a component if the component is running and removes the files and modules.
|
||||
* @todo: Currently limited to complex services only.
|
||||
* @remarks The system needs to run in configuration mode.
|
||||
* @param[in] ssInstallName Installation name.
|
||||
* @return Returns whether the uninstallation was successful.
|
||||
*/
|
||||
boolean Uninstall(in u8string ssInstallName) raises(XInstallationNotFound, XUninstallCouldNotUnload);
|
||||
|
||||
/**
|
||||
* @brief Get a sequence of installations.
|
||||
* @return The sequence with installations.
|
||||
*/
|
||||
sequence<u8string> GetInstallations() const;
|
||||
|
||||
/**
|
||||
* @brief Get the installed files from the installation.
|
||||
* @param[in] ssInstallName The installation to get the files for.
|
||||
* @return Sequence containing the file structures without the binary file content.
|
||||
*/
|
||||
sequence<SFileDesc> GetInstallationFiles(in u8string ssInstallName) const raises(XInstallationNotFound);
|
||||
};
|
||||
}; // module installation
|
||||
|
||||
/**
|
||||
* @brief Helper features
|
||||
*/
|
||||
module helper
|
||||
{
|
||||
/**
|
||||
* @brief Read the module manifest.
|
||||
* @brief Interface for reading the module manifest. This interface is implemented by the manifest_util component to read
|
||||
* the manifest while being isolated from the system, thus protecting the system for unwanted behavior in case of
|
||||
* malfunction.
|
||||
*/
|
||||
interface IModuleManifestHelper
|
||||
{
|
||||
/**
|
||||
* @brief Read the module manifest.
|
||||
* @param[in] ssModule Path to the module file.
|
||||
* @return The module manifest if available. Otherwise an empty string.
|
||||
*/
|
||||
u8string ReadModuleManifest(in u8string ssModule);
|
||||
};
|
||||
}; // module helper
|
||||
}; // module sdv
|
||||
291
export/interfaces/core.idl
Normal file
291
export/interfaces/core.idl
Normal file
@@ -0,0 +1,291 @@
|
||||
/**
|
||||
* @file core.idl
|
||||
* @brief This file provides the core interface definitions of the core SDV framework.
|
||||
* @version 0.1
|
||||
* @date 2023.04.26
|
||||
* @author erik.verhoeven@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2023
|
||||
*/
|
||||
|
||||
#include "core_types.idl"
|
||||
|
||||
#verbatim #include "../support/pointer.h"
|
||||
#verbatim #include "../support/iterator.h"
|
||||
#verbatim #include "../support/string.h"
|
||||
#verbatim #include "../support/sequence.h"
|
||||
#verbatim #include "../support/any.h"
|
||||
|
||||
#verbatim_begin
|
||||
#if defined(_WIN32) && defined(GetClassInfo)
|
||||
#undef GetClassinfo
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4190) // Disable C-linkage warning when using C++ objects.
|
||||
#endif
|
||||
#verbatim_end
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Access interface
|
||||
*/
|
||||
interface IInterfaceAccess
|
||||
{
|
||||
/**
|
||||
* @brief Get access to another interface.
|
||||
*
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
interface_t GetInterface(in interface_id idInterface);
|
||||
|
||||
#verbatim_begin
|
||||
/**
|
||||
* @brief Templated version of GetInterface.
|
||||
* @tparam TInterface The interface type.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
TInterface* GetInterface()
|
||||
{
|
||||
return GetInterface(sdv::GetInterfaceId<TInterface>()).template get<TInterface>();
|
||||
}
|
||||
#verbatim_end
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Object type enumeration.
|
||||
*/
|
||||
enum EObjectType : uint32
|
||||
{
|
||||
SystemObject = 0, ///< System object
|
||||
Device = 10, ///< Abstract device
|
||||
BasicService = 20, ///< Basic service
|
||||
ComplexService = 21, ///< Complex service
|
||||
Application = 30, ///< Application
|
||||
Proxy = 100, ///< Proxy object
|
||||
Stub = 101, ///< Stub object
|
||||
Utility = 1000, ///< Utility object
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Object flags.
|
||||
*/
|
||||
enum EObjectFlags : uint32
|
||||
{
|
||||
singleton = 256, ///< The object is a singleton object.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class information structure.
|
||||
*/
|
||||
struct SClassInfo
|
||||
{
|
||||
u8string ssModulePath; ///< Path to the module that contains the class.
|
||||
u8string ssClassName; ///< String representing the class name.
|
||||
sequence<u8string> seqClassAliases; ///< Sequence with class name aliases.
|
||||
u8string ssDefaultObjectName; ///< The default object name.
|
||||
EObjectType eType; ///< Type of object.
|
||||
uint32 uiFlags; ///< Zero or more object flags from EObjectFlags.
|
||||
sequence<u8string> seqDependencies; ///< Sequence with object class names this object is dependent on.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface implemented by each module and used for managing the objects.
|
||||
*/
|
||||
interface IObjectFactory
|
||||
{
|
||||
/**
|
||||
* @brief Create or get the object using the name from the object class info.
|
||||
* @attention The objects lifetime is ended by a call to the DestroyObject function or the unloading of the module.
|
||||
* @param[in] ssClassName The name of the class object to instantiate.
|
||||
* @return Pointer to IInterfaceAccess interface of the object or NULL when the requested object doesn't exist.
|
||||
*/
|
||||
IInterfaceAccess CreateObject(in u8string ssClassName);
|
||||
|
||||
/**
|
||||
* @brief Destroy an instantiated object using the pointer to the object instance.
|
||||
* @param[in] sdvObject The object to destroy
|
||||
*/
|
||||
void DestroyObject(in IInterfaceAccess sdvObject);
|
||||
|
||||
/**
|
||||
* @brief Destroys all currently instantiated objects in reverse order of creation
|
||||
*/
|
||||
void DestroyAllObjects();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Object status enumeration
|
||||
*/
|
||||
enum EObjectStatus : uint32
|
||||
{
|
||||
initialization_pending = 0, ///< constructor called, but no call to initialize yet
|
||||
initializing = 10, ///< Initialize was called and is being executed.
|
||||
initialization_failure = 11, ///< Initialization failed
|
||||
initialized = 12, ///< Initialization succeeded
|
||||
configuring = 20, ///< In configuration mode (available after initialization).
|
||||
config_error = 21, ///< While configuring, error encountered
|
||||
running = 30, ///< In running mode (available after initialization).
|
||||
runtime_error = 31, ///< While running, error encountered
|
||||
shutdown_in_progress = 90, ///< Shutdown called, but not finished yet
|
||||
destruction_pending = 99, ///< All threads stopped + does no longer fire callbacks or events, ready to be destroyed
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Component operation mode.
|
||||
*/
|
||||
enum EOperationMode : uint32
|
||||
{
|
||||
configuring = 20, ///< The component should switch to configuration mode.
|
||||
running = 30, ///< The component should switch to running mode.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional interface allowing for additional control of more complex SDVObjects.
|
||||
* To be implemented if the object in question calls other SDVobjects via running threads or callbacks,
|
||||
* requires configuration or performs other complex behavior during creation/shutdown
|
||||
*/
|
||||
interface IObjectControl
|
||||
{
|
||||
/**
|
||||
* @brief Initialize the object.
|
||||
* @param[in] ssObjectConfig Optional configuration string.
|
||||
*/
|
||||
void Initialize(in u8string ssObjectConfig);
|
||||
|
||||
/**
|
||||
* @brief Get the current status of the object.
|
||||
* @return Return the current status of the object.
|
||||
*/
|
||||
EObjectStatus GetStatus() const;
|
||||
|
||||
/**
|
||||
* @brief Set the component operation mode.
|
||||
* @param[in] eMode The operation mode, the component should run in.
|
||||
*/
|
||||
void SetOperationMode(in EOperationMode eMode);
|
||||
|
||||
/**
|
||||
* @brief Shutdown called before the object is destroyed.
|
||||
* @attention Implement calls to other SDV objects here as this is no longer considered safe during the destructor of the object!
|
||||
* After a call to shutdown any threads/callbacks/etc that could call other SDV objects need to have been stopped.
|
||||
* The SDV object itself is to remain in a state where it can respond to calls to its interfaces as other objects may still call it during the shutdown sequence!
|
||||
* Any subsequent call to GetStatus should return EObjectStatus::destruction_pending
|
||||
*/
|
||||
void Shutdown();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface that might be exposed by objects to allow self-destruction if the owner doesn't need to object any more.
|
||||
*/
|
||||
interface IObjectDestroy
|
||||
{
|
||||
/**
|
||||
* @brief Destroy the object.
|
||||
* @attention After a call of this function, all exposed interfaces render invalid and should not be used any more.
|
||||
*/
|
||||
void DestroyObject();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Lifetime management through reference counting.
|
||||
*/
|
||||
interface IObjectLifetime
|
||||
{
|
||||
/**
|
||||
* @brief Increment the lifetime. Needs to be balanced by a call to Decrement.
|
||||
*/
|
||||
void Increment();
|
||||
|
||||
/**
|
||||
* @brief Decrement the lifetime. If the lifetime reaches zero, the object will be destroyed (through the exposed
|
||||
* IObjectDestroy interface).
|
||||
* @return Returns 'true' if the object was destroyed, false if not.
|
||||
*/
|
||||
boolean Decrement();
|
||||
|
||||
/**
|
||||
* @brief Get the current lifetime count.
|
||||
* @remarks The GetCount function returns a momentary value, which can be changed at any moment.
|
||||
* @return Returns the current counter value.
|
||||
*/
|
||||
uint32 GetCount() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attribute flags.
|
||||
*/
|
||||
enum EAttributeFlags : uint32
|
||||
{
|
||||
read_only = 0x100, ///< When set, the attribute is readonly.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attribute interface
|
||||
*/
|
||||
interface IAttributes
|
||||
{
|
||||
/**
|
||||
* @brief Get a sequence with the available attribute names.
|
||||
* @return The sequence of attribute names.
|
||||
*/
|
||||
sequence<u8string> GetNames() const;
|
||||
|
||||
/**
|
||||
* @brief Get the attribute value.
|
||||
* @param[in] ssAttribute Name of the attribute.
|
||||
* @return The attribute value or an empty any-value if the attribute wasn't found or didn't have a value.
|
||||
*/
|
||||
any Get(in u8string ssAttribute) const;
|
||||
|
||||
/**
|
||||
* @brief Set the attribute value.
|
||||
* @param[in] ssAttribute Name of the attribute.
|
||||
* @param[in] anyAttribute Attribute value to set.
|
||||
* @return Returns 'true' when setting the attribute was successful or 'false' when the attribute was not found or the
|
||||
* attribute is read-only or another error occurred.
|
||||
*/
|
||||
boolean Set(in u8string ssAttribute, in any anyAttribute);
|
||||
|
||||
/**
|
||||
* @brief Get the attribute flags belonging to a certain attribute.
|
||||
* @param[in] ssAttribute Name of the attribute.
|
||||
* @return Returns the attribute flags (zero or more EAttributeFlags flags) or 0 when the attribute could not be found.
|
||||
*/
|
||||
uint32 GetFlags(in u8string ssAttribute) const;
|
||||
};
|
||||
|
||||
}; // module sdv
|
||||
|
||||
#verbatim_begin
|
||||
/**
|
||||
* @brief Returns whether or not instances of objects implemented by this module are running. If none, the module can be unloaded.
|
||||
* @remarks Unloading the module with running instances could cause a crash and should be prevented at all costs. Unloading the
|
||||
* module removes the code of the objects still running.
|
||||
* @return Returns true when object instances are running; otherwise returns 'false'.
|
||||
*/
|
||||
extern "C" SDV_SYMBOL_PUBLIC bool HasActiveObjects();
|
||||
|
||||
/**
|
||||
* @brief Get the module factory interface with a specific version.
|
||||
* @details This function provides access to the objects being implemented in this module.
|
||||
* @param[in] interfaceVersion Request the module factory for a specific interface version.
|
||||
* Using another interface version than the one returned from the GetInterfaceVersion, might cause the function to fail.
|
||||
* @return Returns pointer to the IInterfaceAccess interface of the module factory object.
|
||||
*/
|
||||
extern "C" SDV_SYMBOL_PUBLIC sdv::IInterfaceAccess* GetModuleFactory(uint32_t interfaceVersion);
|
||||
|
||||
/**
|
||||
* @brief Get the the module manifest.
|
||||
* @details Each module contains a manifest containing general information as well as information about the component classes. This
|
||||
* allows installing the component without having to instantiate the classes.
|
||||
* @return Returns the pointer to a zero terminated string containing the module manifest or NULL when there is no string.
|
||||
*/
|
||||
extern "C" SDV_SYMBOL_PUBLIC const char* GetManifest();
|
||||
#verbatim_end
|
||||
|
||||
#include "mem.idl"
|
||||
650
export/interfaces/core_idl.idl
Normal file
650
export/interfaces/core_idl.idl
Normal file
@@ -0,0 +1,650 @@
|
||||
/**
|
||||
* @file core_idl.idl
|
||||
* @brief This file provides all interface definitions for generator of the IDL compiler as part of the core SDV framework.
|
||||
* @version 0.1
|
||||
* @date 2023.06.29
|
||||
* @author erik.verhoeven@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2022-2025
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
#include "mem.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief IDL features.
|
||||
*/
|
||||
module idl
|
||||
{
|
||||
/**
|
||||
* @brief Compilation error.
|
||||
*/
|
||||
exception XCompileError
|
||||
{
|
||||
|
||||
u8string ssReason; ///< Explanation of the compilation error.
|
||||
u8string ssFile; ///< Path to the file causing the compilation error.
|
||||
uint32 uiLine; ///< Line in the source file that contains the error (starts at 1).
|
||||
uint32 uiCol; ///< Column in the source file that contains the error (starts at 1).
|
||||
u8string ssToken; ///< Token that caused the error.
|
||||
u8string ssLine; ///< Source code line that contains the error.
|
||||
};
|
||||
|
||||
|
||||
const u8string ssOptionDevEnvDir = u8"DevEnvDir"; ///< The installation directory of the compiler.
|
||||
const u8string ssOptionOutDir = u8"OutDir"; ///< Path to the output file directory. Default "." - relative to the file path.
|
||||
const u8string ssOptionFilename = u8"Filename"; ///< Name of the input file.
|
||||
const u8string ssOptionFilePath = u8"FilePath"; ///< Path to the input file.
|
||||
const u8string ssOptionCodeGen = u8"CodeGen"; ///< List of code generators
|
||||
|
||||
/**
|
||||
* @brief Compiler option access.
|
||||
*/
|
||||
interface ICompilerOption
|
||||
{
|
||||
/**
|
||||
* @brief Get the compiler option.
|
||||
* @param[in] rssOption Reference to the string containing the name of the option to retrieve.
|
||||
* @return The requested compiler option (if available).
|
||||
*/
|
||||
u8string GetOption(in u8string rssOption) const;
|
||||
|
||||
/**
|
||||
* @brief Get the amount of option values.
|
||||
* @param[in] rssOption Reference to the string containing the name of the option to retrieve.
|
||||
* @return The amount of option values.
|
||||
*/
|
||||
uint32 GetOptionCnt(in u8string rssOption) const;
|
||||
|
||||
/**
|
||||
* @brief Get the compiler option.
|
||||
* @param[in] rssOption Reference to the string containing the name of the option to retrieve.
|
||||
* @param[in] uiIndex The index of the option value.
|
||||
* @return The requested compiler option value.
|
||||
*/
|
||||
u8string GetOptionN(in u8string rssOption, in uint32 uiIndex) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Compiler information access.
|
||||
*/
|
||||
interface ICompilerInfo
|
||||
{
|
||||
/**
|
||||
* @brief Get the path of the processed file.
|
||||
* @return The path string.
|
||||
*/
|
||||
u8string GetFilePath() const;
|
||||
|
||||
/**
|
||||
* @brief Return the path to the output directory.
|
||||
* @return The directory string.
|
||||
*/
|
||||
u8string GetOutputDir() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The entity type.
|
||||
* @remarks Const entities, declaration entities and typedef entities return the base type of the entity they declare/define.
|
||||
*/
|
||||
enum EEntityType : uint32
|
||||
{
|
||||
type_unknown, ///< Unknown entity type
|
||||
type_variable, ///< Variable entity type
|
||||
type_enum, ///< Enum entity type
|
||||
type_struct, ///< Struct entity type
|
||||
type_union, ///< Union entity type
|
||||
type_module, ///< Module entity type
|
||||
type_interface, ///< Interface entity type
|
||||
type_exception, ///< Interface entity type
|
||||
type_attribute, ///< Attribute entity type
|
||||
type_operation, ///< Operation entity type
|
||||
type_parameter, ///< Parameter entity type
|
||||
type_enum_entry, ///< Enum entry entity type
|
||||
type_case_entry, ///< Case entry entity type
|
||||
type_switch_variable, ///< Switch variable entity type (used by unions)
|
||||
type_typedef, ///< Typedef entity type
|
||||
type_meta, ///< Meta data entity type
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The entity declaration type.
|
||||
*/
|
||||
enum EDeclType : uint32
|
||||
{
|
||||
decltype_unknown, ///< Unknown type
|
||||
decltype_short, ///< Integer type (int16_t)
|
||||
decltype_long, ///< Integer type (int32_t)
|
||||
decltype_long_long, ///< Integer type (int64_t)
|
||||
decltype_octet, ///< Octet type (uint8_t)
|
||||
decltype_unsigned_short, ///< Integer type (uint16_t)
|
||||
decltype_unsigned_long, ///< Integer type (uint32)
|
||||
decltype_unsigned_long_long, ///< Integer type (uint64_t)
|
||||
decltype_float, ///< Floating point type
|
||||
decltype_double, ///< Floating point type
|
||||
decltype_long_double, ///< Floating point type
|
||||
decltype_fixed, ///< Fixed point templated type
|
||||
decltype_char, ///< Character type (int8_t)
|
||||
decltype_char16, ///< UTF-16 character
|
||||
decltype_char32, ///< UTF-32 character
|
||||
decltype_wchar, ///< Character type
|
||||
decltype_boolean, ///< Boolean type
|
||||
decltype_native, ///< Native type
|
||||
decltype_string, ///< ASCII templated string type
|
||||
decltype_u8string, ///< UTF-8 templated string type
|
||||
decltype_u16string, ///< UTF-16 templated string type
|
||||
decltype_u32string, ///< UTF-32 templated string type
|
||||
decltype_wstring, ///< Wide templated string type
|
||||
decltype_enum, ///< Enum type
|
||||
decltype_struct, ///< Struct type
|
||||
decltype_union, ///< Union type
|
||||
decltype_module, ///< Module type
|
||||
decltype_interface, ///< Interface type (not used in declarations)
|
||||
decltype_exception, ///< Interface type (not used in declarations)
|
||||
decltype_attribute, ///< Attribute type (not used in declarations)
|
||||
decltype_operation, ///< Operation type (not used in declarations)
|
||||
decltype_parameter, ///< Parameter type (only for operations)
|
||||
decltype_enum_entry, ///< Enum entry type (only for enums)
|
||||
decltype_case_entry, ///< Case entry type (only for unions)
|
||||
decltype_typedef, ///< Typedef type
|
||||
decltype_void, ///< Void type (only for operations)
|
||||
decltype_meta, ///< Meta data type
|
||||
decltype_pointer, ///< Pointer templated data type
|
||||
decltype_sequence, ///< Sequence templated data type
|
||||
decltype_map, ///< Map templated data type
|
||||
decltype_bitset, ///< Bitset data type
|
||||
decltype_bitfield, ///< Bitfield templated data type
|
||||
decltype_bitmask, ///< Bitmask data type
|
||||
decltype_any, ///< Any composite data type
|
||||
decltype_interface_id, ///< Interface ID data type
|
||||
decltype_interface_type, ///< Interface data type
|
||||
decltype_exception_id, ///< Exception ID data type
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Entity base information interface.
|
||||
*/
|
||||
interface IEntityInfo
|
||||
{
|
||||
/**
|
||||
* @brief Get the type of the entity. Default type is EEntityType::type_unknown.
|
||||
* @return Returns the type of the entity.
|
||||
*/
|
||||
EEntityType GetType() const;
|
||||
|
||||
/**
|
||||
* @brief Get the name of the entity.
|
||||
* @return Returns the name string.
|
||||
*/
|
||||
u8string GetName() const;
|
||||
|
||||
/**
|
||||
* @brief Get the scoped name of the entity (including the modules separated by the scope separator).
|
||||
* @details The scoped name is composed of the entities of the parents separated by the scope operator '::'. For
|
||||
* members of a compound entity (struct, union), the separation is done through the member operator '.'.
|
||||
* @return The scoped name build from the entities of the parents separated by '::'. An empty name means global
|
||||
* scope.
|
||||
*/
|
||||
u8string GetScopedName() const;
|
||||
|
||||
/**
|
||||
* @brief Is the entity defined as (forward) declaration only?
|
||||
* @return Returns 'true' when the entity is defined as forward declaration; otherwise returns 'false'.
|
||||
*/
|
||||
boolean ForwardDeclaration() const;
|
||||
|
||||
/**
|
||||
* @brief Get the entity ID. This ID is a hash value composed from its definition and all declarative members not
|
||||
* including const values. The ID can be used to uniquely identify the entity (e.g. as interface ID or exception ID).
|
||||
* @return The ID of the entity.
|
||||
*/
|
||||
uint64 GetId() const;
|
||||
|
||||
/**
|
||||
* @brief Get the parent entity of this entity.
|
||||
* @return Returns an interface to the parent entity or NULL when this is the root parent (when there is no parent).
|
||||
*/
|
||||
IInterfaceAccess GetParent() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Iterate through a vector of entities.
|
||||
*/
|
||||
interface IEntityIterator
|
||||
{
|
||||
/**
|
||||
* @brief Get amount of entities.
|
||||
* @return Returns the amount of entities available to this iterator.
|
||||
*/
|
||||
uint32 GetCount() const;
|
||||
|
||||
/**
|
||||
* @brief Get entity at supplied index.
|
||||
* @param[in] uiIndex The index to get the entity for.
|
||||
* @return The entity at the index or NULL when there is no entity at this index.
|
||||
*/
|
||||
IInterfaceAccess GetEntityByIndex(in uint32 uiIndex);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Context information interface.
|
||||
*/
|
||||
interface IEntityContext
|
||||
{
|
||||
/**
|
||||
* @brief The location of the parsed file.
|
||||
*/
|
||||
enum ELocation : uint32
|
||||
{
|
||||
source, ///< Source code or source file.
|
||||
local_include, ///< Local include file.
|
||||
global_include ///< Global include file.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get the location.
|
||||
* @return Returns context location.
|
||||
*/
|
||||
ELocation GetLocation() const;
|
||||
|
||||
/**
|
||||
* @brief Get the path to the file.
|
||||
* @return Returns the source path string.
|
||||
*/
|
||||
u8string GetSourcePath() const;
|
||||
|
||||
/**
|
||||
* @brief Get the position in the file.
|
||||
* @remarks Not all entities have a position. If no position is available, the position return value has the
|
||||
* value 0.
|
||||
* @param[out] ruiLineBegin Reference to the variable receiving the line number of the entity beginning.
|
||||
* @param[out] ruiColBegin Reference to the variable receiving the column number of the entity beginning.
|
||||
* @param[out] ruiLineEnd Reference to the variable receiving the line number of the entity ending.
|
||||
* @param[out] ruiColEnd Reference to the variable receiving the column number of the entity ending.
|
||||
*/
|
||||
void GetPosition(out uint32 ruiLineBegin, out uint32 ruiColBegin, out uint32 ruiLineEnd, out uint32 ruiColEnd);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Meta information interface. Exposed by the meta entity.
|
||||
*/
|
||||
interface IMetaEntity
|
||||
{
|
||||
/**
|
||||
* @brief Token meta type (valid when token is a meta token).
|
||||
*/
|
||||
enum EType : uint32
|
||||
{
|
||||
include_local = 10, ///< Local include file
|
||||
include_global = 11, ///< Global include file
|
||||
define = 20, ///< Definition
|
||||
undef = 21, ///< Remove definition
|
||||
verbatim = 100, ///< Verbatim text to be inserted in the generated code
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get the meta data type.
|
||||
* @return Returns the meta type.
|
||||
*/
|
||||
EType GetMetaType() const;
|
||||
|
||||
/**
|
||||
* @brief Get the meta data content.
|
||||
* @return Returns a string object.
|
||||
*/
|
||||
u8string GetContent() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Comment interface.
|
||||
*/
|
||||
interface IEntityComments
|
||||
{
|
||||
/**
|
||||
* \brief Comment mask
|
||||
*/
|
||||
enum ECommentMask : uint32
|
||||
{
|
||||
c_style_javadoc = 0x40001000, ///< Comment of the form "/** ... */"
|
||||
c_style_javadoc_post = 0x40201000, ///< Comment of the form "/**< ... */"
|
||||
c_style_qt = 0x40002000, ///< Comment of the form "/*! ... */"
|
||||
c_style_qt_post = 0x40202000, ///< Comment of the form "/*!< ... */"
|
||||
c_style = 0x40000000, ///< Comment of the form "/* ... */"
|
||||
cpp_style_javadoc = 0x80001000, ///< Comment of the form "/// ..."
|
||||
cpp_style_javadoc_post = 0x80201000, ///< Comment of the form "///< ..."
|
||||
cpp_style_qt = 0x80002000, ///< Comment of the form "//! ..."
|
||||
cpp_style_qt_post = 0x80202000, ///< Comment of the form "///< ..."
|
||||
cpp_style = 0x80000000, ///< Comment of the form "// ..."
|
||||
loc_succeeding = 0x00200000, ///< Comment location is succeeding statement
|
||||
format_javadoc = 0x00001000, ///< Comment using javadoc form
|
||||
format_qt = 0x00002000, ///< Comment using QT form
|
||||
format_mask = 0x0000f000, ///< Comment formatting mask
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get the comment lines for this entity as one string.
|
||||
* @remarks For c-style multi-line comments, the indentation and additional asterisk character at the beginning of
|
||||
* each line is removed.
|
||||
* @param[out] ruiFlags Reference to the variable receiving the comment flags (a bitmask combination of
|
||||
* sdv::idl::IEntityComments::ECommentMask).
|
||||
* @return Returns the comment string. If the comment contains multiple lines, each line is ending with a newline.
|
||||
*/
|
||||
u8string GetComments(out uint32 ruiFlags) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Entity definition information interface.
|
||||
*/
|
||||
interface IDefinitionEntity
|
||||
{
|
||||
/**
|
||||
* \brief Does the entity have an unnamed definition.
|
||||
* @return Returns 'true' when the entity has an unnamed definition; otherwise returns 'false'.
|
||||
*/
|
||||
boolean IsUnnamed() const;
|
||||
|
||||
/**
|
||||
* @brief Get child entity iterator if children are available and supported by the definition.
|
||||
* @return Returns a pointer to the child entity iterator or NULL when not available.
|
||||
*/
|
||||
IEntityIterator GetChildren();
|
||||
|
||||
/**
|
||||
* @brief Get inheritance entity iterator if the definition was inheriting from other entities.
|
||||
* @return Returns a pointer to the inheritance entity iterator or NULL when not available.
|
||||
*/
|
||||
IEntityIterator GetInheritance();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Entities declared in a forward declaration expose this interface.
|
||||
*/
|
||||
interface IForwardDeclarationEntity
|
||||
{
|
||||
/**
|
||||
* @brief Get access to the actual declaration (if there is one).
|
||||
* @return Pointer to the interface of the entity definition or NULL when there is no definition.
|
||||
*/
|
||||
IInterfaceAccess GetEntity();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Declaration type interface containing the base type, type string as defined in the code as well as the
|
||||
* definition object interface and template parameters.
|
||||
*/
|
||||
interface IDeclarationType
|
||||
{
|
||||
/**
|
||||
* @brief Return the base type.
|
||||
* @details The bse type might be a templated type (string, sequence, map, etc.) which means that additional
|
||||
* information is needed. Furthermore, the type might be a complex type (struct, union, enum) or a typedef. In these
|
||||
* cases the type definition interface is available.
|
||||
* @return The base type of this type.
|
||||
*/
|
||||
EDeclType GetBaseType() const;
|
||||
|
||||
/**
|
||||
* @brief Return the string that described the type in the code.
|
||||
* @return The type string.
|
||||
*/
|
||||
u8string GetTypeString() const;
|
||||
|
||||
/**
|
||||
* @brief Return the type definition for complex types or typedefs.
|
||||
* @return Pointer to the interface representing the type definition. Will be NULL for all other types.
|
||||
*/
|
||||
IInterfaceAccess GetTypeDefinition() const;
|
||||
|
||||
/**
|
||||
* @brief Fixed length parameter for some templated types.
|
||||
* @details Fixed length template parameter for "fixed", "string", "sequence", "pointer", "map" and "bitfields".
|
||||
* When not compulsory (for "fixed", "string", "sequence", "pointer" and "map") could be 0 to indicate a dynamic
|
||||
* length (or defined over assignment with "fixed"). Bitfields allow a length between 1 and 64 bits.
|
||||
* @return Returns the fixed length for some templated types or 0 for all other other types.
|
||||
*/
|
||||
uint32 GetFixedLength() const;
|
||||
|
||||
/**
|
||||
* @brief The amount of decimals of the "fixed" data type. Must be equal or smaller than the fixed length.
|
||||
* @return The amount of decimals for the "fixed" data type or 0 for all other data types.
|
||||
*/
|
||||
uint32 GetDecimals() const;
|
||||
|
||||
/**
|
||||
* @brief The value type template parameter for the "sequence", "pointer", "map" and "bitfield" data types.
|
||||
* @return Interface to the value data type for some templated types of NULL for all other types.
|
||||
*/
|
||||
IInterfaceAccess GetValueType() const;
|
||||
|
||||
/**
|
||||
* @brief The key type template parameter for the "map" data type.
|
||||
* @return Interface to the key data type for the "map" type of NULL for all other types.
|
||||
*/
|
||||
IInterfaceAccess GetKeyType() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Array dimension definition.
|
||||
* @details Multi-dimensional arrays are possible. Each dimension is defined between square-brackets
|
||||
* (eg. var[a][b][]). An unbound dimension can only occur as the last dimension. Fixed-bound dimensions can be
|
||||
* specified using a constant expression. If variables are used in the constant expression, they need to be in
|
||||
* scope of the array variable.
|
||||
*/
|
||||
struct SArrayDimension
|
||||
{
|
||||
/**
|
||||
* @brief Dimension type.
|
||||
*/
|
||||
enum EDimensionType : uint32
|
||||
{
|
||||
bound = 0, ///< Bound array
|
||||
unbound = 2, ///< Unbound array
|
||||
} eType; ///< The dimension type
|
||||
|
||||
u8string ssExpression; ///< Expression defining the dimension size either as constant- or as runtime-expression.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Declaration entity information interface.
|
||||
*/
|
||||
interface IDeclarationEntity
|
||||
{
|
||||
/**
|
||||
* @brief Get declaration type.
|
||||
* @return Interface to the declaration type object.
|
||||
*/
|
||||
IInterfaceAccess GetDeclarationType() const;
|
||||
|
||||
/**
|
||||
* @brief Is the entity readonly?
|
||||
* @return Returns 'true' when the declaration is defined as readonly declaration; otherwise returns 'false'.
|
||||
*/
|
||||
boolean IsReadOnly() const;
|
||||
|
||||
/**
|
||||
* @brief Is the entity anonymous when used in a struct/union (unnamed and not declared)?
|
||||
* @details Returns whether the entity is anonymous when used in a struct/union. This allows its members to appear
|
||||
* directly as members within the struct.
|
||||
* @return Returns 'true' when the declaration is defined as anonymous declaration; otherwise returns 'false'.
|
||||
*/
|
||||
boolean IsAnonymous() const;
|
||||
|
||||
/**
|
||||
* @brief Has array?
|
||||
* @return Returns 'true' when the declaration is part of an array; otherwise returns 'false'.
|
||||
*/
|
||||
boolean HasArray() const;
|
||||
|
||||
/**
|
||||
* @brief Get the array dimensions (if there are any).
|
||||
* @return Smart pointer to the sequence of array dimensions.
|
||||
*/
|
||||
sequence<SArrayDimension> GetArrayDimensions() const;
|
||||
|
||||
/**
|
||||
* @brief Has assignment?
|
||||
* @return Returns 'true' when the declaration is followed by an assignment; otherwise returns 'false'.
|
||||
*/
|
||||
boolean HasAssignment() const;
|
||||
|
||||
/**
|
||||
* @brief Get assignment string.
|
||||
* @details The assignment can be an algebraic expression composed from constants and variables. If the assignment is an
|
||||
* array, the expression is composed like this: {{expr1},{expr2},{expr...}}
|
||||
* @return Returns the assignment string when available.
|
||||
*/
|
||||
u8string GetAssignment() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface entity
|
||||
*/
|
||||
interface IInterfaceEntity
|
||||
{
|
||||
/**
|
||||
* @brief Is this interface local?
|
||||
* @details When set, the interface is defined as local and not intended to be marshalled.
|
||||
* @return Returns 'true' when the interface is defined as local interface; otherwise returns 'false'.
|
||||
*/
|
||||
boolean IsLocal() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Operation entity
|
||||
*/
|
||||
interface IOperationEntity
|
||||
{
|
||||
/**
|
||||
* @brief Get parameter entity iterator if the definition has any parameters.
|
||||
* @return Returns a pointer to the parameter entity iterator or NULL when not available.
|
||||
*/
|
||||
IEntityIterator GetParameters();
|
||||
|
||||
/**
|
||||
* @brief Get the list of possible exceptions that might be fired for this operation.
|
||||
* @return Returns a pointer to the exception entity iterator or NULL when not available.
|
||||
*/
|
||||
IEntityIterator GetExceptions();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attribute entity
|
||||
*/
|
||||
interface IAttributeEntity
|
||||
{
|
||||
/**
|
||||
* @brief Get the list of possible exceptions that might be fired during a read operation.
|
||||
* @return Returns a pointer to the exception entity iterator or NULL when not available.
|
||||
*/
|
||||
IEntityIterator GetReadExceptions();
|
||||
|
||||
/**
|
||||
* @brief Get the list of possible exceptions that might be fired during a write operation.
|
||||
* @return Returns a pointer to the exception entity iterator or NULL when not available.
|
||||
*/
|
||||
IEntityIterator GetWriteExceptions();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parameter entity information interface.
|
||||
*/
|
||||
interface IParameterEntity
|
||||
{
|
||||
/**
|
||||
* @brief Parameter direction enumeration
|
||||
*/
|
||||
enum EParameterDirection : uint32
|
||||
{
|
||||
unknown, ///< The parameter direction is not known.
|
||||
input, ///< The parameter is defined as input parameter.
|
||||
output, ///< The parameter is defined as output parameter.
|
||||
in_out, ///< The parameter is defined as input and output parameter.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get the parameter direction.
|
||||
* @return Returns the parameter direction.
|
||||
*/
|
||||
EParameterDirection GetDirection() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enum entity information interface.
|
||||
*/
|
||||
interface IEnumEntity
|
||||
{
|
||||
/**
|
||||
* @brief Get the enumerator base type.
|
||||
* @param[out] reType Reference to the declaration type. The type if EEntityType::type_unknown if not available.
|
||||
* @param[out] rpType Reference to the interface pointer if the type is a complex type. Otherwise is NULL.
|
||||
*/
|
||||
void GetBaseType(out EDeclType reType, out IInterfaceAccess rpType) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Union entity information interface.
|
||||
*/
|
||||
interface IUnionEntity
|
||||
{
|
||||
/**
|
||||
* @brief The interpretation of the switch case.
|
||||
*/
|
||||
enum ESwitchInterpret : uint32
|
||||
{
|
||||
switch_variable, ///< The switch case is determined by a variable of the parent struct.
|
||||
switch_type, ///< The switch case is determined by the value of a type.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Return the switch interpretation.
|
||||
* @return The interpretation of the switch case of this union.
|
||||
*/
|
||||
ESwitchInterpret GetSwitchInterpretation() const;
|
||||
|
||||
/**
|
||||
* @brief Return type information for the switch case. If the switch case is type base, this is the type information
|
||||
* that is used to select. If the switch case is variable based, this is the type of the variable.
|
||||
* @param[out] reType Reference to the declaration type (either enum or an integral type).
|
||||
* @param[out] rpType Reference to the type entity if existing.
|
||||
*/
|
||||
void GetSwitchType(out EDeclType reType, out IInterfaceAccess rpType) const;
|
||||
|
||||
/**
|
||||
* @brief Get the switch variable information if the switch case is variable based. Will be empty/NULL when the switch
|
||||
* case is type based.
|
||||
* @param[out] rssVarStr Reference to the string receiving the exact scoped declaration name of the switch variable if
|
||||
* the interpretation is variable based. The variable name uses the scope separator '::' to define the common parent
|
||||
* definition and the member separator '.' to define the variable declaration as member from the common parent.
|
||||
* @param[out] rpVarEntity Reference to the variable entity if the interpretation is variable based.
|
||||
* @param[out] rpVarContainer Reference to the variable entity of the container of both the switch variable and the
|
||||
* union.
|
||||
*/
|
||||
void GetSwitchVar(out u8string rssVarStr, out IInterfaceAccess rpVarEntity,
|
||||
out IInterfaceAccess rpVarContainer) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Case entity information interface.
|
||||
*/
|
||||
interface ICaseEntity
|
||||
{
|
||||
/**
|
||||
* @brief Get the case label string. The case label string will be empty for the default case entry.
|
||||
* @return Returns the label (of not default).
|
||||
*/
|
||||
u8string GetLabel() const;
|
||||
|
||||
/**
|
||||
* @brief Is this case entry the default entry.
|
||||
* @return Return whether the case entry is the default entry.
|
||||
*/
|
||||
boolean IsDefault() const;
|
||||
};
|
||||
|
||||
}; // module idl
|
||||
}; // module sdv
|
||||
|
||||
253
export/interfaces/core_ps.idl
Normal file
253
export/interfaces/core_ps.idl
Normal file
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
* @file core_ps.idl
|
||||
* @brief This file provides the marshalling interface definitions of the core SDV framework.
|
||||
* @version 0.1
|
||||
* @date 2023.05.10
|
||||
* @author erik.verhoeven@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2023
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
#include "process.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Proxy/stub features
|
||||
*/
|
||||
module ps
|
||||
{
|
||||
/**
|
||||
* @brief Marshall exception.
|
||||
*/
|
||||
exception XMarshallExcept
|
||||
{};
|
||||
|
||||
/**
|
||||
* @brief Marshalling was not initialized.
|
||||
*/
|
||||
exception XMarshallNotInitialized : XMarshallExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Marshalling data between proxy and stub was not initialized or is in an invalid state.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Marshalling timeout exception.
|
||||
*/
|
||||
exception XMarshallTimeout : XMarshallExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The marshalling call was timed out.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Marshalling missing data.
|
||||
*/
|
||||
exception XMarshallMissingData : XMarshallExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Part of the marshalling data was lost during the marshalling call.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Incompatible interface version.
|
||||
*/
|
||||
exception XMarshallVersion : XMarshallExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The marshalling interfaces of objects have different versions and therefore cannot be connected.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Marshall data integrity violation.
|
||||
*/
|
||||
exception XMarshallIntegrity : XMarshallExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "An integrity violation has occurred during marshalling.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief No interface marshalling object found.
|
||||
*/
|
||||
exception XMarshallNoObject : XMarshallExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "No marshalling object for the interface found.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Marshalling flags.
|
||||
*/
|
||||
enum EMarshallFlags : uint32
|
||||
{
|
||||
direction_output = 0x10, ///< When set, direction is output. Otherwise direction is input. If an exception
|
||||
///< occurred, this flag might indicate if the exception occurred on input or on output
|
||||
///< of the call.
|
||||
exception_triggered = 0x80, ///< When set, a exception was triggered and is provided instead of any parameters
|
||||
///< or return value.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Marshall ID used for proxy and stub identification
|
||||
*/
|
||||
struct SMarshallID
|
||||
{
|
||||
uint32 uiHostID; ///< Reserved
|
||||
process::TProcessID tProcessID; ///< ProcessID
|
||||
uint32 uiIdent; ///< Identification value.
|
||||
uint32 uiControl; ///< Control value for 2nd pass identification.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Marshall object ID.
|
||||
*/
|
||||
typedef SMarshallID TMarshallID;
|
||||
|
||||
/**
|
||||
* @brief Marshalling header structure.
|
||||
* @details A marshall packet contains the information about the data being broadcasted. It must be the first packet
|
||||
* in a marshalled call.
|
||||
*/
|
||||
struct SMarshall
|
||||
{
|
||||
EEndian eEndian; ///< Describes whether the data is in big or in little endian.
|
||||
uint16 uiVersion; ///< Structure version (major * 100 + minor).
|
||||
interface_id tIfcId; ///< Interface id.
|
||||
uint32 uiFuncIndex; ///< Operation/attribute index.
|
||||
sequence<uint16> seqChecksums; ///< CRC-16 CCITT-FALSE checksums for each additional stream.
|
||||
uint32 uiFlags; ///< Bitmask with zero or more flags from EMarshallFlags.
|
||||
uint16 uiHdrChecksum; ///< CRC-16 CCITT-FALSE checksum over all data members above (not including
|
||||
///< uiChkSum itself).
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Marshalling data interpretation.
|
||||
*/
|
||||
enum EMarshallDataInterpret : uint32
|
||||
{
|
||||
input_data = 0, ///< The data is input data.
|
||||
output_data = 1, ///< The data is output data..
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Identical marshalling header containing only the address portion of the marshall structure.
|
||||
*/
|
||||
struct SMarshallAddress
|
||||
{
|
||||
EEndian eEndian; ///< Describes whether the data is in big or in little endian.
|
||||
uint16 uiVersion; ///< Structure version (major * 100 + minor).
|
||||
EMarshallDataInterpret eInterpret; ///< Defines the data interpretation.
|
||||
TMarshallID tProxyID; ///< Proxy id to identify the proxy this packet is sending from or destined to.
|
||||
TMarshallID tStubID; ///< Stub id to identify the stub this packet is destined to or receiving from.
|
||||
uint64 uiCallIndex; ///< Call index to uniquely identify the call.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Set the marshall object identification. The identification will be used to verify the proper sender/receiver.
|
||||
*/
|
||||
interface IMarshallObjectIdent
|
||||
{
|
||||
/**
|
||||
* @brief Set the identification.
|
||||
* @param[in] tMarshallID Reference to the marshall object ID. For a proxy object, this is the proxy ID. For a stub object
|
||||
* this is a stub ID.
|
||||
*/
|
||||
void SetIdentification(in TMarshallID tMarshallID);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Communication interface to broadcast a marshall packet to the receiver.
|
||||
*/
|
||||
local interface IMarshall
|
||||
{
|
||||
/**
|
||||
* @brief Marshall a function call.
|
||||
* @remarks This function call is synchronous and does not return until the call has been finalized or a timeout
|
||||
* exception has occurred.
|
||||
* @remarks The sequence contains all data to make the call. It is important that the data in the sequence is
|
||||
* complete and in the correct order.
|
||||
* @param[inout] seqInputData Reference to sequence of input data pointers. The first data pointer contains the
|
||||
* marshalling header. The second contains the parameters (if available) and the others contain raw data pointers
|
||||
* (if available). The call is allowed to change the sequence to be able to add additional information during the
|
||||
* communication without having to copy the existing data.
|
||||
* @return Sequence of output data pointers. The first data pointer contains the marshalling header. The second
|
||||
* contains the return value and parameters (if available) and the others contain raw data pointers (if available).
|
||||
*/
|
||||
sequence<pointer<uint8>> Call(inout sequence<pointer<uint8>> seqInputData);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Link/unlink a communication interface to/from the object.
|
||||
*/
|
||||
interface IMarshallLink
|
||||
{
|
||||
/**
|
||||
* @brief Link the communication interface to the object.
|
||||
* @remarks Only one link can exists at the time.
|
||||
* @param[in] pMarshall Interface to be linked.
|
||||
*/
|
||||
void Link(in IMarshall pMarshall);
|
||||
|
||||
/**
|
||||
* @brief Unlink the linked interface.
|
||||
*/
|
||||
void Unlink();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get the target interface from the proxy object.
|
||||
*/
|
||||
interface IProxyControl
|
||||
{
|
||||
/**
|
||||
* @brief Get the target interface from the proxy object.
|
||||
* @return The target interface.
|
||||
*/
|
||||
interface_t GetTargetInterface();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Link/unlink the object target interface to the stub object.
|
||||
*/
|
||||
interface IStubLink
|
||||
{
|
||||
/**
|
||||
* @brief Link the object target interface to the stub-object.
|
||||
* @remarks Only one link can exists at the time.
|
||||
* @param[in] ifc Interface to be linked.
|
||||
*/
|
||||
void Link(in interface_t ifc);
|
||||
|
||||
/**
|
||||
* @brief Unlink the linked interface.
|
||||
*/
|
||||
void Unlink();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Marshall access interface.
|
||||
*/
|
||||
interface IMarshallAccess
|
||||
{
|
||||
/**
|
||||
* @brief Get a proxy for the interface connection to the stub.
|
||||
* @param[in] tStubID Reference to the ID of the stub to connect to.
|
||||
* @param[in] id The interface ID to get the proxy for.
|
||||
* @return Returns the interface to the proxy object.
|
||||
*/
|
||||
interface_t GetProxy(in TMarshallID tStubID, in interface_id id) raises(XMarshallNoObject);
|
||||
|
||||
/**
|
||||
* @brief Get a stub for the interface with the supplied ID.
|
||||
* @param[in] ifc The interface to get the stub for..
|
||||
* @return Returns the Stub ID that is assigned to the interface. Or an empty ID when no stub could be found.
|
||||
*/
|
||||
TMarshallID GetStub(in interface_t ifc) raises(XMarshallNoObject);
|
||||
};
|
||||
}; // module ps
|
||||
}; // module sdv
|
||||
245
export/interfaces/core_types.idl
Normal file
245
export/interfaces/core_types.idl
Normal file
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* @file core_types.idl
|
||||
* @brief This file provides all data types for the core SDV framework.
|
||||
* @version 0.1
|
||||
* @date 2023.05.08
|
||||
* @author erik.verhoeven@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2023
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Current interface version.
|
||||
*/
|
||||
const uint32 SDVFrameworkInterfaceVersion = 100;
|
||||
|
||||
/**
|
||||
* @brief Current framework build version.
|
||||
*/
|
||||
const uint32 SDVFrameworkBuildVersion = 100;
|
||||
|
||||
/**
|
||||
* @brief Current framework sub-build version.
|
||||
*/
|
||||
const uint32 SDVFrameworkSubbuildVersion = 100;
|
||||
|
||||
#verbatim_begin
|
||||
/* Define SDV_SYMBOL_PUBLIC attribute for exported functions. */
|
||||
#if !defined(SDV_SYMBOL_PUBLIC) || !defined(SDV_SYMBOL_HIDDEN)
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#ifdef __GNUC__
|
||||
#define SDV_SYMBOL_PUBLIC __attribute__((dllexport))
|
||||
#else \
|
||||
#define SDV_SYMBOL_PUBLIC __declspec(dllexport)
|
||||
#endif
|
||||
#define SDV_SYMBOL_HIDDEN
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define SDV_SYMBOL_PUBLIC __attribute__((visibility("default"))) __attribute__((used))
|
||||
#define SDV_SYMBOL_HIDDEN __attribute__((visibility("hidden")))
|
||||
#else
|
||||
#define SDV_SYMBOL_PUBLIC /**< SDV_SYMBOL_PUBLIC: exportable function attribute */
|
||||
#define SDV_SYMBOL_HIDDEN /**< SDV_SYMBOL_HIDDEN: private function attribute */
|
||||
#endif
|
||||
#endif
|
||||
#endif /* !defined(SDV_SYMBOL_PUBLIC) || !defined(SDV_SYMBOL_HIDDEN) */
|
||||
|
||||
#ifdef __unix__
|
||||
#if _POSIX_C_SOURCE < 200809L
|
||||
#error POSIX version POSIX.1-2008 or higher needed
|
||||
#endif
|
||||
#endif
|
||||
#verbatim_end
|
||||
|
||||
#verbatim_begin
|
||||
#include "../support/interface.h"
|
||||
#include "../support/except.h"
|
||||
#verbatim_end
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Endian enum
|
||||
*/
|
||||
enum EEndian : uint8
|
||||
{
|
||||
big_endian = 0,
|
||||
little_endian = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief System exception.
|
||||
*/
|
||||
exception XSysExcept
|
||||
{};
|
||||
|
||||
/**
|
||||
* @brief Access to the function is denied exception.
|
||||
*/
|
||||
exception XAccessDenied : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Access denied.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The requested resource hasn't been found.
|
||||
*/
|
||||
exception XNotFound : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Resource not found.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The system is in an invalid state exception.
|
||||
*/
|
||||
exception XInvalidState : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The system is in an invalid state.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A timeout occurred exception.
|
||||
*/
|
||||
exception XTimeout : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "A timeout occurred.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief No interface found exception.
|
||||
*/
|
||||
exception XNoInterface : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The interface could not be found.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invalid index (index >= size or index < 0).
|
||||
*/
|
||||
exception XIndexOutOfRange : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The supplied index was out of range.";
|
||||
|
||||
uint32 uiIndex; ///< Index
|
||||
uint32 uiSize; ///< Size
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invalid iterator.
|
||||
*/
|
||||
exception XInvalidIterator : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The supplied iterator was invalid.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Null pointer.
|
||||
*/
|
||||
exception XNullPointer : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "A NULL-pointer was supplied.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invalid value for the reference counter.
|
||||
*/
|
||||
exception XInvalidRefCount : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The reference counter has an invalid/unexpected value.";
|
||||
|
||||
uint32 uiCount; ///< Reference counter value.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Buffer is too small.
|
||||
*/
|
||||
exception XBufferTooSmall : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The buffer was too small to store the data.";
|
||||
|
||||
uint64 uiSize; ///< Requested size.
|
||||
uint64 uiCapacity; ///< Size of the buffer.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Hash value doesn't match.
|
||||
*/
|
||||
exception XHashNotMatching : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The provided hash value doesn't match to the calculated hash value.";
|
||||
|
||||
uint64 uiCalculated; ///< Calculated hash value.
|
||||
uint64 uiProvided; ///< Provided hash value.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Offset out of range.
|
||||
*/
|
||||
exception XOffsetPastBufferSize : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The provided offset doesn't is not pointing to a location within the buffer.";
|
||||
|
||||
uint64 uiOffset; ///< Offset value.
|
||||
uint64 uiSize; ///< Buffer size.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Unknown exception.
|
||||
*/
|
||||
exception XUnknownException : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "An exception was fired, but no handler found for it.";
|
||||
|
||||
exception_id unknown_id; ///< The ID of the unknown exception.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Unhandled exception.
|
||||
*/
|
||||
exception XUnhandledException : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "An unhandled exception was caught.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
/**
|
||||
* @brief No memory manager available exception.
|
||||
*/
|
||||
exception XNoMemMgr : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The memory manager could not be accessed.";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Allocation failed exception
|
||||
*/
|
||||
exception XAllocFailed : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "The allocation of memory failed.";
|
||||
|
||||
uint32 uiSize; ///< Size of the allocation.
|
||||
};
|
||||
};
|
||||
};
|
||||
215
export/interfaces/dispatch.idl
Normal file
215
export/interfaces/dispatch.idl
Normal file
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
*
|
||||
* @file dispatch.idl
|
||||
* @brief This file provides interfaces related to the data dispatch service.
|
||||
* @version 1.0
|
||||
* @date 2024.01.12
|
||||
* @author Erik Verhoeven
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2024
|
||||
*
|
||||
*/
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
/**
|
||||
* @brief This interface is called by the data link component transmitting and receiving signals.
|
||||
* @remarks This interface is for local use only.
|
||||
*/
|
||||
local interface ISignalTransmission
|
||||
{
|
||||
/**
|
||||
* @brief Trigger behavior enumeration.
|
||||
*/
|
||||
enum ETxTriggerBehavior : uint32
|
||||
{
|
||||
none = 0, ///< No specific behavior
|
||||
spontaneous = 1, ///< Trigger when signal value change occurs
|
||||
periodic_if_active = 2, ///< Trigger periodically, but only when signal differs from default value.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a TX trigger object that defines how to trigger the signal transmission.
|
||||
* @param[in] uiCycleTime When set to any value other than 0, provides a cyclic trigger (ms). Could be 0 if cyclic
|
||||
* triggering is not required.
|
||||
* @param[in] uiDelayTime When set to any value other than 0, ensures a minimum time between two triggers. Could be 0
|
||||
* if minimum time should not be enforced.
|
||||
* @param[in] uiBehaviorFlags Zero or more flags from ETxTriggerBehavior.
|
||||
* @param[in] pTriggerCallback Pointer to the trigger callback object. This object needs to expose the
|
||||
* ITxTriggerCallback interface. This interface must stay valid during the lifetime of the generated trigger object.
|
||||
* @returns On success, returns an interface to the trigger object. Use the ITxTrigger interface to assign signals to
|
||||
* the trigger. Returns null when a trigger was requested without cycletime and without trigger behavior (which would
|
||||
* mean it would never trigger). Use IObjectDestroy to destroy the trigger object.
|
||||
*/
|
||||
IInterfaceAccess CreateTxTrigger(in uint32 uiCycleTime, in uint32 uiDelayTime, in uint32 uiBehaviorFlags,
|
||||
in IInterfaceAccess pTriggerCallback);
|
||||
|
||||
/**
|
||||
* @brief Register a signal for sending over the network; reading from the dispatch service. Data is provided by the
|
||||
* signal publisher and dependable on the requested behavior stored until it is sent.
|
||||
* @remarks Multiple registrations of the same signal are allowed.
|
||||
* @param[in] ssSignalName Name of the signal. To guarantee uniqueness, it is preferred to add the group hierarchy to
|
||||
* the signal name separated by a dot. E.g. with CAN: MAB.BcmChas1Fr03.SteerReCtrlReqAgReq
|
||||
* @param[in] anyDefVal The default value of the signal.
|
||||
* @return Returns the IInterfaceAccess interface that allows access to the ISignalRead interface for reading the
|
||||
* signal value. Use IObjectDestroy to destroy the signal object.
|
||||
*/
|
||||
IInterfaceAccess RegisterTxSignal(in u8string ssSignalName, in any anyDefVal);
|
||||
|
||||
/**
|
||||
* @brief Register a signal for reception over the network; providing to the dispatch service.
|
||||
* @remarks Multiple registrations of the same signal are allowed.
|
||||
* @param[in] ssSignalName Name of the signal. To guarantee uniqueness, it is preferred to add the group hierarchy to
|
||||
* the signal name separated by a dot. E.g. with CAN: MAB.BcmChas1Fr03.SteerReCtrlReqAgReq
|
||||
* @return Returns the IInterfaceAccess interface that allows access to the ISignalWrite interface for writing the
|
||||
* signal value. Use IObjectDestroy to destroy the signal object.
|
||||
*/
|
||||
IInterfaceAccess RegisterRxSignal(in u8string ssSignalName);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to add and remove signals to the trigger object.
|
||||
*/
|
||||
interface ITxTrigger
|
||||
{
|
||||
/**
|
||||
* @brief Add a signal to the trigger object. The signal must be registered as TX signal before.
|
||||
* @param[in] ssSignalName Name of the signal.
|
||||
* @return Returns whether adding the signal was successful.
|
||||
*/
|
||||
boolean AddSignal(in u8string ssSignalName);
|
||||
|
||||
/**
|
||||
* @brief Remove a signal from the trigger object.
|
||||
* @param[in] ssSignalName Name of the signal.
|
||||
*/
|
||||
void RemoveSignal(in u8string ssSignalName);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Trigger interface to be implemented by the caller to the trigger creation function.
|
||||
*/
|
||||
interface ITxTriggerCallback
|
||||
{
|
||||
/**
|
||||
* @brief Execute the trigger.
|
||||
*/
|
||||
void Execute();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Signal type enumeration.
|
||||
*/
|
||||
enum ESignalDirection
|
||||
{
|
||||
sigdir_tx, ///< Signal is a transmission-signal. Use a publisher to transmit data.
|
||||
sigdir_rx, ///< Signal is a reception-signal. Use a subscriber to receive data.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Signal registration entry function to be used in the GetRegisteredSignals function.
|
||||
*/
|
||||
struct SSignalRegistration
|
||||
{
|
||||
u8string ssName; ///< Name of the signal.
|
||||
ESignalDirection eType; ///< Registration type.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Access a previously registered signal. This interface is called by the devices providing and receiving the
|
||||
* signals.
|
||||
*/
|
||||
local interface ISignalAccess
|
||||
{
|
||||
/**
|
||||
* @brief Requested a registered signal for publication (send signal).
|
||||
* @param[in] ssSignalName Name of the signal. To guarantee uniqueness, it is preferred to add the group hierarchy to
|
||||
* the signal name separated by a dot. E.g. with CAN: MAB.BcmChas1Fr03.SteerReCtrlReqAgReq
|
||||
* @return Returns the IInterfaceAccess interface that allows access to the ISignalWrite interface for writing the
|
||||
* signal value.
|
||||
*/
|
||||
IInterfaceAccess RequestSignalPublisher(in u8string ssSignalName);
|
||||
|
||||
/**
|
||||
* @brief Add a registered signal for subscription (receive signal).
|
||||
* @param[in] ssSignalName Name of the signal. To guarantee uniqueness, it is preferred to add the group hierarchy to
|
||||
* the signal name separated by a dot. E.g. with CAN: MAB.BcmChas1Fr03.SteerReCtrlReqAgReq
|
||||
* @param[in] pSubscriber Pointer to the IInterfaceAccess of the subscriber. The subscriber should implement the
|
||||
* ISignalReceiveEvent interface.
|
||||
* @return Returns an interface that can be used to manage the subscription. Use IObjectDestroy to destroy the signal
|
||||
* object.
|
||||
*/
|
||||
IInterfaceAccess AddSignalSubscription(in u8string ssSignalName, in IInterfaceAccess pSubscriber);
|
||||
|
||||
/**
|
||||
* @brief Get a list of registered signals.
|
||||
* @return List of registration functions.
|
||||
*/
|
||||
sequence<SSignalRegistration> GetRegisteredSignals() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to allow transacted updates as well as transacted readings without the interference of another update.
|
||||
*/
|
||||
local interface IDispatchTransaction
|
||||
{
|
||||
/**
|
||||
* @brief Create a transaction.
|
||||
* @details When starting a group transaction, any writing to a signal will not be reflected yet until the transaction
|
||||
* is finalized. For the data link layer, this also allows freezing the reading values until all values have been read.
|
||||
* @return Returns the transaction interface or NULL when the transaction could not be started. Use IObjectDestroy to
|
||||
* destroy the transaction object.
|
||||
*/
|
||||
IInterfaceAccess CreateTransaction();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to update a signal value.
|
||||
*/
|
||||
local interface ISignalWrite
|
||||
{
|
||||
/**
|
||||
* @brief Update the signal value.
|
||||
* @param[in] anyVal The value to update the signal with.
|
||||
* @param[in] pTransaction The transaction interface. Could be NULL in case the update should occur immediately.
|
||||
*/
|
||||
void Write(in any anyVal, in IInterfaceAccess pTransaction);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to read a signal value.
|
||||
* @remarks This interface is only accessible by the link layer.
|
||||
*/
|
||||
local interface ISignalRead
|
||||
{
|
||||
/**
|
||||
* @brief Get the signal value.
|
||||
* @param[in] pTransaction The transaction interface. Could be NULL in case the most up-to-date value is requested.
|
||||
* @return Returns the value.
|
||||
*/
|
||||
any Read(in IInterfaceAccess pTransaction) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Inform, that a signal value has been received.
|
||||
* @remarks This interface is to be implemented by the device to receive signal values.
|
||||
*/
|
||||
local interface ISignalReceiveEvent
|
||||
{
|
||||
/**
|
||||
* @brief A signal value was received.
|
||||
* @param[in] anyVal The signal value.
|
||||
*/
|
||||
void Receive(in any anyVal);
|
||||
};
|
||||
|
||||
}; // core module
|
||||
}; // sdv module
|
||||
36
export/interfaces/hw_ident.idl
Normal file
36
export/interfaces/hw_ident.idl
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file hw_ident.idl
|
||||
* @author Erik Verhoeven DISDS1 (mailto:erik.verhoeven@zf.com)
|
||||
* @brief This file includes all the interfaces used for hardware identification.
|
||||
* @version 1.0
|
||||
* @date 2024-05-09
|
||||
*
|
||||
* @copyright Copyright ZF Friedrichshafen AG (c) 2023-2025
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Hardware specific features.
|
||||
*/
|
||||
module hardware
|
||||
{
|
||||
/**
|
||||
* @brief Interface to obtain Hardware ID
|
||||
*/
|
||||
interface IHardwareID
|
||||
{
|
||||
/**
|
||||
* @brief Gets the hardware ID of the current hardware.
|
||||
* It's same for the all processes running in the same hardware and different for the processes of each different hardwares.
|
||||
* @return Returns the hardware ID or 0 in case of failure.
|
||||
*/
|
||||
uint64 GetHardwareID();
|
||||
};
|
||||
};
|
||||
};
|
||||
184
export/interfaces/ipc.idl
Normal file
184
export/interfaces/ipc.idl
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* @file ipc.idl
|
||||
* @author Erik Verhoeven DISDS1 (mailto:erik.verhoeven@zf.com)
|
||||
* @brief This file includes all the interfaces used for interpprocess communication.
|
||||
* @version 1.0
|
||||
* @date 2024-05-09
|
||||
*
|
||||
* @copyright Copyright ZF Friedrichshafen AG (c) 2023-2025
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Interprocess communication features.
|
||||
*/
|
||||
module ipc
|
||||
{
|
||||
/**
|
||||
* @brief structure of IPC Connection to which a client can attach.
|
||||
*/
|
||||
struct SChannelEndpoint
|
||||
{
|
||||
IInterfaceAccess pConnection; ///< Connection object
|
||||
u8string ssConnectString; ///< Parameter string used by other participant to establish a connection. The
|
||||
///< parameter string is a TOMl description containing the identification of the
|
||||
///< provider among with provider specific connection details. The provider
|
||||
///< identification must be similar to the following example:
|
||||
///< @code
|
||||
///< [Provider]
|
||||
///< Name = "DefaultSharedMemoryChannelControl"
|
||||
///< @endcode
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface for creating an IPC connection, which other participants can connect to via IChannelAccess
|
||||
*/
|
||||
interface ICreateEndpoint
|
||||
{
|
||||
/**
|
||||
* @brief Create IPC connection object and return the endpoint information.
|
||||
* @post Use AsyncConnect on SChannelEndpoint::pConnection to initiate the connection.
|
||||
* @param[in] ssChannelConfig Optional channel type specific endpoint configuration. The configuration is a TOML base
|
||||
* description specific to the provider.
|
||||
* @return IPC connection object
|
||||
*/
|
||||
SChannelEndpoint CreateEndpoint(in u8string ssChannelConfig);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface local IPC access.
|
||||
*/
|
||||
interface IChannelAccess
|
||||
{
|
||||
/**
|
||||
* @brief Create a connection object from the channel connection parameters string.
|
||||
* @post Use AsyncConnect to initiate the connection.
|
||||
* @param[in] ssConnectString Reference to the string containing the channel connection parameters returned by the
|
||||
* ICreateEndpoint::CreateEndpoint function or a TOML configuration that is provider specific and describes clearly the
|
||||
* access to a running channel. This configuriration is identical (or similar) to the configuration supplied to the
|
||||
* ICreateEndpoint::CreateEndpoint function.
|
||||
* @return Pointer to IInterfaceAccess interface of the connection object or NULL when the object cannot be created.
|
||||
*/
|
||||
IInterfaceAccess Access(in u8string ssConnectString);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Connection status enumeration
|
||||
*/
|
||||
enum EConnectStatus : uint32
|
||||
{
|
||||
uninitialized = 0, ///< Initialization via IConnect pending/required
|
||||
initializing = 1, ///< Initiation channel access.
|
||||
initialized = 2, ///< Channel access initialized.
|
||||
connecting = 10, ///< Both participants are available, connecting started
|
||||
negotiating = 20, ///< Negotiating the connection
|
||||
connection_error = 990, ///< Connection error; negotiation failed
|
||||
connected = 11, ///< Connection successful
|
||||
communication_error = 991, ///< Communication error
|
||||
disconnected = 30, ///< Connection terminated due to disconnection of other participant
|
||||
disconnected_forced = 32, ///< Connection terminated due to unplanned disconnection of other participant
|
||||
terminating = 90, ///< Termination of channel access (through IObjectDestroy::DestroyObject)
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Interface for managing IPC connection.
|
||||
*/
|
||||
interface IConnect
|
||||
{
|
||||
/**
|
||||
* @brief Establish a connection and start sending/receiving messages.
|
||||
* @param[in] pReceiver Callback interface for receiving data and connect status.
|
||||
* @return Returns 'true' when a channel connection could be initiated. Use GetStatus or IConnectEventCallback to
|
||||
* check the connection state.
|
||||
*/
|
||||
boolean AsyncConnect(in IInterfaceAccess pReceiver);
|
||||
|
||||
/**
|
||||
* @brief Wait for a connection to take place.
|
||||
* @param[in] uiWaitMs Wait for a connection to take place. A value of 0 doesn't wait at all, a value of 0xffffffff
|
||||
* waits for infinite time.
|
||||
* @return Returns 'true' when a connection took place.
|
||||
*/
|
||||
boolean WaitForConnection(in uint32 uiWaitMs);
|
||||
|
||||
/**
|
||||
* @brief Cancel a wait for connection.
|
||||
*/
|
||||
void CancelWait();
|
||||
|
||||
/**
|
||||
* @brief Disconnect from a connection. This will set the connect status to disconnected and release the interface
|
||||
* used for the status events.
|
||||
*/
|
||||
void Disconnect();
|
||||
|
||||
/**
|
||||
* @brief Register event callback interface.
|
||||
* @details Register a connection status event callback interface. The exposed interface must be of type
|
||||
* IConnectEventCallback. The registration will exist until a call to the unregister function with the returned cookie
|
||||
* or until the connection is terminated.
|
||||
* @param[in] pEventCallback Pointer to the object exposing the IConnectEventCallback interface.
|
||||
* @return The cookie assigned to the registration or 0 when the registration wasn't successful.
|
||||
*/
|
||||
uint64 RegisterStatusEventCallback(in IInterfaceAccess pEventCallback);
|
||||
|
||||
/**
|
||||
* @brief Unregister the status event callback with the returned cookie from the registration.
|
||||
* @param[in] uiCookie The cookie returned by a previous call to the registration function.
|
||||
*/
|
||||
void UnregisterStatusEventCallback(in uint64 uiCookie);
|
||||
|
||||
/**
|
||||
* @brief Gets the current status of the IPC whether it is initialized/connected/disconnected or having connection
|
||||
* error.
|
||||
* @return Returns retrieved status of the IPC.
|
||||
*/
|
||||
EConnectStatus GetStatus() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface implemented by the connecting object to receive channel connection events.
|
||||
*/
|
||||
interface IConnectEventCallback
|
||||
{
|
||||
/**
|
||||
* @brief Set the current status.
|
||||
* @param[in] eConnectStatus The connection status.
|
||||
*/
|
||||
void SetStatus(in EConnectStatus eConnectStatus);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface implemented by the channel connection object for sending messages through a channel.
|
||||
*/
|
||||
interface IDataSend
|
||||
{
|
||||
/**
|
||||
* @brief Sends data consisting of multiple data chunks via the IPC connection.
|
||||
* @param[inout] seqData Sequence of data buffers to be sent. The sequence might be changed to optimize the
|
||||
* communication without having to copy the data.
|
||||
* @return Return 'true' if all data could be sent; 'false' otherwise.
|
||||
*/
|
||||
boolean SendData(inout sequence<pointer<uint8>> seqData);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface implemented by the connecting object that allows receiving messages.
|
||||
*/
|
||||
interface IDataReceiveCallback
|
||||
{
|
||||
/**
|
||||
* @brief Callback to be called by the IPC connection when receiving a data packet.
|
||||
* @param[inout] seqData Sequence of data buffers to received. The sequence might be changed to optimize the
|
||||
* communication without having to copy the data.
|
||||
*/
|
||||
void ReceiveData(inout sequence<pointer<uint8>> seqData);
|
||||
};
|
||||
}; // module ipc
|
||||
}; // module sdv
|
||||
107
export/interfaces/log.idl
Normal file
107
export/interfaces/log.idl
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @file log.idl
|
||||
* @author Erik Verhoeven DISDS1 (mailto:erik.verhoeven@zf.com)
|
||||
* @brief This file includes all the interfaces used for logging information.
|
||||
* @version 1.0
|
||||
* @date 2024-05-09
|
||||
*
|
||||
* @copyright Copyright ZF Friedrichshafen AG (c) 2023-2025
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
#include "process.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
/**
|
||||
* @brief Enumeration for the severity level of the logging from sdv platform abstraction
|
||||
*/
|
||||
enum ELogSeverity : uint32
|
||||
{
|
||||
trace = 1, ///< level: this is a code smell if used in production. This should be used during development to track
|
||||
///< bugs, but never committed to your VCS.
|
||||
debug = 2, ///< level: log at this level about anything that happens in the program. This is mostly used during
|
||||
///< debugging, and I'd advocate trimming down the number of debug statement before entering the production
|
||||
///< stage, so that only the most meaningful entries are left, and can be activated during troubleshooting.
|
||||
info = 3, ///< level: log at this level all actions that are user-driven, or system specific (i.e. regularly scheduled
|
||||
///< operations...)
|
||||
///< (not included) NOTICE level: this will certainly be the level at which the program will run when in production.
|
||||
///< Log at this level all the notable events that are not considered an error.
|
||||
warning = 4, ///< level: log at this level all events that could potentially become an error. For instance if one
|
||||
///< database call took more than a predefined time, or if an in-memory cache is near capacity. This
|
||||
///< will allow proper automated alerting, and during troubleshooting will allow to better understand
|
||||
///< how the system was behaving before the failure.
|
||||
error = 5, ///< level: log every error condition at this level. That can be API calls that return errors or internal
|
||||
///< error conditions.
|
||||
fatal = 6 ///< level: too bad, it's doomsday. Use this very scarcely, this shouldn't happen a lot in a real program.
|
||||
///< Usually logging at this level signifies the end of the program. For instance, if a network daemon
|
||||
///< can't bind a network socket, log at this level and exit is the only sensible thing to do.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to configure the logger.
|
||||
*/
|
||||
interface ILoggerConfig
|
||||
{
|
||||
/**
|
||||
* @brief Initialize the logging from sdv platform abstraction.
|
||||
* @details This function needs to be called before starting to log.
|
||||
* @param[in] ssTag Provided tag to create log.
|
||||
*/
|
||||
void SetProgramTag(in u8string ssTag);
|
||||
|
||||
/**
|
||||
* @brief Get the program tag used for logging.
|
||||
* @return The string containing the program tag.
|
||||
*/
|
||||
u8string GetProgramTag() const;
|
||||
|
||||
/**
|
||||
* @brief Filter the log messages based on severity.
|
||||
* @param[in] eSeverity The severity level to use as a lowest level for logging. Default is "info" meaning, that
|
||||
* debug and trace messages will not be logged.
|
||||
* @param[in] eViewSeverity The severity level to use as a lowest level for viewing. Default is "error" meaning, that
|
||||
* debug, trace, info, warning and error messages will not be shown in console output.
|
||||
*/
|
||||
void SetLogFilter(in ELogSeverity eSeverity, in ELogSeverity eViewSeverity);
|
||||
|
||||
/**
|
||||
* @brief Get the current log severity filter level.
|
||||
* @return The severity level of the log filter.
|
||||
*/
|
||||
ELogSeverity GetLogFilter() const;
|
||||
|
||||
/**
|
||||
* @brief Get the current view severity level.
|
||||
* @return The severity level of the view filter.
|
||||
*/
|
||||
ELogSeverity GetViewFilter() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to enable logging information from sdv platform abstraction
|
||||
*/
|
||||
interface ILogger
|
||||
{
|
||||
/**
|
||||
* @brief Log a message to the SDV log.
|
||||
* @param[in] eSeverity Severity level of the log message which will be logged, e.g. info, warning, error etc.
|
||||
* @param[in] ssSrcFile The source file that caused the log entry.
|
||||
* @param[in] iSrcLine The line number in the source file that caused the log entry.
|
||||
* @param[in] tProcessID Process ID of the process reporting this log entry.
|
||||
* @param[in] ssObjectName Name of the object if the log entry is supplied by a component.
|
||||
* @param[in] ssMessage The log message that will be logged.
|
||||
*/
|
||||
void Log(in ELogSeverity eSeverity, in u8string ssSrcFile, in uint32 iSrcLine, in process::TProcessID tProcessID,
|
||||
in u8string ssObjectName, in u8string ssMessage);
|
||||
};
|
||||
};
|
||||
};
|
||||
36
export/interfaces/mem.idl
Normal file
36
export/interfaces/mem.idl
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file mem.idl
|
||||
* @brief This file provides the memory management interface definitions of the core SDV framework.
|
||||
* @version 0.1
|
||||
* @date 2023.05.22
|
||||
* @author erik.verhoeven@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2023
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
/**
|
||||
* @brief Memory allocation interface.
|
||||
* @attention This interface is not intended to be marshalled.
|
||||
*/
|
||||
local interface IMemoryAlloc
|
||||
{
|
||||
/**
|
||||
* @brief Allocate a memory block of the provided length.
|
||||
* @param[in] uiLength The length of the memory block to allocate.
|
||||
* @return Smart pointer to the memory allocation or NULL when allocating was not possible.
|
||||
*/
|
||||
pointer<uint8> Allocate(in uint32 uiLength);
|
||||
};
|
||||
};
|
||||
};
|
||||
125
export/interfaces/module.idl
Normal file
125
export/interfaces/module.idl
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @file module.idl
|
||||
* @author Erik Verhoeven FRD DISDS1 (mailto:erik.verhoeven@zf.com)
|
||||
* @brief This file includes all the interfaces used for module management
|
||||
* @version 1.0
|
||||
* @date 2024-05-02
|
||||
*
|
||||
* @copyright Copyright ZF Friedrichshafen AG (c) 2023-2025
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
/**
|
||||
* @brief Module ID.
|
||||
*/
|
||||
typedef uint64 TModuleID;
|
||||
|
||||
/**
|
||||
* @brief Special module ID for the Core Library module.
|
||||
*/
|
||||
const TModuleID tCoreLibModule = 0xffffffffffffffffu;
|
||||
|
||||
/**
|
||||
* @brief Interface for module control.
|
||||
* @attention This interface is accessible by standalone and essential apps.
|
||||
*/
|
||||
interface IModuleControl
|
||||
{
|
||||
/**
|
||||
* @brief Load a module with the provided path containing SDV components. The components are available for creation
|
||||
* through the repository.
|
||||
* @attention Only modules with exposed SDV functions and the correct interface version can be loaded.
|
||||
* @details This method can be used to load a module by providing a path to SDV components. Upon successful loading it
|
||||
* will return the ID of the module. If the module Path is wrong/invalid or empty, module cannot not be loaded and 0 is
|
||||
* returned. If the module is successfully loaded once and same module is loaded again the same module ID is returned.
|
||||
* @param[in] ssModulePath Path to the module to load.
|
||||
* @return Returns the ID of the module or 0 if the module could not be loaded.
|
||||
*/
|
||||
TModuleID Load(in u8string ssModulePath);
|
||||
|
||||
/**
|
||||
* @brief Unload the module by providing module ID. The function will request the repository to shutdown any running
|
||||
* component. If there are no components running any more, the module will be unloaded.
|
||||
* @param[in] tModuleID Id representing a module, which has previous been loaded by Load
|
||||
* @return Returns 'true' when unloading was successful or the module was unloaded before already. Returns 'false' in
|
||||
* case the module could not be unloaded due to having active objects.
|
||||
*/
|
||||
boolean Unload(in TModuleID tModuleID);
|
||||
|
||||
/**
|
||||
* @brief Checks for active objects - if active objects are present in a module, the module (currently) cannot be
|
||||
* unloaded via Unload.
|
||||
* @param[in] tModuleID Id representing a module, which has previous been loaded by Load(ModulePath)
|
||||
* @return Returns true if the module is currently loaded and it contains at least one loaded object and false
|
||||
* otherwise.
|
||||
*
|
||||
* @details The module exposes the symbol HasActiveObjects defined in
|
||||
* export/support/component_impl.h, which is to be used in order to determine whether or not
|
||||
* active objects remain within the module
|
||||
*/
|
||||
boolean HasActiveObjects(in TModuleID tModuleID) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modukle control configuration interface.
|
||||
*/
|
||||
interface IModuleControlConfig
|
||||
{
|
||||
/**
|
||||
* @brief Add a search path to a folder where modules can be found.
|
||||
* @param[in] ssDir Relative (to the executable) or absolute path to an existing folder.
|
||||
* @return Returns 'true' if folder exists; otherwise 'false'.
|
||||
*/
|
||||
boolean AddModuleSearchDir(in u8string ssDir);
|
||||
|
||||
/**
|
||||
* @brief Get a sequence containing the current module search directories.
|
||||
* @return The sequence with the module search directories.
|
||||
*/
|
||||
sequence<u8string> GetModuleSearchDirs() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Loaded component module information.
|
||||
*/
|
||||
struct SModuleInfo
|
||||
{
|
||||
TModuleID tModuleID; ///< The ID of the module.
|
||||
u8string ssPath; ///< The full path to the module.
|
||||
u8string ssFilename; ///< The module file name.
|
||||
uint32 uiVersion; ///< The module version.
|
||||
boolean bActive; ///< Boolean indicating whether or not objects are loaded.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Module information access.
|
||||
*/
|
||||
interface IModuleInfo
|
||||
{
|
||||
/**
|
||||
* @brief Get a list of loaded modules.
|
||||
* @return Sequence with the module information structures.
|
||||
*/
|
||||
sequence<SModuleInfo> GetModuleList() const;
|
||||
|
||||
/**
|
||||
* @brief Get a list of classes exposed by the provided module.
|
||||
* @param[in] tModuleID The module ID to request the list of classes for.
|
||||
* @return Sequence with the class information structures.
|
||||
*/
|
||||
sequence<SClassInfo> GetClassList(in TModuleID tModuleID) const;
|
||||
};
|
||||
};
|
||||
};
|
||||
119
export/interfaces/process.idl
Normal file
119
export/interfaces/process.idl
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @file process.idl
|
||||
* @author Erik Verhoeven DISDS1 (mailto:erik.verhoeven@zf.com)
|
||||
* @brief This file includes all the interfaces used for process creation.
|
||||
* @version 1.0
|
||||
* @date 2024-05-09
|
||||
*
|
||||
* @copyright Copyright ZF Friedrichshafen AG (c) 2023-2025
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Process features.
|
||||
*/
|
||||
module process
|
||||
{
|
||||
/**
|
||||
* @brief Process ID.
|
||||
*/
|
||||
typedef uint32 TProcessID;
|
||||
|
||||
/**
|
||||
* @brief Process termination callback.
|
||||
*/
|
||||
local interface IProcessLifetimeCallback
|
||||
{
|
||||
/**
|
||||
* @brief Called when the process was terminated.
|
||||
* @remarks The process return value is not always valid. The validity depends on the support of the underlying system.
|
||||
* @param[in] tProcessID The process ID of the process being terminated.
|
||||
* @param[in] iRetValue Process return value or 0 when not supported.
|
||||
*/
|
||||
void ProcessTerminated(in TProcessID tProcessID, in int64 iRetValue);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Process lifetime monitoring.
|
||||
*/
|
||||
local interface IProcessLifetime
|
||||
{
|
||||
/**
|
||||
* @brief Register a process lifetime monitor.
|
||||
* @param[in] tProcessID Process ID to monitor the lifetime for.
|
||||
* @param[in] pMonitor Pointer to the monitor interface. The monitor should expose the IProcessLifetimeCallback
|
||||
* interface.
|
||||
* @return Returns a non-zero cookie when successful; zero when not.
|
||||
*/
|
||||
uint32 RegisterMonitor(in TProcessID tProcessID, in IInterfaceAccess pMonitor);
|
||||
|
||||
/**
|
||||
* @brief Unregistered a previously registered monitor.
|
||||
* @param[in] uiCookie The cookie from the monitor registration.
|
||||
*/
|
||||
void UnregisterMonitor(in uint32 uiCookie);
|
||||
|
||||
/**
|
||||
* @brief Wait for a process to finalize.
|
||||
* @param[in] tProcessID The process ID to wait for.
|
||||
* @param[in] uiWaitMs Maximum time to wait in ms. Could be 0xffffffff to wait indefintely.
|
||||
* @return Returns 'true' when the process was terminated (or isn't running), 'false' when still running and a timeout
|
||||
* has occurred.
|
||||
*/
|
||||
boolean WaitForTerminate(in TProcessID tProcessID, in uint32 uiWaitMs);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Process rights during process creation
|
||||
*/
|
||||
enum EProcessRights : uint32
|
||||
{
|
||||
default_rights = 0, ///< Default rights - for 'main' application the process is started using reduced rights, for a
|
||||
///< standalone application the parent rights are used.
|
||||
parent_rights = 10, ///< Same rights as the parent process
|
||||
reduced_rights = 20, ///< Reduced rights
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface for process control. This interface is accessible by 'main' and 'standalone' applications only.
|
||||
*/
|
||||
local interface IProcessControl
|
||||
{
|
||||
/**
|
||||
* @brief Execute a process.
|
||||
* @param[in] ssModule Module name of the process executable.
|
||||
* @param[in] seqArgs Instantiation arguments to supply to the process.
|
||||
* @param[in] eRights The process rights during instantiation.
|
||||
* @return Returns the process ID or 0 when process creation failed.
|
||||
*/
|
||||
TProcessID Execute(in u8string ssModule, in sequence<u8string> seqArgs, in EProcessRights eRights);
|
||||
|
||||
/**
|
||||
* @brief Terminate the process.
|
||||
* @attention Use this function as a last resort only. The process will be killed and anything unsaved will render
|
||||
* invalid.
|
||||
* @param[in] tProcessID The process ID of the process to terminate.
|
||||
* @return Returns 'true' if termination was successful; returns 'false' if termination was not possible or not allowed.
|
||||
*/
|
||||
boolean Terminate(in TProcessID tProcessID);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface for process information.
|
||||
*/
|
||||
local interface IProcessInfo
|
||||
{
|
||||
/**
|
||||
* @brief Gets the process ID of the own process.
|
||||
* @return Return the process ID.
|
||||
*/
|
||||
TProcessID GetProcessID() const;
|
||||
};
|
||||
};
|
||||
};
|
||||
248
export/interfaces/repository.idl
Normal file
248
export/interfaces/repository.idl
Normal file
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
*
|
||||
* @file repository.idl
|
||||
* @brief This file provides interfaces related to the repository service
|
||||
* @version 0.1
|
||||
* @date 2022.11.21
|
||||
* @author steffen.altmeier@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2022
|
||||
*
|
||||
*/
|
||||
#include "core.idl"
|
||||
#include "module.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Object ID.
|
||||
*/
|
||||
typedef uint64 TObjectID;
|
||||
|
||||
/**
|
||||
* @brief Interface used to access objects from other modules via the repository service
|
||||
*/
|
||||
interface IObjectAccess
|
||||
{
|
||||
/**
|
||||
* @brief Get the object instance previously created through the repository service.
|
||||
* @param[in] ssObjectName The name of the requested object.
|
||||
* @return Returns the IInterfaceAccess interface of the object instance if found and nullptr otherwise.
|
||||
*/
|
||||
IInterfaceAccess GetObject(in u8string ssObjectName);
|
||||
|
||||
/**
|
||||
* @brief Get the object instance previously created through the repository service.
|
||||
* @attention Utilities cannot be returned by this function.
|
||||
* @param[in] tObjectID The ID of the requested object.
|
||||
* @return Returns the IInterfaceAccess interface of the object instance if found and nullptr otherwise.
|
||||
*/
|
||||
IInterfaceAccess GetObjectByID(in TObjectID tObjectID);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Object information flags.
|
||||
*/
|
||||
enum EObjectInfoFlags : uint32
|
||||
{
|
||||
object_foreign = 0x00000100, ///< The object is registered as a foreign object.
|
||||
object_controlled = 0x00008000, ///< The object is controlled by the Repository Service.
|
||||
object_isolated = 0x00010000, ///< The object is running in an isolated environment.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Object information.
|
||||
*/
|
||||
struct SObjectInfo
|
||||
{
|
||||
TObjectID tObjectID; ///< The object ID to identify the object.
|
||||
TModuleID tModuleID; ///< The module ID that contains the object class. Might be zero with foreign
|
||||
///< objects.
|
||||
SClassInfo sClassInfo; ///< The class information used during object creation.
|
||||
u8string ssObjectName; ///< The object name. Might be empty for uncontrolled objects.
|
||||
u8string ssObjectConfig; ///< The object configuration. Might be empty when no configuration was supplied.
|
||||
uint32 uiFlags; ///< Information flags - zero or more flags of EObjectInfoFlags.
|
||||
|
||||
// TODO... Proxy/Stub objects (tObjectID) and Process (tProcessID) information and host information.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get object information.
|
||||
*/
|
||||
interface IRepositoryInfo
|
||||
{
|
||||
/**
|
||||
* @brief Find the class information of an object with the supplied name.
|
||||
* @param[in] ssClassName Object class name.
|
||||
* @return The object class information.
|
||||
*/
|
||||
SClassInfo FindClass(in u8string ssClassName) const;
|
||||
|
||||
/**
|
||||
* @brief Get a list of all the instantiated objects.
|
||||
* @return Sequence containing the object information structures.
|
||||
*/
|
||||
sequence<SObjectInfo> GetObjectList() const;
|
||||
|
||||
/**
|
||||
* @brief Get the object info for the requested object.
|
||||
* @param[in] tObjectID The object ID to return the object information for.
|
||||
* @return The object information structure if the object is available or an empty structure if not.
|
||||
*/
|
||||
SObjectInfo GetObjectInfo(in TObjectID tObjectID) const;
|
||||
|
||||
/**
|
||||
* @brief Find an object with the supplied name. Only object instances that are in the service list can be found with
|
||||
* this function (devices, basic and complex services, and system objects).
|
||||
* @param[in] ssObjectName Object name to search for.
|
||||
* @return The object information structure if the object is available or an empty structure if not.
|
||||
*/
|
||||
SObjectInfo FindObject(in u8string ssObjectName) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface used to control object creation and destruction.
|
||||
*/
|
||||
interface IRepositoryControl
|
||||
{
|
||||
/**
|
||||
* @brief Create an object and all its objects it depends on.
|
||||
* @details For standalone and essential applications, this function allows the creation of system, device and service
|
||||
* objects if the module was loaded previously. For the main and isolated application, this function allows the
|
||||
* creation of complex services only and only those that are in the installation. For the isolated application only one
|
||||
* complex service can be created. External apps, utilities, and proxy and stub objects cannot be created at all using
|
||||
* this function.
|
||||
* Objects that the to be create object is depending on will be created as well. For the main application this is
|
||||
* limited to complex services. Isolated applications cannot load other services; this is taken over by the main
|
||||
* application.
|
||||
* @param[in] ssClassName The name of the object class to be created. For the main application, the class string could
|
||||
* be empty for the main application if the object was defined in the installation.
|
||||
* @param[in] ssObjectName Name of the object, required to be unique. For standalone and essential applications, the
|
||||
* name string can be empty, in which case the object might either provide a name proposal or the name is the same as
|
||||
* the class name. Use the returned object ID to request the name of the object.
|
||||
* @param[in] ssObjectConfig Optional configuration handed over to the object upon creation via IObjectControl. Only
|
||||
* valid for standalone, essential and isolated applications.
|
||||
* @return Returns the object ID when the object creation was successful or 0 when not. On success the object is
|
||||
* available through the IObjectAccess interface. If the object already exists (class and object names are identical),
|
||||
* the object ID of the existing object is returned.
|
||||
*/
|
||||
TObjectID CreateObject(in u8string ssClassName, in u8string ssObjectName, in u8string ssObjectConfig);
|
||||
|
||||
/**
|
||||
* @brief Create an object from a previously loaded module. Provide the module ID to explicitly define what module to
|
||||
* use during object creation.
|
||||
* @attention This function is not available for 'main' and 'isolated' applications.
|
||||
* @param[in] tModuleID Module ID that contains the object class to create the object with.
|
||||
* @param[in] ssClassName The name of the object class to be created.
|
||||
* @param[in] ssObjectName Optional name of the object - required to be unique. If not supplied, the object might
|
||||
* either provide a name proposal or the name is the same as the class name. Use the returned object ID to request
|
||||
* the name of the object.
|
||||
* @param[in] ssObjectConfig Optional configuration handed over to the object upon creation via IObjectControl.
|
||||
* @return Returns the object ID when the object creation was successful or 0 when not. On success the object is
|
||||
* available through the IObjectAccess interface. If the object already exists (class and object names are identical),
|
||||
* the object ID of the existing object is returned.
|
||||
*/
|
||||
TObjectID CreateObjectFromModule(in TModuleID tModuleID, in u8string ssClassName, in u8string ssObjectName,
|
||||
in u8string ssObjectConfig);
|
||||
|
||||
/**
|
||||
* @brief Destroy a previously created object with the supplied name.
|
||||
* @details For standalone and essential applications previously created system, device and service objects can be
|
||||
* destroyed. For the main and isolated applications, only the complex service can be destroyed. For isolated
|
||||
* applications a destruction of the object will end the application.
|
||||
* @param[in] ssObjectName The name of the object to destroy.
|
||||
* @return Returns whether the object destruction was successful.
|
||||
*/
|
||||
boolean DestroyObject(in u8string ssObjectName);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface used to create utilities.
|
||||
*/
|
||||
interface IRepositoryUtilityCreate
|
||||
{
|
||||
/**
|
||||
* @brief Creates an utility object.
|
||||
* @details The behavior of this function depends on the run-as mode the application is running in... For the core
|
||||
* application running as 'main' the module will be loaded if not already done so (pre-condition, the module containing
|
||||
* the object is installed) . If the object is
|
||||
* a complex service, the object is created in an isolated space. For the isolated application, only complex services
|
||||
* can be created running locally if the module is installed. For all other run-as modes (standalone, essential, etc.),
|
||||
* the object is created if the module was loaded previously.
|
||||
* @attention Utilities are standalone objects. Use IObjectDestroy to destroy the utility.
|
||||
* @param[in] ssClassName The name of the object class to be created.
|
||||
* @param[in] ssObjectConfig Optional configuration handed over to the object upon creation via IObjectControl.
|
||||
* @return Returns the IInterfaceAccess interface of newly created utility.
|
||||
*/
|
||||
IInterfaceAccess CreateUtility(in u8string ssClassName, in u8string ssObjectConfig);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface used to create marshall objects. This interface is operated by the Communication Control service.
|
||||
*/
|
||||
local interface IRepositoryMarshallCreate
|
||||
{
|
||||
/**
|
||||
* @brief Create a proxy object for the interface with the supplied ID. If successful, this object is initialized, but
|
||||
* not linked to any other object within the system.
|
||||
* @details Create a proxy object with the name "proxy_<ifc id>". "ifc_id" is the decimal value of an interface ID.
|
||||
* @param[in] id The interface ID to create the object for.
|
||||
* @return Returns the interface to the proxy object. Destruction of the object can be achieved through IObjectDestroy.
|
||||
*/
|
||||
IInterfaceAccess CreateProxyObject(in interface_id id);
|
||||
|
||||
/**
|
||||
* @brief Create a stub object for the interface with the supplied ID. If successful, this object is initialized, but
|
||||
* not linked to any other object within the system.
|
||||
* @details Create a stub object with the name "stub_<ifc id>". "ifc_id" is the decimal value of an interface ID.
|
||||
* @param[in] id The interface ID to create the object for.
|
||||
* @return Returns the interface to the stub object. Destruction of the object can be achieved through IObjectDestroy.
|
||||
*/
|
||||
IInterfaceAccess CreateStubObject(in interface_id id);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface used to publish external objects to the SDV system.
|
||||
* @attention Any objects supplied must not be destroyed before IRepositoryControl::Shutdown has been called
|
||||
*/
|
||||
interface IRegisterForeignObject
|
||||
{
|
||||
/**
|
||||
* @brief Register as foreign object and make it public to the system with the given name.
|
||||
* @param[in] pObjectIfc The object to be registered
|
||||
* @param[in] ssObjectName The name under which the object - required to be unique.
|
||||
* @return Returns the object ID when the object creation was successful or 0 when not. On success the object is
|
||||
* available through the IObjectAccess interface. If the object already exists (class and object names are identical),
|
||||
* the object ID of the existing object is returned.
|
||||
*/
|
||||
TObjectID RegisterObject(in IInterfaceAccess pObjectIfc, in u8string ssObjectName);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Connect the core repository to the local repository to allow object access by the locally running components.
|
||||
* @remarks This interface is available only for isolated and external applications.
|
||||
*/
|
||||
interface ILinkCoreRepository
|
||||
{
|
||||
/**
|
||||
* @brief Register the core repository.
|
||||
* @param[in] pCoreRepository Pointer to the proxy interface of the core repository.
|
||||
*/
|
||||
void LinkCoreRepository(in IInterfaceAccess pCoreRepository);
|
||||
|
||||
/**
|
||||
* @brief Unlink a previously linked core repository.
|
||||
*/
|
||||
void UnlinkCoreRepository();
|
||||
};
|
||||
|
||||
}; // module core
|
||||
}; // module sdv
|
||||
62
export/interfaces/timer.idl
Normal file
62
export/interfaces/timer.idl
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @file timer.idl
|
||||
* @author Erik Verhoeven DISDS1 (mailto:erik.verhoeven@zf.com)
|
||||
* @brief This file includes all the interfaces used for timer creation.
|
||||
* @version 1.0
|
||||
* @date 2024-05-09
|
||||
*
|
||||
* @copyright Copyright ZF Friedrichshafen AG (c) 2023-2025
|
||||
*/
|
||||
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
/**
|
||||
* @brief Interface to be implemented by user-defined tasks so that the core::ITaskTimer interface can periodically execute the
|
||||
* task
|
||||
*/
|
||||
interface ITaskExecute
|
||||
{
|
||||
/**
|
||||
* @brief Execute a task. This function is triggered by the task timer service.
|
||||
*/
|
||||
void Execute();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to execute tasks periodically
|
||||
*/
|
||||
interface ITaskTimer
|
||||
{
|
||||
/**
|
||||
* @brief Method to execute the user-defined task periodically.
|
||||
* @param[in] uiPeriod The time period in milliseconds in which the task should executed.
|
||||
* @param[in] pTask Interface to the task object exposing the ITaskExecute interface. The object must be kept alive
|
||||
* until the timer has been destroyed.
|
||||
* @return Returns an interface to the task timer object. Use sdv::IObjectDestroy to terminate the timer.
|
||||
*/
|
||||
IInterfaceAccess CreateTimer(in uint32 uiPeriod, in IInterfaceAccess pTask);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to set the simulation time between 2 simulation steps.
|
||||
*/
|
||||
interface ITimerSimulationStep
|
||||
{
|
||||
/**
|
||||
* @brief Method to set the time which has past from the last simulation step.
|
||||
* @param[in] uiSimulationStep the time in microseconds which has past from the last simulation step.
|
||||
*/
|
||||
void SimulationStep(in uint64 uiSimulationStep);
|
||||
};
|
||||
};
|
||||
};
|
||||
123
export/interfaces/toml.idl
Normal file
123
export/interfaces/toml.idl
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
*
|
||||
* @file dispatch.idl
|
||||
* @brief This file provides interfaces related to the data dispatch service.
|
||||
* @version 1.0
|
||||
* @date 2024.01.12
|
||||
* @author Erik Verhoeven
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2024
|
||||
*
|
||||
*/
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief TOML interface.
|
||||
*/
|
||||
module toml
|
||||
{
|
||||
/**
|
||||
* @brief TOML parse exception.
|
||||
*/
|
||||
exception XTOMLParseException : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "TOML parse exception.";
|
||||
|
||||
u8string ssMessage; ///< Message indicating the cause of the exception.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Collection of possible data in parse tree node
|
||||
*/
|
||||
enum ENodeType : uint8
|
||||
{
|
||||
node_table, //!< Table
|
||||
node_array, //!< Array
|
||||
node_integer, //!< Integer
|
||||
node_floating_point, //!< Floating point
|
||||
node_boolean, //!< Boolean
|
||||
node_string, //!< String
|
||||
node_invalid //!< Invalid content
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Node information interface
|
||||
*/
|
||||
interface INodeInfo
|
||||
{
|
||||
/**
|
||||
* @brief Get the node name.
|
||||
* @return String containing the name of the node.
|
||||
*/
|
||||
u8string GetName() const;
|
||||
|
||||
/**
|
||||
* @brief Get the node type.
|
||||
* @return Type of the node.
|
||||
*/
|
||||
ENodeType GetType() const;
|
||||
|
||||
/**
|
||||
* @brief The node value.
|
||||
* @return For boolean, integer, floating point and strings, the function returns a value. Otherwise the function
|
||||
* returns empty.
|
||||
*/
|
||||
any GetValue() const;
|
||||
|
||||
/**
|
||||
* @brief Return the TOML string belonging to this node including all potential child nodes.
|
||||
* @return The TOML string.
|
||||
*/
|
||||
u8string GetTOML() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface allowing access to table and array nodes.
|
||||
*/
|
||||
interface INodeCollection
|
||||
{
|
||||
/**
|
||||
* @brief Returns the amount of nodes.
|
||||
* @return The amount of nodes.
|
||||
*/
|
||||
uint32 GetCount() const;
|
||||
|
||||
/**
|
||||
* @brief Get the node.
|
||||
* @param[in] uiIndex Index of the node to get.
|
||||
* @return Interface to the node object.
|
||||
*/
|
||||
IInterfaceAccess GetNode(in uint32 uiIndex) const;
|
||||
|
||||
/**
|
||||
* @brief Searches a node by its key in the parse tree
|
||||
* @details Elements of tables can be accessed and traversed by using '.' to separated the parent name from child
|
||||
* name. E.g. 'parent.child' would access the 'child' element of the 'parent' table. Elements of arrays can be
|
||||
* accessed and traversed by using the index number in brackets. E.g. 'array[3]' would access the fourth element of
|
||||
* the array 'array'. These access conventions can also be chained like 'table.array[2][1].subtable.integerElement'.
|
||||
* @attention Array indexing starts with 0!
|
||||
* @param[in] ssPath The path of the Node to searched for.
|
||||
* @return Returns an interface the requested node if available.
|
||||
*/
|
||||
IInterfaceAccess GetNodeDirect(in u8string ssPath) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief TOML parser interface.
|
||||
*/
|
||||
interface ITOMLParser
|
||||
{
|
||||
/**
|
||||
* @brief Process the configuration from the supplied content string.
|
||||
* @param[in] ssContent Configuration string.
|
||||
* @return Returns 'true' when the configuration could be read successfully, false when not.
|
||||
*/
|
||||
boolean Process(in u8string ssContent) raises(XTOMLParseException);
|
||||
};
|
||||
};
|
||||
};
|
||||
491
export/support/any.h
Normal file
491
export/support/any.h
Normal file
@@ -0,0 +1,491 @@
|
||||
#ifndef SDV_ANY_H
|
||||
#define SDV_ANY_H
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
#include <filesystem>
|
||||
#include "string.h"
|
||||
#include "interface.h"
|
||||
#include "except.h"
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief The 'any' class implementation.
|
||||
*/
|
||||
class any_t
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Value type enumeration
|
||||
*/
|
||||
enum class EValType : uint32_t
|
||||
{
|
||||
val_type_empty = 0, ///< Empty value
|
||||
val_type_bool = 1, ///< Boolean value; bVal is used.
|
||||
val_type_int8 = 8, ///< 8-Bit signed value; i8Val is used.
|
||||
val_type_uint8 = 9, ///< 8-Bit unsigned value; ui8Val is used.
|
||||
val_type_int16 = 16, ///< 16-Bit signed value; i16Val is used.
|
||||
val_type_uint16 = 17, ///< 16-Bit unsigned value; ui16Val is used.
|
||||
val_type_int32 = 32, ///< 32-Bit signed value; i32Val is used.
|
||||
val_type_uint32 = 33, ///< 32-Bit unsigned value; ui32Val is used.
|
||||
val_type_int64 = 64, ///< 64-Bit signed value; i64Val is used.
|
||||
val_type_uint64 = 65, ///< 64-Bit unsigned value; ui64Val is used.
|
||||
val_type_char = 100, ///< ANSI Character value; cVal is used.
|
||||
val_type_char16 = 116, ///< UTF-16 Character value; c16Val is used.
|
||||
val_type_char32 = 132, ///< UTF-32 Character value; c32Val is used.
|
||||
val_type_wchar = 101, ///< Wide character value; cwVal is used.
|
||||
val_type_float = 232, ///< Singled precision floating point value; fVal is used.
|
||||
val_type_double = 264, ///< Double precision floating point value; dVal is used.
|
||||
val_type_long_double = 265, ///< Long double precision floating point value; ldVal is used.
|
||||
val_type_fixed = 300, ///< Fixed point value; fixValue is used.
|
||||
val_type_string = 1000, ///< ANSI string value; ssVal is used.
|
||||
val_type_u8string = 1008, ///< UTF-8 string value; ss8Val is used.
|
||||
val_type_u16string = 1016, ///< UTF-16 string value; ss16Val is used.
|
||||
val_type_u32string = 1032, ///< UTF-32 string value; ss32Val is used.
|
||||
val_type_wstring = 1001, ///< Wide string value; sswVal is used.
|
||||
val_type_interface = 2000, ///< Interface type value; ifcVal is used.
|
||||
val_type_interface_id = 2001, ///< Interface id value; idIfcVal is used.
|
||||
val_type_exception_id = 3000, ///< Exception id value; idExceptVal is used.
|
||||
} eValType = EValType::val_type_empty; ///< The value type
|
||||
|
||||
/// Anonymous union
|
||||
union
|
||||
{
|
||||
bool bVal; ///< Boolean value
|
||||
int8_t i8Val; ///< 8-Bit signed value
|
||||
uint8_t ui8Val; ///< 8-Bit unsigned value
|
||||
int16_t i16Val; ///< 16-Bit signed value
|
||||
uint16_t ui16Val; ///< 16-Bit unsigned value
|
||||
int32_t i32Val; ///< 32-Bit signed value
|
||||
uint32_t ui32Val; ///< 32-Bit unsigned value
|
||||
int64_t i64Val; ///< 64-Bit signed value
|
||||
uint64_t ui64Val; ///< 64-Bit unsigned value
|
||||
char cVal; ///< ANSI Character value
|
||||
char16_t c16Val; ///< UTF-16 Character value
|
||||
char32_t c32Val; ///< UTF-32 Character value
|
||||
wchar_t cwVal; ///< Wide character value
|
||||
float fVal; ///< Singled precision floating point value
|
||||
double dVal; ///< Double precision floating point value
|
||||
long double ldVal; ///< Long double precision floating point value
|
||||
//fixed fixValue; ///< Fixed point value
|
||||
string ssVal; ///< ANSI string value
|
||||
u8string ss8Val; ///< UTF-8 string value
|
||||
u16string ss16Val; ///< UTF-16 string value
|
||||
u32string ss32Val; ///< UTF-32 string value
|
||||
wstring sswVal; ///< Wide string value
|
||||
interface_t ifcVal; ///< Interface type value
|
||||
interface_id idIfcVal; ///< Interface id value
|
||||
exception_id idExceptVal; ///< Exception id value
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Default constructor; construct an empty any
|
||||
*/
|
||||
any_t();
|
||||
|
||||
/**
|
||||
* @brief destructor
|
||||
*/
|
||||
~any_t();
|
||||
|
||||
/**
|
||||
* @brief Assignment constructor.
|
||||
* @param[in] tVal The value to assign.
|
||||
*/
|
||||
template <typename TType>
|
||||
explicit any_t(TType tVal);
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief SDV string constructors.
|
||||
* @param[in] rssVal Reference to the string object.
|
||||
*/
|
||||
explicit any_t(const string& rssVal);
|
||||
explicit any_t(const u8string& rssVal);
|
||||
explicit any_t(const u16string& rssVal);
|
||||
explicit any_t(const u32string& rssVal);
|
||||
explicit any_t(const wstring& rssVal);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief C-style string constructors.
|
||||
* @param[in] sz Zero terminated string.
|
||||
*/
|
||||
any_t(const char* sz);
|
||||
|
||||
/**
|
||||
* @brief C-style string constructors.
|
||||
* @param[in] sz Zero terminated string.
|
||||
*/
|
||||
any_t(const char16_t* sz);
|
||||
|
||||
/**
|
||||
* @brief C-style string constructors.
|
||||
* @param[in] sz Zero terminated string.
|
||||
*/
|
||||
any_t(const char32_t* sz);
|
||||
|
||||
/**
|
||||
* @brief C-style string constructors.
|
||||
* @param[in] sz Zero terminated string.
|
||||
*/
|
||||
any_t(const wchar_t* sz);
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief STD string constructors.
|
||||
* @param[in] rssVal Reference to the string object.
|
||||
*/
|
||||
explicit any_t(const std::string& rssVal);
|
||||
explicit any_t(const std::u16string& rssVal);
|
||||
explicit any_t(const std::u32string& rssVal);
|
||||
explicit any_t(const std::wstring& rssVal);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Assignment constructor.
|
||||
* @param[in] tVal The value to assign.
|
||||
* @param[in] eValTypeParam The target value type.
|
||||
*/
|
||||
template <typename TType>
|
||||
any_t(TType tVal, EValType eValTypeParam);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] rany Reference to any class to copy from.
|
||||
*/
|
||||
any_t(const any_t& rany);
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @param[in] rany Reference to any class to move from.
|
||||
*/
|
||||
any_t(any_t&& rany) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Assignment operator.
|
||||
* @param[in] tVal The value to assign.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
template <typename TType>
|
||||
any_t& operator=(TType tVal);
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator.
|
||||
* @param[in] rany Reference to any class to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
any_t& operator=(const any_t& rany);
|
||||
|
||||
/**
|
||||
* @brief Move operator.
|
||||
* @param[in] rany Reference to any class to move from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
any_t& operator=(any_t&& rany) noexcept;
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief Cast operators (provides conversion if not identical to the original type).
|
||||
* @remarks The operators for ANSI string, interface id and exception id are rerpresented by u8string and uint64_t
|
||||
* respectively and cannot be used to cast to automatically.
|
||||
* @return The value stored.
|
||||
*/
|
||||
operator bool() const;
|
||||
operator int8_t() const;
|
||||
operator uint8_t() const;
|
||||
operator int16_t() const;
|
||||
operator uint16_t() const;
|
||||
operator int32_t() const;
|
||||
operator uint32_t() const;
|
||||
operator int64_t() const;
|
||||
operator uint64_t() const;
|
||||
#ifdef __linux__
|
||||
operator long long int() const { return static_cast<long long int>(operator int64_t()); }
|
||||
operator unsigned long long int() const { return static_cast<long long int>(operator uint64_t()); }
|
||||
#endif
|
||||
operator char() const;
|
||||
operator char16_t() const;
|
||||
operator char32_t() const;
|
||||
operator wchar_t() const;
|
||||
operator float() const;
|
||||
operator double() const;
|
||||
operator long double() const;
|
||||
//operator fixed() const;
|
||||
operator string() const;
|
||||
operator u8string() const;
|
||||
operator u16string() const;
|
||||
operator u32string() const;
|
||||
operator wstring() const;
|
||||
operator interface_t() const;
|
||||
//operator interface_id() const;
|
||||
//operator exception_id() const;
|
||||
operator std::string() const;
|
||||
operator std::u16string() const;
|
||||
operator std::u32string() const;
|
||||
operator std::wstring() const;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Check for an empty any.
|
||||
* @return Retrurns whether the any is empty.
|
||||
*/
|
||||
bool empty() const;
|
||||
|
||||
/**
|
||||
* @brief Empty the any.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* @brief Assign the value to the any. The any takes the value type based on the value.
|
||||
* @tparam TType The type of the value to set.
|
||||
* @param[in] tVal The value to set.
|
||||
*/
|
||||
template <typename TType>
|
||||
void set(TType tVal);
|
||||
|
||||
/**
|
||||
* @brief Assign the value to the any. The value will be converted to the provided value type.
|
||||
* @tparam TType The type of the value to set.
|
||||
* @param[in] tVal The valiue to set.
|
||||
* @param[in] eValTypeParam The value type of the any.
|
||||
*/
|
||||
template <typename TType>
|
||||
void set(TType tVal, EValType eValTypeParam);
|
||||
|
||||
/**
|
||||
* @brief Get the value converted to the provided type.
|
||||
* @tparam TType The type of the value to get,
|
||||
* @return The value to get.
|
||||
*/
|
||||
template <typename TType>
|
||||
TType get() const;
|
||||
|
||||
/**
|
||||
* @brief Comparison type.
|
||||
*/
|
||||
enum class ECompareType
|
||||
{
|
||||
compare_equal,
|
||||
compare_inequal,
|
||||
compare_smaller,
|
||||
compare_smaller_equal,
|
||||
compare_larger,
|
||||
compare_larger_equal,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Compare the provided value with the contained value.
|
||||
* @tparam TType Type of the supplied value.
|
||||
* @tparam eType Type of comparison to do.
|
||||
* @param[in] rtVal Reference to the value to use for comparison.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType, ECompareType eType>
|
||||
bool Compare(const TType& rtVal) const;
|
||||
|
||||
/**
|
||||
* @brief Compare the provided value with the contained value.
|
||||
* @tparam eType Type of comparison to do.
|
||||
* @param[in] ranyVal Reference to the value to use for comparison.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <ECompareType eType>
|
||||
bool Compare(const any_t& ranyVal) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Convert the value from one type to the other.
|
||||
* @remarks This function doesn't check for correct sizes. Invalid conversions lead to an empty destination.
|
||||
* @tparam TSourceType The source type to convert from.
|
||||
* @tparam TDestTyoe The destination type to convert to.
|
||||
* @param[in] rtSrcVal Reference to the source value.
|
||||
* @param[in] rtDstVal Reference to the destination value.
|
||||
*/
|
||||
template <typename TSourceType, typename TDestType>
|
||||
static void convert(const TSourceType& rtSrcVal, TDestType& rtDstVal);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Equality comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] tVal2 Value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator==(const sdv::any_t& ranyVal1, TType tVal2);
|
||||
|
||||
/**
|
||||
* @brief Equality comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] tVal1 Value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator==(TType tVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Equality comparison operator.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
bool operator==(const sdv::any_t& ranyVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Inequality comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] tVal2 Value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator!=(const sdv::any_t& ranyVal1, TType tVal2);
|
||||
|
||||
/**
|
||||
* @brief Inequality comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] tVal1 Value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator!=(TType tVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Inequality comparison operator.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
bool operator!=(const sdv::any_t& ranyVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Smaller than comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] tVal2 Value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator<(const sdv::any_t& ranyVal1, TType tVal2);
|
||||
|
||||
/**
|
||||
* @brief Smaller than comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] tVal1 Value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator<(TType tVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Smaller than comparison operator.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
bool operator<(const sdv::any_t& ranyVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Smaller than or equality comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] tVal2 Value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator<=(const sdv::any_t& ranyVal1, TType tVal2);
|
||||
|
||||
/**
|
||||
* @brief Smaller than or equality comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] tVal1 Value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator<=(TType tVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Smaller than or equality comparison operator.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
bool operator<=(const sdv::any_t& ranyVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Greater than comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] tVal2 Value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator>(const sdv::any_t& ranyVal1, TType tVal2);
|
||||
|
||||
/**
|
||||
* @brief Greater than comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] tVal1 Value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator>(TType tVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Greater than comparison operator.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
bool operator>(const sdv::any_t& ranyVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Greater than or equality comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] tVal2 Value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator>=(const sdv::any_t& ranyVal1, TType tVal2);
|
||||
|
||||
/**
|
||||
* @brief Greater than or equality comparison operator.
|
||||
* @tparam TType The type to use for the comparison.
|
||||
* @param[in] tVal1 Value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
template <typename TType>
|
||||
bool operator>=(TType tVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
/**
|
||||
* @brief Greater than or equality comparison operator.
|
||||
* @param[in] ranyVal1 Reference to the any value to compare with.
|
||||
* @param[in] ranyVal2 Reference to the any value to compare with.
|
||||
* @return The result of the comparison.
|
||||
*/
|
||||
bool operator>=(const sdv::any_t& ranyVal1, const sdv::any_t& ranyVal2);
|
||||
|
||||
}
|
||||
|
||||
#include "any.inl"
|
||||
|
||||
#endif // !defined SDV_ANY_H
|
||||
1460
export/support/any.inl
Normal file
1460
export/support/any.inl
Normal file
File diff suppressed because it is too large
Load Diff
476
export/support/app_control.h
Normal file
476
export/support/app_control.h
Normal file
@@ -0,0 +1,476 @@
|
||||
#ifndef SDV_APP_CONTROL_H
|
||||
#define SDV_APP_CONTROL_H
|
||||
|
||||
#include "sdv_core.h"
|
||||
#include "../interfaces/app.h"
|
||||
#include "../interfaces/config.h"
|
||||
#include "interface_ptr.h"
|
||||
#include "local_service_access.h"
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
namespace app
|
||||
{
|
||||
/**
|
||||
* @brief Application control class.
|
||||
*/
|
||||
class CAppControl : public IInterfaceAccess, public IAppEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor; doesn't start the application control.
|
||||
*/
|
||||
CAppControl() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructor; starts the application control with the supplied configuration.
|
||||
* @param[in] rssConfig Reference to the configuration string.
|
||||
*/
|
||||
CAppControl(const std::string& rssConfig) : CAppControl()
|
||||
{
|
||||
Startup(rssConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Shuts down during destruction if not explicitly done before.
|
||||
*/
|
||||
~CAppControl()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(IAppEvent)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief Starts the application control with the supplied configuration.
|
||||
* @param[in] rssConfig Reference to the configuration string.
|
||||
* @return Returns 'true' on success; otherwise returns 'false'.
|
||||
*/
|
||||
bool Startup(const std::string& rssConfig)
|
||||
{
|
||||
IAppControl* pAppControl = core::GetCore() ? core::GetCore<IAppControl>() : nullptr;
|
||||
if (!pAppControl) return false;
|
||||
if (m_eState != EAppOperationState::not_started) return false;
|
||||
try
|
||||
{
|
||||
// Start the application control
|
||||
bool bRet = pAppControl->Startup(rssConfig, this);
|
||||
|
||||
// Get the application context
|
||||
const IAppContext* pAppContext = core::GetCore<IAppContext>();
|
||||
if (pAppContext)
|
||||
{
|
||||
m_eContext = pAppContext->GetContextType();
|
||||
m_uiInstanceID = pAppContext->GetInstanceID();
|
||||
m_uiRetries = pAppContext->GetRetries();
|
||||
}
|
||||
|
||||
// Automatically connect to the server
|
||||
if (m_eContext == EAppContext::external)
|
||||
{
|
||||
// Try to connect
|
||||
m_ptrServerRepository = sdv::com::ConnectToLocalServerRepository(m_uiInstanceID, m_uiRetries);
|
||||
if (!m_ptrServerRepository)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Failed to connect to the server repository." << std::endl;
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get access to the module control service
|
||||
sdv::core::IObjectAccess* pObjectAccess = m_ptrServerRepository.GetInterface<sdv::core::IObjectAccess>();
|
||||
const sdv::core::IRepositoryControl* pRepoControl = nullptr;
|
||||
if (pObjectAccess)
|
||||
pRepoControl = sdv::TInterfaceAccessPtr(pObjectAccess->GetObject("RepositoryService")).
|
||||
GetInterface<sdv::core::IRepositoryControl>();
|
||||
if (!pRepoControl)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Failed to access the server repository." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Link the local repository to the server repository.
|
||||
sdv::core::ILinkCoreRepository* pLinkCoreRepo =
|
||||
sdv::core::GetObject<sdv::core::ILinkCoreRepository>("RepositoryService");
|
||||
if (!pLinkCoreRepo)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Cannot link local and server repositories." << std::endl;
|
||||
return false;
|
||||
}
|
||||
pLinkCoreRepo->LinkCoreRepository(m_ptrServerRepository);
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
catch (const XSysExcept& rxException)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: " << rxException.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Running loop until shutdown request is triggered.
|
||||
* @return Returns whether running the loop was successful.
|
||||
*/
|
||||
bool RunLoop()
|
||||
{
|
||||
IAppControl* pAppControl = core::GetCore() ? core::GetCore<IAppControl>() : nullptr;
|
||||
if (!pAppControl) return false;
|
||||
|
||||
try
|
||||
{
|
||||
pAppControl->RunLoop();
|
||||
} catch (const XSysExcept&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Shutdown the application control
|
||||
* @attention The created objects are destroyed and the module unloaded in reverse order of their creation.
|
||||
*/
|
||||
void Shutdown()
|
||||
{
|
||||
// Disconnect local and remote repositories.
|
||||
if (m_ptrServerRepository)
|
||||
{
|
||||
// Link the local repository to the server repository.
|
||||
sdv::core::ILinkCoreRepository* pLinkCoreRepo =
|
||||
sdv::core::GetObject<sdv::core::ILinkCoreRepository>("RepositoryService");
|
||||
if (!pLinkCoreRepo)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Cannot unlink local and server repositories." << std::endl;
|
||||
} else
|
||||
pLinkCoreRepo->UnlinkCoreRepository();
|
||||
}
|
||||
|
||||
// Disconnect from the server (if connected at all).
|
||||
m_ptrServerRepository.Clear();
|
||||
|
||||
// Shutdown.
|
||||
IAppControl* pAppControl = core::GetCore() ? core::GetCore<IAppControl>() : nullptr;
|
||||
try
|
||||
{
|
||||
if (pAppControl) pAppControl->Shutdown(false);
|
||||
} catch (const XSysExcept&)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Failed to shutdown app control." << std::endl;
|
||||
}
|
||||
m_eContext = EAppContext::no_context;
|
||||
m_uiInstanceID = 0u;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Is the system running?
|
||||
* @return Returns whether the system is running.
|
||||
*/
|
||||
bool IsRunning() const
|
||||
{
|
||||
return m_eState == EAppOperationState::running;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the SDV_FRAMEWORK_RUNTIME environment variable for this application.
|
||||
* @return Path directing to the SDV V-API Framework directory if available or an empty path if not.
|
||||
*/
|
||||
static std::filesystem::path GetFrameworkRuntimeDirectory()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const wchar_t* szFrameworkDir = _wgetenv(L"SDV_FRAMEWORK_RUNTIME");
|
||||
if (!szFrameworkDir) return {};
|
||||
return szFrameworkDir;
|
||||
#elif defined __unix__
|
||||
const char* szFrameworkDir = getenv("SDV_FRAMEWORK_RUNTIME");
|
||||
if (!szFrameworkDir) return {};
|
||||
return szFrameworkDir;
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set or overwrite the SDV_FRAMEWORK_RUNTIME environment variable for this application.
|
||||
* @param[in] rpathDir Reference of the path directing to the SDV V-API Framework directory.
|
||||
*/
|
||||
static void SetFrameworkRuntimeDirectory(const std::filesystem::path& rpathDir)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// NOTE: In windows there are two environment variable stacks which need to be updated.
|
||||
std::ignore = SetEnvironmentVariable(L"SDV_FRAMEWORK_RUNTIME", rpathDir.native().c_str());
|
||||
std::ignore = _wputenv((std::wstring(L"SDV_FRAMEWORK_RUNTIME=") + rpathDir.native()).c_str());
|
||||
#elif defined __unix__
|
||||
std::ignore = setenv("SDV_FRAMEWORK_RUNTIME", rpathDir.generic_u8string().c_str(), 1);
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the SDV_COMPONENT_INSTALL environment variable for this application.
|
||||
* @return Path directing to the SDV V-API component installation directory if available or an empty path if not.
|
||||
*/
|
||||
static std::filesystem::path GetComponentInstallDirectory()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const wchar_t* szComponentDir = _wgetenv(L"SDV_COMPONENT_INSTALL");
|
||||
if (!szComponentDir) return {};
|
||||
return szComponentDir;
|
||||
#elif defined __unix__
|
||||
const char* szComponentDir = getenv("SDV_COMPONENT_INSTALL");
|
||||
if (!szComponentDir) return {};
|
||||
return szComponentDir;
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set or overwrite the SDV_COMPONENT_INSTALL environment variable for this application.
|
||||
* @param[in] rpathDir Reference of the path directing to the SDV V-API component installation directory.
|
||||
*/
|
||||
static void SetComponentInstallDirectory(const std::filesystem::path& rpathDir)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// NOTE: In windows there are two environment variable stacks which need to be updated.
|
||||
std::ignore = SetEnvironmentVariable(L"SDV_COMPONENT_INSTALL", rpathDir.native().c_str());
|
||||
std::ignore = _wputenv((std::wstring(L"SDV_COMPONENT_INSTALL=") + rpathDir.native()).c_str());
|
||||
#elif defined __unix__
|
||||
std::ignore = setenv("SDV_COMPONENT_INSTALL", rpathDir.generic_u8string().c_str(), 1);
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the application context.
|
||||
* @return The application context.
|
||||
*/
|
||||
EAppContext GetAppContext() const
|
||||
{
|
||||
return m_eContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the core instance ID.
|
||||
* @return The core instance ID.
|
||||
*/
|
||||
uint32_t GetInstanceID() const
|
||||
{
|
||||
return m_uiInstanceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the operation to running mode.
|
||||
* @pre The system is operating in configuration mode.
|
||||
*/
|
||||
void SetRunningMode()
|
||||
{
|
||||
IAppOperation* pAppOperation = core::GetObject<IAppOperation>("AppControlService");
|
||||
if (pAppOperation)
|
||||
pAppOperation->SetRunningMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Is the system in configuration state?
|
||||
* @return Returns whether the system is being configured.
|
||||
*/
|
||||
bool IsConfiguring() const
|
||||
{
|
||||
return m_eState == EAppOperationState::configuring;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the operation to config mode.
|
||||
* @pre The system is operating in running mode.
|
||||
*/
|
||||
void SetConfigMode()
|
||||
{
|
||||
IAppOperation* pAppOperation = core::GetObject<IAppOperation>("AppControlService");
|
||||
if (pAppOperation)
|
||||
pAppOperation->SetConfigMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process the provided configuration by loading modules and creating objects/stubs/proxies defined in the
|
||||
* configuration string.
|
||||
* @attention Configuration changes can only occur when the system is in configuration mode.
|
||||
* @param[in] ssContent The contents of the configuration file (TOML).
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
core::EConfigProcessResult ProcessConfig(/*in*/ const sdv::u8string& ssContent)
|
||||
{
|
||||
core::IConfig* pAppConfig = nullptr;
|
||||
sdv::TInterfaceAccessPtr ptrConfigObj = core::GetObject("ConfigService");
|
||||
if (ptrConfigObj) pAppConfig = ptrConfigObj.GetInterface<core::IConfig>();
|
||||
if (!pAppConfig) return core::EConfigProcessResult::failed;
|
||||
|
||||
bool bRunning = IsRunning();
|
||||
SetConfigMode();
|
||||
core::EConfigProcessResult eResult = pAppConfig->ProcessConfig(ssContent);
|
||||
if (bRunning) SetRunningMode();
|
||||
return eResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read file pointed to by the provided file path and load modules and create objects/stubs/proxies as defined
|
||||
* in the configuration file.
|
||||
* @attention Configuration changes can only occur when the system is in configuration mode.
|
||||
* @param[in] ssFilename Path to the file containing the configuration (TOML). The path can be absolute as well as relative.
|
||||
* In case a relative path is provided, the current directory is searched as well as all directories supplied through
|
||||
* the AddConfigSearchDir function.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
core::EConfigProcessResult LoadConfig(/*in*/ const sdv::u8string& ssFilename)
|
||||
{
|
||||
core::IConfig* pAppConfig = nullptr;
|
||||
sdv::TInterfaceAccessPtr ptrConfigObj = core::GetObject("ConfigService");
|
||||
if (ptrConfigObj) pAppConfig = ptrConfigObj.GetInterface<core::IConfig>();
|
||||
if (!pAppConfig) return core::EConfigProcessResult::failed;
|
||||
|
||||
bool bRunning = IsRunning();
|
||||
SetConfigMode();
|
||||
core::EConfigProcessResult eResult = pAppConfig->LoadConfig(ssFilename);
|
||||
if (bRunning) SetRunningMode();
|
||||
return eResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a search path to a folder where a config file can be found.
|
||||
* @param[in] rpathDir Reference to the relative or absolute path to an existing folder.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
bool AddConfigSearchDir(/*in*/ const std::filesystem::path& rpathDir)
|
||||
{
|
||||
core::IConfig* pAppConfig = nullptr;
|
||||
sdv::TInterfaceAccessPtr ptrConfigObj = core::GetObject("ConfigService");
|
||||
if (ptrConfigObj) pAppConfig = ptrConfigObj.GetInterface<core::IConfig>();
|
||||
if (!pAppConfig) return false;
|
||||
return pAppConfig->AddConfigSearchDir(rpathDir.generic_u8string());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a search path to a folder where a config file can be found.
|
||||
* @param[in] ssDir Relative or absolute path to an existing folder.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
bool AddConfigSearchDir(/*in*/ const sdv::u8string& ssDir)
|
||||
{
|
||||
core::IConfig* pAppConfig = nullptr;
|
||||
sdv::TInterfaceAccessPtr ptrConfigObj = core::GetObject("ConfigService");
|
||||
if (ptrConfigObj) pAppConfig = ptrConfigObj.GetInterface<core::IConfig>();
|
||||
if (!pAppConfig) return false;
|
||||
return pAppConfig->AddConfigSearchDir(ssDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a search path to a folder where a config file can be found.
|
||||
* @param[in] ssDir Relative or absolute path to an existing folder.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
bool AddConfigSearchDir(/*in*/ const std::string& ssDir)
|
||||
{
|
||||
core::IConfig* pAppConfig = nullptr;
|
||||
sdv::TInterfaceAccessPtr ptrConfigObj = core::GetObject("ConfigService");
|
||||
if (ptrConfigObj) pAppConfig = ptrConfigObj.GetInterface<core::IConfig>();
|
||||
if (!pAppConfig) return false;
|
||||
return pAppConfig->AddConfigSearchDir(ssDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a search path to a folder where a config file can be found.
|
||||
* @param[in] szDir Zero terminated string to the relative or absolute path to an existing folder.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
bool AddConfigSearchDir(/*in*/ const char* szDir)
|
||||
{
|
||||
if (!szDir) return false;
|
||||
core::IConfig* pAppConfig = nullptr;
|
||||
sdv::TInterfaceAccessPtr ptrConfigObj = core::GetObject("ConfigService");
|
||||
if (ptrConfigObj) pAppConfig = ptrConfigObj.GetInterface<core::IConfig>();
|
||||
if (!pAppConfig) return false;
|
||||
return pAppConfig->AddConfigSearchDir(szDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a search path to a folder where a module can be found.
|
||||
* @param[in] rpathDir Reference to the relative or absolute path to an existing folder.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
bool AddModuleSearchDir(/*in*/ const std::filesystem::path& rpathDir)
|
||||
{
|
||||
sdv::core::IModuleControlConfig* pModuleConfig = sdv::core::GetCore<sdv::core::IModuleControlConfig>();
|
||||
if (!pModuleConfig) return false;
|
||||
return pModuleConfig->AddModuleSearchDir(rpathDir.generic_u8string());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a search path to a folder where a module can be found.
|
||||
* @param[in] rssDir Reference to the relative or absolute path to an existing folder.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
bool AddModuleSearchDir(/*in*/ const sdv::u8string& rssDir)
|
||||
{
|
||||
sdv::core::IModuleControlConfig* pModuleConfig = sdv::core::GetCore<sdv::core::IModuleControlConfig>();
|
||||
if (!pModuleConfig) return false;
|
||||
return pModuleConfig->AddModuleSearchDir(rssDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a search path to a folder where a module can be found.
|
||||
* @param[in] rssDir Reference to the relative or absolute path to an existing folder.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
bool AddModuleSearchDir(/*in*/ const std::string& rssDir)
|
||||
{
|
||||
sdv::core::IModuleControlConfig* pModuleConfig = sdv::core::GetCore<sdv::core::IModuleControlConfig>();
|
||||
if (!pModuleConfig) return false;
|
||||
return pModuleConfig->AddModuleSearchDir(rssDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a search path to a folder where a module can be found.
|
||||
* @param[in] szDir Zero terminated string to the relative or absolute path to an existing folder.
|
||||
* @return Returns 'true' on success; 'false' otherwise.
|
||||
*/
|
||||
bool AddModuleSearchDir(/*in*/ const char* szDir)
|
||||
{
|
||||
if (!szDir) return false;
|
||||
sdv::core::IModuleControlConfig* pModuleConfig = sdv::core::GetCore<sdv::core::IModuleControlConfig>();
|
||||
if (!pModuleConfig) return false;
|
||||
return pModuleConfig->AddModuleSearchDir(szDir);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Process the event. Overload of IAppEvent::ProcessEvent.
|
||||
* @param[inout] sEvent Event structure containing the information to process.
|
||||
*/
|
||||
virtual void ProcessEvent(/*inout*/ SAppEvent& sEvent) override
|
||||
{
|
||||
// Only process state change events
|
||||
if (sEvent.uiEventID != EVENT_OPERATION_STATE_CHANGED) return;
|
||||
|
||||
m_eState = static_cast<EAppOperationState>(sEvent.uiInfo);
|
||||
}
|
||||
|
||||
EAppOperationState m_eState = EAppOperationState::not_started; ///< Application state.
|
||||
EAppContext m_eContext = EAppContext::no_context; ///< Application context.
|
||||
uint32_t m_uiInstanceID = 0u; ///< Core instance.
|
||||
uint32_t m_uiRetries = 0u; ///< Number of retries to establish a connection.
|
||||
sdv::TObjectPtr m_ptrServerRepository; ///< Server repository interface.
|
||||
};
|
||||
} // namespace app
|
||||
} // namespace sdv
|
||||
#endif // !defined SDV_APP_CONTROL_H
|
||||
954
export/support/component_impl.h
Normal file
954
export/support/component_impl.h
Normal file
@@ -0,0 +1,954 @@
|
||||
/**
|
||||
*
|
||||
* @file component_impl.h
|
||||
* @brief This file provides all necessary definitions to implement SDV object.
|
||||
* @version 0.1
|
||||
* @date 2022.11.14
|
||||
* @author Thomas.pfleiderer@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2022
|
||||
*
|
||||
*/
|
||||
#ifndef COMPONENT_IMPL_H
|
||||
#define COMPONENT_IMPL_H
|
||||
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "../interfaces/core_types.h"
|
||||
#include "../interfaces/core.h"
|
||||
#include "../interfaces/repository.h"
|
||||
#include "interface_ptr.h"
|
||||
#include "local_service_access.h"
|
||||
|
||||
// NOLINTBEGIN(cppcoreguidelines-macro-usage)
|
||||
|
||||
/**
|
||||
* @brief Stringize helper.
|
||||
*/
|
||||
#define SDV_STRINGIZE_HELPER2(txt) #txt
|
||||
/**
|
||||
* @brief Stringize helper.
|
||||
*/
|
||||
#define SDV_STRINGIZE_HELPER(txt) SDV_STRINGIZE_HELPER2(txt)
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-macro-usage)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// Resolve conflict
|
||||
#pragma push_macro("interface")
|
||||
#undef interface
|
||||
#pragma push_macro("GetObject")
|
||||
#undef GetObject
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#include <objbase.h>
|
||||
|
||||
// Resolve conflict
|
||||
#pragma pop_macro("GetObject")
|
||||
#pragma pop_macro("interface")
|
||||
#ifdef GetClassInfo
|
||||
#undef GetClassInfo
|
||||
#endif
|
||||
|
||||
#elif defined __unix__
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif // defined _MSC_VER
|
||||
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
namespace sdv
|
||||
{
|
||||
// Forward declarations
|
||||
class CSdvObject;
|
||||
|
||||
|
||||
////////////////////////////////////
|
||||
// Object control classes //
|
||||
////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief SDV object create interface.
|
||||
* @remarks This is an internal interface not exposed through IInterfaceAccess.
|
||||
*/
|
||||
struct ISdvObjectClassInfo
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Get the class information struct.
|
||||
* @return Returns the class information struct.
|
||||
*/
|
||||
virtual sdv::SClassInfo GetClassInfo() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Create the SDV object.
|
||||
* @return Returns an instance of the SDV object or nullptr when the object could not be created.
|
||||
*/
|
||||
virtual std::unique_ptr<CSdvObject> CreateObject() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Top level SDV object to solve ambiguities in the use of IInterfaceAccess. THis class is used by
|
||||
* CSdvObjectClass during the instantiation of the SDV object.
|
||||
*/
|
||||
class CSdvObjectAccess : public IInterfaceAccess
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CSdvObjectAccess() = default;
|
||||
|
||||
CSdvObjectAccess(CSdvObjectAccess&) = delete;
|
||||
CSdvObjectAccess& operator=(CSdvObjectAccess&) = delete;
|
||||
CSdvObjectAccess(CSdvObjectAccess&&) = delete;
|
||||
CSdvObjectAccess& operator=(CSdvObjectAccess&&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Default virtual destructor
|
||||
*/
|
||||
virtual ~CSdvObjectAccess() = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to the implemented IInterfaceAccess interface.
|
||||
* @return Returns a pointer to the implementation of IInterfaceAccess.
|
||||
*/
|
||||
IInterfaceAccess* GetObjectAccess()
|
||||
{
|
||||
return static_cast<IInterfaceAccess*>(this);
|
||||
}
|
||||
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
END_SDV_INTERFACE_MAP()
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Lifetime cookie to automatically manage the module lifetime.
|
||||
* @details The lifetime cookie uses an increment and decrement function to increment for every assigned instantiation of
|
||||
* the cookie and to decrement every previously instantiated cookie. This allows the classfactory to keep track of its lifetime
|
||||
* even with dynamically created objects.
|
||||
*/
|
||||
class CLifetimeCookie
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
CLifetimeCookie() = default;
|
||||
|
||||
/**
|
||||
* @brief Assignment constructor, assigning the increment and decrement functions.
|
||||
* @details Assign the increment and decrement functions and increase the incrementation.
|
||||
* @param[in] fnLifetimeIncr Increment function object.
|
||||
* @param[in] fnLifetimeDecr Decrement function object.
|
||||
*/
|
||||
CLifetimeCookie(std::function<void()> fnLifetimeIncr, std::function<void()> fnLifetimeDecr) :
|
||||
m_fnLifetimeIncr(fnLifetimeIncr), m_fnLifetimeDecr(fnLifetimeDecr)
|
||||
{
|
||||
if (m_fnLifetimeIncr) m_fnLifetimeIncr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor.
|
||||
* @details Construct a lifetime cookie object and copy the increment and decrement functions and call the increment
|
||||
* function if valid.
|
||||
* @param[in] rCookie Reference to the cookie to copy from.
|
||||
*/
|
||||
CLifetimeCookie(const CLifetimeCookie& rCookie) :
|
||||
m_fnLifetimeIncr(rCookie.m_fnLifetimeIncr), m_fnLifetimeDecr(rCookie.m_fnLifetimeDecr)
|
||||
{
|
||||
if (m_fnLifetimeIncr) m_fnLifetimeIncr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @details Construct a lifetime cookie object and move the functions from the provided cookie. Then reset the functions
|
||||
* of the provided cookie.
|
||||
* @param[in] rCookie Reference to the cookie to copy from.
|
||||
*/
|
||||
CLifetimeCookie(CLifetimeCookie&& rCookie) noexcept :
|
||||
m_fnLifetimeIncr(rCookie.m_fnLifetimeIncr), m_fnLifetimeDecr(rCookie.m_fnLifetimeDecr)
|
||||
{
|
||||
rCookie.m_fnLifetimeIncr = nullptr;
|
||||
rCookie.m_fnLifetimeDecr = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the lifetime cookie.
|
||||
* @details Decrement the lifetime by calling the decrement function if valid and destroy the cookie object.
|
||||
*/
|
||||
~CLifetimeCookie()
|
||||
{
|
||||
if (m_fnLifetimeDecr) m_fnLifetimeDecr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator.
|
||||
* @details Release the current lifetime by calling the decrement function and assign the increment and decrement functions
|
||||
* of the provided cookie and call the increment function if valid.
|
||||
* @param[in] rCookie Reference to the cookie to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CLifetimeCookie& operator=(const CLifetimeCookie& rCookie)
|
||||
{
|
||||
if (m_fnLifetimeDecr) m_fnLifetimeDecr();
|
||||
m_fnLifetimeIncr = rCookie.m_fnLifetimeIncr;
|
||||
m_fnLifetimeDecr = rCookie.m_fnLifetimeDecr;
|
||||
if (m_fnLifetimeIncr) m_fnLifetimeIncr();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move operator.
|
||||
* @details Release the current lifetime by calling the decrement function and move the functions from the provided cookie.
|
||||
* Then reset the functions of the provided cookie.
|
||||
* @param[in] rCookie Reference to the cookie to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CLifetimeCookie& operator=(CLifetimeCookie&& rCookie) noexcept
|
||||
{
|
||||
if (m_fnLifetimeDecr) m_fnLifetimeDecr();
|
||||
m_fnLifetimeIncr = rCookie.m_fnLifetimeIncr;
|
||||
m_fnLifetimeDecr = rCookie.m_fnLifetimeDecr;
|
||||
rCookie.m_fnLifetimeIncr = nullptr;
|
||||
rCookie.m_fnLifetimeDecr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> m_fnLifetimeIncr; ///< Lifetime increment function
|
||||
std::function<void()> m_fnLifetimeDecr; ///< Lifetime decrement function
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Global tracking of active objects. Functions in this class will only be called by CSdvObject and CSdvObjectClass
|
||||
*/
|
||||
class CObjectFactory : public IInterfaceAccess, public IObjectFactory
|
||||
{
|
||||
// Friend class SDV object and definition
|
||||
friend class CSdvObject; ///< SDV object base class.
|
||||
template <class TSdvObject>
|
||||
friend class CSdvObjectClass; ///< SDV object creator class.
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
CObjectFactory() = default;
|
||||
|
||||
/**
|
||||
* @brief Interface map.
|
||||
*/
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(IObjectFactory)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief Create a lifetime cookie that keeps track of the module lifetime as long as it is alive.
|
||||
* @return Returns a lifetime cookie.
|
||||
*/
|
||||
CLifetimeCookie CreateLifetimeCookie()
|
||||
{
|
||||
return CLifetimeCookie([this]() { m_uiActiveObjectCount++; },
|
||||
[this]() { if (m_uiActiveObjectCount) m_uiActiveObjectCount--; });
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the amount of active SDV objects.
|
||||
* @return Returns the number of active SDV objects.
|
||||
*/
|
||||
uint32_t GetActiveObjects() const
|
||||
{
|
||||
return m_uiActiveObjectCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the module manifest.
|
||||
* @return Returns the pointer to a zero terminated string containing the module manifest or NULL when there is no string.
|
||||
*/
|
||||
const char* GetManifest()
|
||||
{
|
||||
if (m_ssManifest.empty())
|
||||
BuildManifest();
|
||||
return m_ssManifest.c_str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create or get the object using the name from the object class info. Overload of
|
||||
* sdv::IObjectFactory::CreateObject.
|
||||
* @attention The objects lifetime is ended by a call to the DestroyObject function or the unloading of he module.
|
||||
* @param[in] ssClassName The name of the class object to instantiate.
|
||||
* @return Pointer to IInterfaceAccess interface of the object or NULL when the requested object doesn't exist.
|
||||
*/
|
||||
virtual IInterfaceAccess* CreateObject(const sdv::u8string& ssClassName) override;
|
||||
|
||||
/**
|
||||
* @brief Destroy an instantiated object using the name of the object class info. Overload of
|
||||
* sdv::IObjectFactory::DestroyObject.
|
||||
* @param[in] object The object to destroy.
|
||||
*/
|
||||
virtual void DestroyObject(IInterfaceAccess* object) override;
|
||||
|
||||
/**
|
||||
* @brief Destroys all active objects in reverse order of creation
|
||||
*/
|
||||
virtual void DestroyAllObjects() override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Build the module manifest.
|
||||
* @return Returns the pointer to a zero terminated string containing the module manifest or NULL when there is no string.
|
||||
*/
|
||||
void BuildManifest()
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << R"code(# Module manifest
|
||||
|
||||
[Interface]
|
||||
Version = )code" << SDVFrameworkInterfaceVersion
|
||||
<< R"code(
|
||||
|
||||
)code";
|
||||
std::shared_lock<std::shared_mutex> lock(m_mtxObjectClasses);
|
||||
for (const ISdvObjectClassInfo* pClassInfo : m_vecObjectClasses)
|
||||
{
|
||||
sdv::SClassInfo sInfo = pClassInfo->GetClassInfo();
|
||||
sstream << "[[Component]]" << std::endl;
|
||||
sstream << "Class=\"" << sInfo.ssClassName << "\"" << std::endl;
|
||||
if (!sInfo.seqClassAliases.empty())
|
||||
{
|
||||
sstream << "Aliases=[";
|
||||
bool bInitialAlias = true;
|
||||
for (const sdv::u8string& rssAlias : sInfo.seqClassAliases)
|
||||
{
|
||||
if (!bInitialAlias)
|
||||
sstream << ", ";
|
||||
bInitialAlias = false;
|
||||
sstream << "\"" << rssAlias << "\"";
|
||||
}
|
||||
sstream << "]" << std::endl;
|
||||
}
|
||||
if (!sInfo.ssDefaultObjectName.empty())
|
||||
sstream << "DefaultName=\"" << sInfo.ssDefaultObjectName << "\"" << std::endl;
|
||||
bool bSkip = false;
|
||||
switch (sInfo.eType)
|
||||
{
|
||||
case sdv::EObjectType::SystemObject:
|
||||
sstream << "Type=\""
|
||||
<< "System"
|
||||
<< "\"" << std::endl;
|
||||
break;
|
||||
case sdv::EObjectType::Device:
|
||||
sstream << "Type=\""
|
||||
<< "Device"
|
||||
<< "\"" << std::endl;
|
||||
break;
|
||||
case sdv::EObjectType::BasicService:
|
||||
sstream << "Type=\""
|
||||
<< "BasicService"
|
||||
<< "\"" << std::endl;
|
||||
break;
|
||||
case sdv::EObjectType::ComplexService:
|
||||
sstream << "Type=\""
|
||||
<< "ComplexService"
|
||||
<< "\"" << std::endl;
|
||||
break;
|
||||
case sdv::EObjectType::Application:
|
||||
sstream << "Type=\""
|
||||
<< "App"
|
||||
<< "\"" << std::endl;
|
||||
break;
|
||||
case sdv::EObjectType::Proxy:
|
||||
sstream << "Type=\""
|
||||
<< "Proxy"
|
||||
<< "\"" << std::endl;
|
||||
break;
|
||||
case sdv::EObjectType::Stub:
|
||||
sstream << "Type=\""
|
||||
<< "Stub"
|
||||
<< "\"" << std::endl;
|
||||
break;
|
||||
case sdv::EObjectType::Utility:
|
||||
sstream << "Type=\""
|
||||
<< "Utility"
|
||||
<< "\"" << std::endl;
|
||||
break;
|
||||
default:
|
||||
bSkip = true;
|
||||
break;
|
||||
}
|
||||
if (bSkip)
|
||||
continue;
|
||||
if (sInfo.uiFlags & static_cast<uint32_t>(sdv::EObjectFlags::singleton))
|
||||
sstream << "Singleton=true" << std::endl;
|
||||
if (!sInfo.seqDependencies.empty())
|
||||
{
|
||||
sstream << "Dependencies=[";
|
||||
bool bInitialDependency = true;
|
||||
for (const sdv::u8string& rssDependsOn : sInfo.seqDependencies)
|
||||
{
|
||||
if (!bInitialDependency)
|
||||
sstream << ", ";
|
||||
bInitialDependency = false;
|
||||
sstream << "\"" << rssDependsOn << "\"";
|
||||
}
|
||||
sstream << "]" << std::endl;
|
||||
}
|
||||
}
|
||||
m_ssManifest = sstream.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Expose the object prototype by placing it into the object prototype list.
|
||||
* @details Expose the object class to allow class access. This function is called by the constructor of the
|
||||
* class object.
|
||||
* @param[in] pObjectClassInfo The object class internal interface.
|
||||
*/
|
||||
void ExposeObjectClass(ISdvObjectClassInfo* pObjectClassInfo)
|
||||
{
|
||||
if (pObjectClassInfo)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock(m_mtxObjectClasses);
|
||||
m_vecObjectClasses.push_back(pObjectClassInfo);
|
||||
|
||||
// Attention: pObjectClass is a pointer to ISdvObjectClassInfo even if the class was derived.
|
||||
// Virtual functions are not available yet at this stage.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Revoke the object prototype from the object prototype list.
|
||||
* @param[in] pObjectClassInfo The object class internal interface.
|
||||
*/
|
||||
void RevokeObjectClass(const ISdvObjectClassInfo* pObjectClassInfo)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock(m_mtxObjectClasses);
|
||||
auto itObjectClass = std::find(m_vecObjectClasses.begin(), m_vecObjectClasses.end(), pObjectClassInfo);
|
||||
if (itObjectClass != m_vecObjectClasses.end())
|
||||
m_vecObjectClasses.erase(itObjectClass);
|
||||
// TODO EVE: Updated through cppcheck warning
|
||||
//for (auto objectClassIter = m_vecObjectClasses.begin(); objectClassIter != m_vecObjectClasses.end();
|
||||
// objectClassIter++)
|
||||
//{
|
||||
// if (*objectClassIter == pObjectClassInfo)
|
||||
// {
|
||||
// m_vecObjectClasses.erase(objectClassIter);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<uint32_t> m_uiActiveObjectCount{0}; ///< The amount of active SDV objects.
|
||||
|
||||
mutable std::mutex m_mtxActiveObjects; ///< Synchronize access to m_vecActiveObjects
|
||||
std::vector<std::unique_ptr<CSdvObject>> m_vecActiveObjects; ///< List of objects actively kept alive
|
||||
|
||||
mutable std::shared_mutex m_mtxObjectClasses; ///< Synchronize access to the object classes.
|
||||
std::vector<ISdvObjectClassInfo*> m_vecObjectClasses; ///< List of object classes contained in this module.
|
||||
|
||||
std::string m_ssManifest; ///< Manifest of this module.
|
||||
};
|
||||
|
||||
////////////////////////////////////
|
||||
// Framework module classes //
|
||||
////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Class that manages the object instantiation and module lifetime.
|
||||
* @remarks A pointer to an instance of this class is exposed across dll boundaries and used to implement
|
||||
* CModuleInstance for SDV DLLs
|
||||
* The instance is created by the DEFINE_SDV_OBJECT macro and the macro also registers a helper capable of
|
||||
* instantiating the SDV object with the instance (see CObjectFactory for details)
|
||||
*/
|
||||
class CModule
|
||||
: public CSdvObjectAccess
|
||||
, public CObjectFactory
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CModule() = default;
|
||||
|
||||
/**
|
||||
* @brief Interface map.
|
||||
*/
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_CHAIN_BASE(CObjectFactory)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief Check whether the requested interface version corresponds to the one implemented here and return this
|
||||
* object.
|
||||
* @param[in] interfaceVersion The version of module interface that is requested for.
|
||||
* @return Returns the IInterfaceAccess interface of the module if the interface versions match, nullptr otherwise
|
||||
*/
|
||||
IInterfaceAccess* GetModuleControl(uint32_t interfaceVersion)
|
||||
{
|
||||
// No compatibility interfacing available yet.
|
||||
return interfaceVersion == SDVFrameworkInterfaceVersion ? GetObjectAccess() : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Module access (global per module).
|
||||
* @return Reference to the global module.
|
||||
*/
|
||||
inline CModule& GetModule()
|
||||
{
|
||||
static CModule module;
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a lifetime cookie that keeps track of the module lifetime as long as it is alive.
|
||||
* @return Returns a lifetime cookie.
|
||||
*/
|
||||
inline CLifetimeCookie CreateLifetimeCookie()
|
||||
{
|
||||
return GetModule().CreateLifetimeCookie();
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// Component object class //
|
||||
////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief SDV object creator class. Used to define the SDV class object and register its definition into the system
|
||||
* as welll a as providing the creation interface for creating an object instance.
|
||||
* @tparam TSdvObject Class type of the SDV object derived from CSdvObject.
|
||||
*/
|
||||
template <class TSdvObject>
|
||||
class CSdvObjectClass
|
||||
: public ISdvObjectClassInfo
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor assigning the SDV prototype to the module.
|
||||
*/
|
||||
CSdvObjectClass()
|
||||
{
|
||||
// Add this object definition to the definition list.
|
||||
GetModule().ExposeObjectClass(this);
|
||||
}
|
||||
|
||||
CSdvObjectClass(CSdvObjectClass&) = delete;
|
||||
CSdvObjectClass(CSdvObjectClass&&) = delete;
|
||||
CSdvObjectClass& operator=(CSdvObjectClass&) = delete;
|
||||
CSdvObjectClass& operator=(CSdvObjectClass&&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Destructor revoking the object prototype.
|
||||
*/
|
||||
virtual ~CSdvObjectClass()
|
||||
{
|
||||
GetModule().RevokeObjectClass(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the object class name.
|
||||
* @return Returns the class name of the object.
|
||||
* @remarks Default implementation gets the information from the object class if not defined in the definition.
|
||||
*/
|
||||
virtual sdv::u8string GetClassName() const
|
||||
{
|
||||
return TSdvObject::GetClassNameStatic();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the class name aliases.
|
||||
* @return Returns a sequence containing zero or more class name aliases.
|
||||
* @remarks Default implementation gets the information from the object class if not defined in the definition.
|
||||
*/
|
||||
virtual sdv::sequence<sdv::u8string> GetClassAliases() const
|
||||
{
|
||||
return TSdvObject::GetClassAliasesStatic();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the default object name.
|
||||
* @return Returns the default name of the object if exists.
|
||||
*/
|
||||
virtual sdv::u8string GetDefaultObjectName() const
|
||||
{
|
||||
return TSdvObject::GetDefaultObjectNameStatic();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Is the object marked as singleton.
|
||||
* @return Returns whether the object is a singleton object.
|
||||
*/
|
||||
virtual bool IsSingleton() const
|
||||
{
|
||||
return TSdvObject::IsSingletonStatic();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get object dependencies.
|
||||
* @return Returns a vector containing the class names of the objects this component is dependent on.
|
||||
*/
|
||||
virtual sdv::sequence<sdv::u8string> GetObjectDependencies() const
|
||||
{
|
||||
return TSdvObject::GetObjectDependenciesStatic();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the object type.
|
||||
* @return Returns the type of the object
|
||||
* @remarks Default implementation gets the information from the object class if not defined in the definition.
|
||||
*/
|
||||
virtual EObjectType GetObjectType() const
|
||||
{
|
||||
return TSdvObject::GetObjectType();
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Helper function to retrieve the object creation flags.
|
||||
* @return Returns the current flags of the object
|
||||
*/
|
||||
uint32_t GetObjectFlags() const
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (IsSingleton()) flags |= static_cast<uint32_t>(EObjectFlags::singleton);
|
||||
|
||||
// Currently no other flags known.
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the class information struct. Overload of ISdvObjectClassInfo::GetClassInfo.
|
||||
* @return Returns the class information struct.
|
||||
*/
|
||||
sdv::SClassInfo GetClassInfo() const override
|
||||
{
|
||||
sdv::SClassInfo classInfo{};
|
||||
classInfo.ssClassName = GetClassName();
|
||||
classInfo.seqClassAliases = GetClassAliases();
|
||||
classInfo.ssDefaultObjectName = GetDefaultObjectName();
|
||||
classInfo.eType = GetObjectType();
|
||||
classInfo.uiFlags = GetObjectFlags();
|
||||
classInfo.seqDependencies = GetObjectDependencies();
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create the SDV object. Overload of ISdvObjectClassInfo::CreateObject.
|
||||
* @return Returns an instance of the SDV object or nullptr when the object could not be created (exception thrown during construction).
|
||||
*/
|
||||
std::unique_ptr<CSdvObject> CreateObject() override
|
||||
{
|
||||
std::unique_ptr<CSdvObject> ret;
|
||||
try
|
||||
{
|
||||
ret = std::make_unique<TSdvObject>();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
SDV_LOG(core::ELogSeverity::error, "Failed to instantiate object of class ", GetClassName(), " - exception thrown during construction! ");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SDV object base class.
|
||||
*/
|
||||
class CSdvObject : public CSdvObjectAccess
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Use the default object creator class.
|
||||
*/
|
||||
template <class TSdvObject>
|
||||
using TSdvObjectCreator = CSdvObjectClass<TSdvObject>;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
CSdvObject() = default;
|
||||
|
||||
CSdvObject(CSdvObject&) = delete;
|
||||
CSdvObject& operator=(CSdvObject&) = delete;
|
||||
CSdvObject(CSdvObject&&) = delete;
|
||||
CSdvObject& operator=(CSdvObject&&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CSdvObject() override
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Class aliases sequence if not provided.
|
||||
* @return An empty sequence of class aliases.
|
||||
*/
|
||||
static sdv::sequence<sdv::u8string> GetClassAliasesStatic() { return {}; }
|
||||
|
||||
/**
|
||||
* @brief Default object name is not set.
|
||||
* @return The empty default object name
|
||||
*/
|
||||
static sdv::u8string GetDefaultObjectNameStatic() { return {}; }
|
||||
|
||||
/**
|
||||
* @brief Return whether the object is a singleton object (only one instance will be created of the object).
|
||||
* @return Returns whether the object is a singleton.
|
||||
*/
|
||||
static bool IsSingletonStatic() { return false; }
|
||||
|
||||
/**
|
||||
* @brief Get object dependencies.
|
||||
* @return Returns a vector containing the class names of the objects this component is dependent on.
|
||||
*/
|
||||
static sdv::sequence<sdv::u8string> GetObjectDependenciesStatic() { return sdv::sequence<sdv::u8string>(); }
|
||||
|
||||
/**
|
||||
* @brief Interface map
|
||||
*/
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
END_SDV_INTERFACE_MAP()
|
||||
};
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Object control class implementation //
|
||||
/////////////////////////////////////////
|
||||
|
||||
inline IInterfaceAccess* CObjectFactory::CreateObject(const sdv::u8string& ssClassName)
|
||||
{
|
||||
if (ssClassName.empty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_lock<std::shared_mutex> lock(m_mtxObjectClasses);
|
||||
for (ISdvObjectClassInfo* pObjectClassInfo : m_vecObjectClasses)
|
||||
{
|
||||
if (pObjectClassInfo == nullptr)continue;
|
||||
sdv::SClassInfo sClassInfo = pObjectClassInfo->GetClassInfo();
|
||||
|
||||
// Check for the class name.
|
||||
bool bFound = sClassInfo.ssClassName == ssClassName;
|
||||
|
||||
// If not found, check for all aliases.
|
||||
for (auto itAlias = sClassInfo.seqClassAliases.begin(); !bFound && itAlias != sClassInfo.seqClassAliases.end(); itAlias++)
|
||||
bFound = *itAlias == ssClassName;
|
||||
if (!bFound) continue;
|
||||
|
||||
++m_uiActiveObjectCount;
|
||||
auto object = pObjectClassInfo->CreateObject();
|
||||
lock.unlock();
|
||||
if(!object)
|
||||
{
|
||||
--m_uiActiveObjectCount;
|
||||
return nullptr;
|
||||
}
|
||||
auto ret = object.get()->GetObjectAccess();
|
||||
std::unique_lock<std::mutex> lockObjects (m_mtxActiveObjects);
|
||||
m_vecActiveObjects.emplace_back(std::move(object));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline void CObjectFactory::DestroyObject(IInterfaceAccess* object)
|
||||
{
|
||||
if (object == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lockObjects(m_mtxActiveObjects);
|
||||
for(auto iter = m_vecActiveObjects.begin(); iter!= m_vecActiveObjects.end();++iter)
|
||||
{
|
||||
if(iter->get()->GetObjectAccess() == object)
|
||||
{
|
||||
auto objectPtr = std::move(*iter);
|
||||
m_vecActiveObjects.erase(iter);
|
||||
lockObjects.unlock();
|
||||
objectPtr = nullptr;
|
||||
if (m_uiActiveObjectCount) --m_uiActiveObjectCount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline void CObjectFactory::DestroyAllObjects()
|
||||
{
|
||||
std::unique_lock<std::mutex> lockObjects(m_mtxActiveObjects);
|
||||
auto objects = std::move(m_vecActiveObjects);
|
||||
lockObjects.unlock();
|
||||
while(!objects.empty())
|
||||
{
|
||||
objects.pop_back();
|
||||
if (m_uiActiveObjectCount) --m_uiActiveObjectCount;
|
||||
}
|
||||
}
|
||||
} // namespace sdv
|
||||
|
||||
// NOLINTBEGIN(cppcoreguidelines-macro-usage)
|
||||
|
||||
/**
|
||||
* @brief Define the SDV object (derived from CSdvObject) to be exposed to the framework.
|
||||
* @param sdv_object_class The object class must derive from sdv::CSdvObject.
|
||||
*/
|
||||
#define DEFINE_SDV_OBJECT(sdv_object_class) \
|
||||
struct SObjectClassInstance_##sdv_object_class \
|
||||
{ \
|
||||
public: \
|
||||
SObjectClassInstance_##sdv_object_class() \
|
||||
{ \
|
||||
/* Enforce derivation of sdv::CSdvObject. */ \
|
||||
static_assert(std::is_base_of<sdv::CSdvObject, sdv_object_class>::value, \
|
||||
"CSdvObject is not base of sdv_object_class"); \
|
||||
/* Call the static function once to instantiate the definition. */ \
|
||||
GetObjectClassInstance(); \
|
||||
} \
|
||||
static sdv_object_class::TSdvObjectCreator<sdv_object_class>& GetObjectClassInstance() \
|
||||
{ \
|
||||
static sdv_object_class::TSdvObjectCreator<sdv_object_class> object_class; \
|
||||
return object_class; \
|
||||
} \
|
||||
}; \
|
||||
static SObjectClassInstance_##sdv_object_class g_##sdv_object_class; \
|
||||
extern "C" SDV_SYMBOL_PUBLIC bool HasActiveObjects(); \
|
||||
extern "C" SDV_SYMBOL_PUBLIC sdv::IInterfaceAccess* GetModuleFactory(uint32_t uiInterfaceVersion); \
|
||||
extern "C" SDV_SYMBOL_PUBLIC const char* GetManifest();
|
||||
|
||||
/**
|
||||
* @brief Define the SDV object (derived from CSdvObject) to be exposed to the framework. Do not define export functions.
|
||||
* @param sdv_object_class The object class must derive from sdv::CSdvObject.
|
||||
*/
|
||||
#define DEFINE_SDV_OBJECT_NO_EXPORT(sdv_object_class) \
|
||||
struct SObjectClassInstance_##sdv_object_class \
|
||||
{ \
|
||||
public: \
|
||||
SObjectClassInstance_##sdv_object_class() \
|
||||
{ \
|
||||
/* Enforce derivation of sdv::CSdvObject. */ \
|
||||
static_assert(std::is_base_of<sdv::CSdvObject, sdv_object_class>::value, \
|
||||
"CSdvObject is not base of sdv_object_class"); \
|
||||
/* Call the static function once to instantiate the definition. */ \
|
||||
GetObjectClassInstance(); \
|
||||
} \
|
||||
static sdv_object_class::TSdvObjectCreator<sdv_object_class>& GetObjectClassInstance() \
|
||||
{ \
|
||||
static sdv_object_class::TSdvObjectCreator<sdv_object_class> object_class; \
|
||||
return object_class; \
|
||||
} \
|
||||
}; \
|
||||
static SObjectClassInstance_##sdv_object_class g_##sdv_object_class; \
|
||||
bool HasActiveObjects(); \
|
||||
sdv::IInterfaceAccess* GetModuleFactory(uint32_t uiInterfaceVersion); \
|
||||
const char* GetManifest();
|
||||
|
||||
/**
|
||||
* @brief Declare the object class type. To be placed in the SDV object class derived from CSdvObject.
|
||||
* \param class_type The type of the object (EObjectType).
|
||||
*/
|
||||
#define DECLARE_OBJECT_CLASS_TYPE(class_type) \
|
||||
/** \
|
||||
* @brief Declare the object class type. To be placed in the SDV object class derived from CSdvObject. \
|
||||
* @return Returns the type of the object (EObjectType). \
|
||||
*/ \
|
||||
constexpr static sdv::EObjectType GetObjectType() \
|
||||
{ \
|
||||
return class_type; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Declare the object class name. To be placed in the SDV object class derived from CSdvObject.
|
||||
* @param class_name_string The UTF-8 string containing the name of the object.
|
||||
*/
|
||||
#define DECLARE_OBJECT_CLASS_NAME(class_name_string) \
|
||||
static sdv::u8string GetClassNameStatic() \
|
||||
{ \
|
||||
return class_name_string; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Declare the object class aliases. To be placed in the SDV object class derived from CSdvObject.
|
||||
* @param ... Multiple UTF-8 strings containing the alias names for the object class.
|
||||
*/
|
||||
#define DECLARE_OBJECT_CLASS_ALIAS(...) \
|
||||
static sdv::sequence<sdv::u8string> GetClassAliasesStatic() \
|
||||
{ \
|
||||
return sdv::sequence<sdv::u8string>({__VA_ARGS__}); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Declare the default object name. To be placed in the SDV object class derived from CSdvObject.
|
||||
* @param object_name_string The UTF-8 string containing the name of the object.
|
||||
*/
|
||||
#define DECLARE_DEFAULT_OBJECT_NAME(object_name_string) \
|
||||
static sdv::u8string GetDefaultObjectNameStatic() \
|
||||
{ \
|
||||
return object_name_string; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Declare the object to be a singleton object (only one instance will be created of the object).
|
||||
*/
|
||||
#define DECLARE_OBJECT_SINGLETON() \
|
||||
static bool IsSingletonStatic() { return true; }
|
||||
|
||||
/**
|
||||
* @brief Declare the object to be a singleton object (only one instance will be created of the object).
|
||||
* One or more strings with the class/default names of the objects the component is dependent on.
|
||||
*/
|
||||
#define DECLARE_OBJECT_DEPENDENCIES(...) \
|
||||
static sdv::sequence<sdv::u8string> GetObjectDependenciesStatic() { return sdv::sequence<sdv::u8string>({__VA_ARGS__}); }
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-macro-usage)
|
||||
|
||||
/*
|
||||
* @brief Returns whether or not instances of objects implemented by this module are running. If none, the module can be unloaded.
|
||||
* @remarks Unloading the module with running instances could cause a crash and should be prevented at all costs. Unloading the
|
||||
* module removes the code of the objects still running.
|
||||
* @return Returns true when object instances are running; otherwise returns 'false'.
|
||||
*/
|
||||
inline extern bool HasActiveObjects()
|
||||
{
|
||||
return sdv::GetModule().GetActiveObjects() != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Get the module factory interface with a specific version.
|
||||
* @details This function provides access to the objects being implemented in this module.
|
||||
* @param[in] interfaceVersion Request the module factory for a specific interface version. Using another interface version than
|
||||
* the one returned from the manifest, might cause the function to fail.
|
||||
* @return Returns pointer to the IInterfaceAccess interface of the module factory object.
|
||||
*/
|
||||
inline extern sdv::IInterfaceAccess* GetModuleFactory(uint32_t interfaceVersion)
|
||||
{
|
||||
return sdv::GetModule().GetModuleControl(interfaceVersion);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Get the the module manifest.
|
||||
* @details Each module contains a manifest containing general information as well as information about the component classes. This
|
||||
* allows installing the component without having to instantiate the classes.
|
||||
* @return Returns the pointer to a zero terminated string containing the module manifest or NULL when there is no string.
|
||||
*/
|
||||
inline extern const char* GetManifest()
|
||||
{
|
||||
return sdv::GetModule().GetManifest();
|
||||
}
|
||||
|
||||
#endif // !defined COMPONENT_IMPL_H
|
||||
207
export/support/crc.h
Normal file
207
export/support/crc.h
Normal file
@@ -0,0 +1,207 @@
|
||||
#ifndef SDV_CRC_H
|
||||
#define SDV_CRC_H
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief Reflect the bits within the data type (change the order MSB <--> LSB).
|
||||
* @tparam T The type to use for bit reflection.
|
||||
* @param[in] tValue The value to reflect. Must be a arithmetic or boolean type.
|
||||
* @return The reflected value.
|
||||
*/
|
||||
template <typename T>
|
||||
constexpr T reflect(T tValue)
|
||||
{
|
||||
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, bool>);
|
||||
|
||||
T tMask = 1;
|
||||
T tReflection{0};
|
||||
for (size_t nBit = 0; nBit < sizeof(T) * 8; nBit++)
|
||||
{
|
||||
tReflection <<= 1;
|
||||
if (tValue & tMask)
|
||||
tReflection |= 0x1;
|
||||
tMask <<= 1;
|
||||
}
|
||||
return tReflection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Templated CRC calculation class
|
||||
* @tparam TCRC The CRC type to use for the calculation.
|
||||
* @tparam tPolynomial The polynomial of the CRC function.
|
||||
* @tparam tInitVal The initial value to use for the calculation.
|
||||
* @tparam tXorOut XOR the result with the provided value.
|
||||
* @tparam bReflectIn Reflect the input bits.
|
||||
* @tparam bReflectOut Reflect the output bits.
|
||||
*/
|
||||
template <typename TCRC, TCRC tPolynomial, TCRC tInitVal, TCRC tXorOut, bool bReflectIn, bool bReflectOut>
|
||||
class crc
|
||||
{
|
||||
public:
|
||||
using TCRCType = TCRC; ///< CRC type
|
||||
|
||||
/**
|
||||
* @brief Calculate the CRC checksum value providing a buffer with data of type T.
|
||||
* @attention This function doesn't reset the CRC that was calculated before.
|
||||
* @remarks The CRC calculation occurs byte-wise regardless of the endianness of the the processor architecture.
|
||||
* @tparam T Type of the value buffer to calculate the CRC for.
|
||||
* @param[in] pData Pointer to the value buffer.
|
||||
* @param[in] nCount Amount of values in the buffer.
|
||||
* @return The calculated CRC checksum.
|
||||
*/
|
||||
template <typename T>
|
||||
TCRCType calc_checksum(const T* pData, size_t nCount) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Add one value to the calculation.
|
||||
* @remarks The CRC calculation occurs byte-wise regardless of the endianness of the the processor architecture.
|
||||
* @tparam T Type of the value buffer to calculate the CRC for.
|
||||
* @param[in] tValue The value to add to the calculation.
|
||||
*/
|
||||
template <typename T>
|
||||
void add(T tValue) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get the currently calculated checksum.
|
||||
* @return The CRC checksum.
|
||||
*/
|
||||
TCRCType get_checksum() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Set a CRC checksum to continue the calculation with additional data.
|
||||
* @param[in] tCrcValue The previously calculated CRC value.
|
||||
*/
|
||||
void set_checksum(TCRCType tCrcValue) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Reset the current calculation (resets the CRC value to its initial value).
|
||||
*/
|
||||
void reset() noexcept;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief With of the CRC type in bits.
|
||||
*/
|
||||
static constexpr uint64_t m_nWidth = 8 * sizeof(TCRCType);
|
||||
|
||||
/**
|
||||
* @brief MSB for the CRC type.
|
||||
*/
|
||||
static constexpr uint64_t m_nMsb = 1ull << (m_nWidth - 1);
|
||||
|
||||
/**
|
||||
* @brief CRC lookup table.
|
||||
*/
|
||||
static constexpr auto m_arrTable = []
|
||||
{
|
||||
std::array<TCRCType, 256> arrTemp{};
|
||||
for (size_t tDividend = 0; tDividend < 256; ++tDividend)
|
||||
{
|
||||
TCRCType tRemainder = static_cast<TCRCType>(tDividend << (m_nWidth - 8));
|
||||
for (uint8_t bit = 8; bit > 0; --bit)
|
||||
{
|
||||
if (tRemainder & m_nMsb)
|
||||
tRemainder = (tRemainder << 1) ^ tPolynomial;
|
||||
else
|
||||
tRemainder = (tRemainder << 1);
|
||||
}
|
||||
arrTemp[tDividend] = tRemainder;
|
||||
}
|
||||
return arrTemp;
|
||||
}();
|
||||
|
||||
TCRCType m_tCrcValue = tInitVal; ///< Calculated CRC value.
|
||||
};
|
||||
|
||||
/// SAE-J1850: polynomial 0x1D, initial = 0xFF, final_xor = 0xFF, reflect_input = false, reflect_output = false
|
||||
using crcSAE_J1850 = sdv::crc<uint8_t, 0x1du, 0xff, 0xff, false, false>;
|
||||
|
||||
/// AUTOSAR_8H2F: polynomial 0x2F, initial = 0xFF, final_xor = 0xFF, reflect_input = false, reflect_output = false)
|
||||
using crcAUTOSAR_8H2F = sdv::crc<uint8_t, 0x2fu, 0xff, 0xff, false, false>;
|
||||
|
||||
/// CCITT-FALSE: polynomial 0x1021, initial = 0xFFFF, final_xor = 0, reflect_input = false, reflect_output = false
|
||||
using crcCCITT_FALSE = sdv::crc<uint16_t, 0x1021u, 0xffffu, 0, false, false> ;
|
||||
|
||||
/// ARC: polynomial 0x8005, initial = 0, final_xor = 0, reflect_input = true, reflect_output = true
|
||||
using crcARC = sdv::crc<uint16_t, 0x8005, 0, 0, true, true>;
|
||||
|
||||
/// IEEE_802_3 polynomial 0x04C11DB7, initial = 0xFFFFFFFF, final_xor = 0xFFFFFFFF, reflect_input = true, reflect_output = true
|
||||
using crcIEEE_802_3 = sdv::crc<uint32_t, 0x04C11DB7u, 0xffffffffu, 0xffffffffu, true, true> ;
|
||||
|
||||
/// AUTOSAR_P4 polynomial 0xF4ACFB13, initial = 0xFFFFFFFF, final_xor = 0xFFFFFFFF, reflect_input = true, reflect_output = true
|
||||
using crcAUTOSAR_P4 = sdv::crc<uint32_t, 0xF4ACFB13u, 0xffffffffu, 0xffffffffu, true, true> ;
|
||||
|
||||
/// CRC32-C Castagnoli polynomial 0x1EDC6F41, initial = 0xFFFFFFFF, final_xor = 0xFFFFFFFF, reflect_input = true,
|
||||
/// reflect_output = true
|
||||
using crcCRC32C = sdv::crc<uint32_t, 0x1EDC6F41, 0xffffffffu, 0xffffffffu, true, true> ;
|
||||
|
||||
/// ECMA (polynomial 0x42F0E1EBA9EA3693, initial = 0xFFFFFFFFFFFFFFFF, final_xor = 0xFFFFFFFFFFFFFFFF, reflect_input = true,
|
||||
/// reflect_output = true
|
||||
using crcECMA = sdv::crc<uint64_t, 0x42F0E1EBA9EA3693, 0xffffffffffffffffu, 0xffffffffffffffffu, true, true>;
|
||||
|
||||
template <typename TCRC, TCRC tPolynomial, TCRC tInitVal, TCRC tXorOut, bool bReflectIn, bool bReflectOut>
|
||||
template <typename T>
|
||||
typename crc<TCRC, tPolynomial, tInitVal, tXorOut, bReflectIn, bReflectOut>::TCRCType
|
||||
crc<TCRC, tPolynomial, tInitVal, tXorOut, bReflectIn, bReflectOut>::calc_checksum(const T* pData, size_t nCount) noexcept
|
||||
{
|
||||
if (!pData || !nCount) return get_checksum();
|
||||
for (size_t nIndex = 0; nIndex < nCount; nIndex++)
|
||||
add(pData[nIndex]);
|
||||
return get_checksum();
|
||||
}
|
||||
|
||||
template <typename TCRC, TCRC tPolynomial, TCRC tInitVal, TCRC tXorOut, bool bReflectIn, bool bReflectOut>
|
||||
template <typename T>
|
||||
inline void crc<TCRC, tPolynomial, tInitVal, tXorOut, bReflectIn, bReflectOut>::add(T tValue) noexcept
|
||||
{
|
||||
if constexpr (bReflectIn)
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < sizeof(T); ++nIndex)
|
||||
{
|
||||
uint8_t data = static_cast<uint8_t>(reflect(reinterpret_cast<uint8_t*>(&tValue)[nIndex]) ^ (m_tCrcValue >> (m_nWidth - 8)));
|
||||
m_tCrcValue = m_arrTable[data] ^ (m_tCrcValue << 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < sizeof(T); ++nIndex)
|
||||
{
|
||||
uint8_t data = static_cast<uint8_t>((reinterpret_cast<uint8_t*>(&tValue)[nIndex]) ^ (m_tCrcValue >> (m_nWidth - 8)));
|
||||
m_tCrcValue = m_arrTable[data] ^ (m_tCrcValue << 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TCRC, TCRC tPolynomial, TCRC tInitVal, TCRC tXorOut, bool bReflectIn, bool bReflectOut>
|
||||
inline typename crc<TCRC, tPolynomial, tInitVal, tXorOut, bReflectIn, bReflectOut>::TCRCType
|
||||
crc<TCRC, tPolynomial, tInitVal, tXorOut, bReflectIn, bReflectOut>::get_checksum() const noexcept
|
||||
{
|
||||
if constexpr (bReflectOut)
|
||||
return static_cast<TCRCType>(reflect(m_tCrcValue) ^ tXorOut);
|
||||
else
|
||||
return static_cast<TCRCType>(m_tCrcValue ^ tXorOut);
|
||||
}
|
||||
|
||||
template <typename TCRC, TCRC tPolynomial, TCRC tInitVal, TCRC tXorOut, bool bReflectIn, bool bReflectOut>
|
||||
inline void crc<TCRC, tPolynomial, tInitVal, tXorOut, bReflectIn, bReflectOut>::set_checksum(TCRCType tCrcValue) noexcept
|
||||
{
|
||||
if constexpr (bReflectOut)
|
||||
m_tCrcValue = static_cast<TCRCType>(reflect(static_cast<TCRCType>(tCrcValue ^ tXorOut)));
|
||||
else
|
||||
m_tCrcValue = static_cast<TCRCType>(tCrcValue ^ tXorOut);
|
||||
}
|
||||
|
||||
template <typename TCRC, TCRC tPolynomial, TCRC tInitVal, TCRC tXorOut, bool bReflectIn, bool bReflectOut>
|
||||
inline void crc<TCRC, tPolynomial, tInitVal, tXorOut, bReflectIn, bReflectOut>::reset() noexcept
|
||||
{
|
||||
m_tCrcValue = tInitVal;
|
||||
}
|
||||
|
||||
} // namespace sdv
|
||||
|
||||
#endif // SDV_CRC_H
|
||||
31
export/support/except.h
Normal file
31
export/support/except.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef SDV_EXCEPT_H
|
||||
#define SDV_EXCEPT_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef except
|
||||
/** Define the except keyword */
|
||||
#define except struct
|
||||
#endif
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief exception ID type
|
||||
*/
|
||||
using exception_id = uint64_t;
|
||||
|
||||
/**
|
||||
* @brief Get the exception ID.
|
||||
* @tparam TException The exception type
|
||||
* @return The ID of the exception
|
||||
*/
|
||||
template <typename TExcept>
|
||||
constexpr inline exception_id GetExceptionId() noexcept
|
||||
{
|
||||
// Return the exception ID.
|
||||
return TExcept::_id;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined SDV_EXCEPT_H
|
||||
279
export/support/interface.h
Normal file
279
export/support/interface.h
Normal file
@@ -0,0 +1,279 @@
|
||||
#ifndef SDV_INTERFACE_H
|
||||
#define SDV_INTERFACE_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef interface
|
||||
/** Define the interface keyword */
|
||||
#define interface struct
|
||||
#endif
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief Interface ID type
|
||||
*/
|
||||
using interface_id = uint64_t;
|
||||
|
||||
/**
|
||||
* @brief Get the interface ID.
|
||||
* @tparam TIfc The interface type
|
||||
* @return The ID of the interface
|
||||
*/
|
||||
template <typename TIfc>
|
||||
constexpr inline interface_id GetInterfaceId() noexcept
|
||||
{
|
||||
// Return the interface ID.
|
||||
return TIfc::_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Interface type class
|
||||
*/
|
||||
class interface_t
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
interface_t() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] rifc Reference to the interface to copy the pointer from.
|
||||
*/
|
||||
interface_t(const interface_t& rifc) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
* @param[in] rifc Reference to the interface to move the pointer from.
|
||||
*/
|
||||
interface_t(interface_t&& rifc) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Null-pointer constructor
|
||||
*/
|
||||
interface_t(std::nullptr_t) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Assignment constructor
|
||||
* @tparam TInterface Interface type
|
||||
* @param[in] pInterface Interface pointer
|
||||
*/
|
||||
template <typename TInterface>
|
||||
interface_t(TInterface* pInterface) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment
|
||||
* @param[in] rifc Reference to the interface to copy the pointer from.
|
||||
* @return Reference to this interface type.
|
||||
*/
|
||||
interface_t& operator=(const interface_t& rifc) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Move assignment
|
||||
* @param[in] rifc Reference to the interface to move the pointer from.
|
||||
* @return Reference to this interface type.
|
||||
*/
|
||||
interface_t& operator=(interface_t&& rifc) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Null-pointer assignment
|
||||
* @return Reference to this interface type.
|
||||
*/
|
||||
interface_t& operator=(std::nullptr_t) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Interface assignment operator
|
||||
* @tparam TInterface Interface type
|
||||
* @param[in] pInterface Interface pointer
|
||||
* @return Reference to this interface type.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
interface_t& operator=(TInterface* pInterface) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Boolean cast operator. Returns whether an interface (!= nullptr) has been assigned.
|
||||
* @return Returns 'true' when assigned; 'false' when not.
|
||||
*/
|
||||
operator bool() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Reset the interface pointer.
|
||||
*/
|
||||
void reset() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get the interface ID.
|
||||
* @return The ID of the stored interface.
|
||||
*/
|
||||
interface_id id() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the stored interface.
|
||||
* @tparam TInterface The interface to get the pointer for.
|
||||
* @return Returns the stored interface pointer if the ID of the requested interface corresponds to the stored interface.
|
||||
* Returns a NULL-pointer if not.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
TInterface* get() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the stored interface.
|
||||
* @tparam TInterface The interface to get the pointer for.
|
||||
* @return Returns the stored interface pointer if the ID of the requested interface corresponds to the stored interface.
|
||||
* Returns a NULL-pointer if not.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
const TInterface* get() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare the interface with another interface.
|
||||
* @param[in] rifc Reference to the interface to compare with.
|
||||
* @return Returns negative when the stored interface is smaller, 0 when the interfaces are equal and positive when the
|
||||
* stored interface is larger.
|
||||
*/
|
||||
int compare(const interface_t& rifc) const noexcept;
|
||||
|
||||
private:
|
||||
interface_id m_id = 0ull; ///< The interface ID of the stored interface.
|
||||
void* m_pInterface = nullptr; ///< Interface pointer.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Compare two interfaces for equality.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether both interfaces are equal.
|
||||
*/
|
||||
bool operator==(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare the interface for equality to NULL-pointer.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @return Returns whether the interface is a NULL-pointer.
|
||||
*/
|
||||
bool operator==(const interface_t& rifcLeft, std::nullptr_t) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare the interface for equality to NULL-pointer.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the interface is a NULL-pointer.
|
||||
*/
|
||||
bool operator==(std::nullptr_t, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare two interfaces for in-equality.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether both interfaces are not equal.
|
||||
*/
|
||||
bool operator!=(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare the interfaces for in-equality to NULL-pointer.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @return Returns whether the interface is not a NULL-pointer.
|
||||
*/
|
||||
bool operator!=(const interface_t& rifcLeft, std::nullptr_t) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare the interfaces for in-equality to NULL-pointer.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the interface is not a NULL-pointer.
|
||||
*/
|
||||
bool operator!=(std::nullptr_t, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left interface is smaller than the right interface.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the left interface is smaller.
|
||||
*/
|
||||
bool operator<(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left interface is smaller than a NULL-pointer.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @return Returns whether the left interface is smaller.
|
||||
*/
|
||||
bool operator<(const interface_t& rifcLeft, std::nullptr_t) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether a NULL-pointer is smaller than the right interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the NULL-pointer is smaller.
|
||||
*/
|
||||
bool operator<(std::nullptr_t, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left interface is smaller than or equal to the right interface.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the left interface is smaller or equal.
|
||||
*/
|
||||
bool operator<=(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left interface is smaller than or equal to a NULL-pointer.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @return Returns whether the left interface is smaller.
|
||||
*/
|
||||
bool operator<=(const interface_t& rifcLeft, std::nullptr_t) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether a NULL-pointer is smaller than or equal to the right interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the NULL-pointer is smaller or equal.
|
||||
*/
|
||||
bool operator<=(std::nullptr_t, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left interface is larger than the right interface.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the left interface is larger.
|
||||
*/
|
||||
bool operator>(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left interface is larger than a NULL-pointer.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @return Returns whether the left interface is larger.
|
||||
*/
|
||||
bool operator>(const interface_t& rifcLeft, std::nullptr_t) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether a NULL-pointer is larger than the right interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the NULL-pointer is larger.
|
||||
*/
|
||||
bool operator>(std::nullptr_t, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left interface is larger than or equal to the right interface.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the left interface is larger or equal.
|
||||
*/
|
||||
bool operator>=(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left interface is larger than or equal to a NULL-pointer.
|
||||
* @param[in] rifcLeft Reference to the left interface.
|
||||
* @return Returns whether the left interface is larger or equal.
|
||||
*/
|
||||
bool operator>=(const interface_t& rifcLeft, std::nullptr_t) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether a NULL-pointer is larger than or equal to the right interface.
|
||||
* @param[in] rifcRight Reference to the right interface.
|
||||
* @return Returns whether the NULL-pointer larger or equal.
|
||||
*/
|
||||
bool operator>=(std::nullptr_t, const interface_t& rifcRight) noexcept;
|
||||
|
||||
} // namespace idl
|
||||
|
||||
#include "interface.inl"
|
||||
|
||||
#endif // !defined SDV_INTERFACE_H
|
||||
208
export/support/interface.inl
Normal file
208
export/support/interface.inl
Normal file
@@ -0,0 +1,208 @@
|
||||
#ifndef SDV_INTERFACE_INL
|
||||
#define SDV_INTERFACE_INL
|
||||
|
||||
#ifndef SDV_INTERFACE_H
|
||||
#error Do not include "interface.inl" directly. Include "interface.h" instead!
|
||||
#endif //!defined SDV_INTERFACE_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
inline interface_t::interface_t() noexcept
|
||||
{
|
||||
// Ensure the layout is the same on all platforms.
|
||||
static_assert(offsetof(interface_t, m_id) == 0);
|
||||
static_assert(offsetof(interface_t, m_pInterface) == 8);
|
||||
static_assert(sizeof(interface_t) == 16);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
inline interface_t::interface_t(const interface_t& rifc) noexcept :
|
||||
m_id(rifc.m_id), m_pInterface(rifc.m_pInterface)
|
||||
{}
|
||||
|
||||
inline interface_t::interface_t(interface_t&& rifc) noexcept :
|
||||
m_id(rifc.m_id), m_pInterface(rifc.m_pInterface)
|
||||
{
|
||||
rifc.reset();
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
inline interface_t::interface_t(std::nullptr_t) noexcept
|
||||
{}
|
||||
|
||||
template <typename TInterface>
|
||||
inline interface_t::interface_t(TInterface* pInterface) noexcept :
|
||||
m_id(GetInterfaceId<TInterface>()), m_pInterface(pInterface)
|
||||
{}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
inline interface_t& interface_t::operator=(const interface_t& rifc) noexcept
|
||||
{
|
||||
m_id = rifc.m_id;
|
||||
m_pInterface = rifc.m_pInterface;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline interface_t& interface_t::operator=(interface_t&& rifc) noexcept
|
||||
{
|
||||
m_id = rifc.m_id;
|
||||
m_pInterface = rifc.m_pInterface;
|
||||
rifc.reset();
|
||||
return *this;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
inline interface_t& interface_t::operator=(std::nullptr_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline interface_t& interface_t::operator=(TInterface* pInterface) noexcept
|
||||
{
|
||||
m_id = GetInterfaceId<TInterface>();
|
||||
m_pInterface = pInterface;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline interface_t::operator bool() const noexcept
|
||||
{
|
||||
return m_pInterface ? true : false;
|
||||
}
|
||||
|
||||
inline void interface_t::reset() noexcept
|
||||
{
|
||||
m_id = 0ull;
|
||||
m_pInterface = nullptr;
|
||||
}
|
||||
|
||||
inline interface_id interface_t::id() const noexcept
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline TInterface* interface_t::get() noexcept
|
||||
{
|
||||
return GetInterfaceId<TInterface>() == m_id ? reinterpret_cast<TInterface*>(m_pInterface) : nullptr;
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline const TInterface* interface_t::get() const noexcept
|
||||
{
|
||||
return GetInterfaceId<TInterface>() == m_id ? reinterpret_cast<const TInterface*>(m_pInterface) : nullptr;
|
||||
}
|
||||
|
||||
inline int interface_t::compare(const interface_t& rifc) const noexcept
|
||||
{
|
||||
if (m_id < rifc.m_id) return -1;
|
||||
if (m_id > rifc.m_id) return 1;
|
||||
if (m_pInterface < rifc.m_pInterface) return -1;
|
||||
if (m_pInterface > rifc.m_pInterface) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool operator==(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return rifcLeft.compare(rifcRight) == 0;
|
||||
}
|
||||
|
||||
inline bool operator==(const interface_t& rifcLeft, std::nullptr_t) noexcept
|
||||
{
|
||||
return !rifcLeft;
|
||||
}
|
||||
|
||||
inline bool operator==(std::nullptr_t, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return !rifcRight;
|
||||
}
|
||||
|
||||
inline bool operator!=(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return rifcLeft.compare(rifcRight) != 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const interface_t& rifcLeft, std::nullptr_t) noexcept
|
||||
{
|
||||
return static_cast<bool>(rifcLeft);
|
||||
}
|
||||
|
||||
inline bool operator!=(std::nullptr_t, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return static_cast<bool>(rifcRight);
|
||||
}
|
||||
|
||||
inline bool operator<(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return rifcLeft.compare(rifcRight) < 0;
|
||||
}
|
||||
|
||||
inline bool operator<(const interface_t& /*rifcLeft*/, std::nullptr_t) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator<(std::nullptr_t, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return static_cast<bool>(rifcRight);
|
||||
}
|
||||
|
||||
inline bool operator<=(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return rifcLeft.compare(rifcRight) <= 0;
|
||||
}
|
||||
inline bool operator<=(const interface_t& rifcLeft, std::nullptr_t) noexcept
|
||||
{
|
||||
return !rifcLeft;
|
||||
}
|
||||
|
||||
inline bool operator<=(std::nullptr_t, const interface_t& /*rifcRight*/) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator>(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return rifcLeft.compare(rifcRight) > 0;
|
||||
}
|
||||
|
||||
inline bool operator>(const interface_t& rifcLeft, std::nullptr_t) noexcept
|
||||
{
|
||||
return static_cast<bool>(rifcLeft);
|
||||
}
|
||||
|
||||
inline bool operator>(std::nullptr_t, const interface_t& /*rifcRight*/) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator>=(const interface_t& rifcLeft, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return rifcLeft.compare(rifcRight) >= 0;
|
||||
}
|
||||
|
||||
inline bool operator>=(const interface_t& /*rifcLeft*/, std::nullptr_t) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator>=(std::nullptr_t, const interface_t& rifcRight) noexcept
|
||||
{
|
||||
return !rifcRight;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined SDV_INTERFACE_INL
|
||||
835
export/support/interface_ptr.h
Normal file
835
export/support/interface_ptr.h
Normal file
@@ -0,0 +1,835 @@
|
||||
/**
|
||||
*
|
||||
* @file interface_ptr.h
|
||||
* @brief This file provides all necessary definitions to use and implement interface maps.
|
||||
* @version 0.1
|
||||
* @date 2022.11.14
|
||||
* @author Thomas.pfleiderer@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2022
|
||||
*
|
||||
*/
|
||||
#ifndef INTERFACE_IMPL_H
|
||||
#define INTERFACE_IMPL_H
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo> // AXIVION Same Line AutosarC++19_03-A16.2.2
|
||||
|
||||
#ifndef DONT_LOAD_CORE_TYPES
|
||||
#include "../interfaces/core.h"
|
||||
#endif
|
||||
|
||||
// NOLINTBEGIN(cppcoreguidelines-macro-usage)
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief Internal namespace
|
||||
*/
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* @brief Helper struct for section selection during interface map processing.
|
||||
*/
|
||||
class CSectionSelector
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Any processing of interfaces after this the call to this function belongs to the default section.
|
||||
*/
|
||||
void DefineDefaultSection()
|
||||
{
|
||||
m_uiSection = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Any processing of interfaces after the call of this function, belongs to the section with the provided
|
||||
* section number.
|
||||
* @param[in] uiSection The section number the interface table entries belong to.
|
||||
*/
|
||||
void DefineSection(int uiSection)
|
||||
{
|
||||
m_uiSection = uiSection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the section that is supported now.
|
||||
*/
|
||||
void Select(int uiSection)
|
||||
{
|
||||
m_uiUseSection = uiSection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Is the current section selected.
|
||||
* @return Returns whether the section is currently within the selection.
|
||||
*/
|
||||
bool Selected() const
|
||||
{
|
||||
return m_uiSection < 0 || m_uiSection == m_uiUseSection;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_uiUseSection = -1; ///< The number of the section to process the interface table entries for.
|
||||
int m_uiSection = -1; ///< The number of the section the interface table entries belong to.
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Interface map containing the supported interface definitions.
|
||||
* @pre The class using the interface map should derive from IInterfaceAccess.
|
||||
*/
|
||||
#define BEGIN_SDV_INTERFACE_MAP() \
|
||||
/** \
|
||||
* @brief Gets the requested interface \
|
||||
* @param[in] idInterface The id representing the requested interface \
|
||||
* @return Returns the IInterfaceAccess pointer to this if the requested interface is found, nullptr otherwise \
|
||||
*/ \
|
||||
sdv::interface_t GetInterface(sdv::interface_id idInterface) override \
|
||||
{ \
|
||||
if (!idInterface) return nullptr; \
|
||||
::sdv::internal::CSectionSelector selector; \
|
||||
if (selector.Selected()) \
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Using a namespace in the interface map.
|
||||
*/
|
||||
#define SDV_INTERFACE_USE_NAMESPACE(namespace_name) using namespace namespace_name;
|
||||
|
||||
/**
|
||||
* @brief Interface entry containing the interface this class is derived from.
|
||||
* @param ifc The interface to return.
|
||||
*/
|
||||
#define SDV_INTERFACE_ENTRY(ifc) \
|
||||
if (idInterface == sdv::GetInterfaceId<ifc>()) \
|
||||
return static_cast<ifc*>(this);
|
||||
|
||||
/**
|
||||
* @brief Interface entry containing the interface a member class is derived from.
|
||||
* @param ifc The interface to return. The member must derive from this interface.
|
||||
* @param member_or_pointer The interface of the member to return.
|
||||
*/
|
||||
#define SDV_INTERFACE_ENTRY_MEMBER(ifc, member_or_pointer) \
|
||||
{ \
|
||||
sdv::interface_t tifc = sdv::SInterfaceMemberHelper<ifc>::InterfaceMapEntryHelper(member_or_pointer, idInterface); \
|
||||
if (tifc) \
|
||||
return tifc; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Interface entry containing the interface this class is derived from. The indirect implementation solves
|
||||
* ambiguous casts when the class is derived from the same interface more than once.
|
||||
* @param ifc The interface to return.
|
||||
* @param ifc_cast The interface to use for casting before casting to the interface. This is usually one of the
|
||||
* interfaces/classes derived from the interface
|
||||
*/
|
||||
#define SDV_INTERFACE_ENTRY_INDIRECT(ifc, ifc_cast) \
|
||||
if (idInterface == sdv::GetInterfaceId<ifc>()) \
|
||||
return static_cast<ifc*>(static_cast<ifc_cast*>(this));
|
||||
|
||||
/**
|
||||
* @brief Interface entry containing the interface this class is definitely not supporting (used to overload an entry
|
||||
* in an interface map in a base class).
|
||||
* @attention When the interface map was chained, this will end the current processing for the chained map, but the
|
||||
* calling map will still continue the processing.
|
||||
* @param ifc The interface to deny.
|
||||
*/
|
||||
#define SDV_INTERFACE_DENY_ENTRY(ifc) \
|
||||
if (idInterface == sdv::GetInterfaceId<ifc>()) \
|
||||
return nullptr;
|
||||
|
||||
/**
|
||||
* @brief Chain the interface map of a base class.
|
||||
* @param base_class The class implementing the GetInterface function.
|
||||
*/
|
||||
#define SDV_INTERFACE_CHAIN_BASE(base_class) \
|
||||
{ \
|
||||
sdv::interface_t ifc = base_class::GetInterface(idInterface); \
|
||||
if (ifc) \
|
||||
return ifc; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Chain the interface map of a member as reference or as pointer.
|
||||
* @param member_or_pointer The member implementing the GetInterface function.
|
||||
*/
|
||||
#define SDV_INTERFACE_CHAIN_MEMBER(member_or_pointer) \
|
||||
{ \
|
||||
sdv::interface_t ifc = sdv::InterfaceMapChainHelper(member_or_pointer, idInterface); \
|
||||
if (ifc) \
|
||||
return ifc; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conditional check; when true continue the checking for interfaces.
|
||||
* @param condition The condition to be checked. When 'false' processing will be stopped; otherwise processing
|
||||
* continues. Example: @code SDV_INTERFACE_CHECK_CONDITION(CheckFunc()) @endcode
|
||||
*/
|
||||
#define SDV_INTERFACE_CHECK_CONDITION(condition) \
|
||||
if (!(condition)) \
|
||||
return nullptr;
|
||||
|
||||
/**
|
||||
* @brief Use the condition, to select a section to process.
|
||||
* @param condition Condition to be checked. When 'true' processing will be limited to the section.
|
||||
* Example: @code SDV_INTERFACE_PROCESS_SECTION(CheckFunc(), 1) @endcode
|
||||
* @param section_number The section to be processed when the condition is true.
|
||||
*/
|
||||
#define SDV_INTERFACE_SET_SECTION_CONDITION(condition, section_number) \
|
||||
if (condition) \
|
||||
selector.Select(section_number); \
|
||||
} \
|
||||
if (selector.Selected()) \
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Set section to process.
|
||||
* @param section_number The section to process.
|
||||
*/
|
||||
#define SDV_INTERFACE_SET_SECTION(section_number) \
|
||||
selector.Select(section_number); \
|
||||
} \
|
||||
if (selector.Selected()) \
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @brief Define that the interface map entries following this statement are to be processed regardless of the section
|
||||
* selection.
|
||||
*/
|
||||
#define SDV_INTERFACE_DEFAULT_SECTION() \
|
||||
} \
|
||||
selector.DefineDefaultSection(); \
|
||||
if (selector.Selected()) \
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Define that the interface map entries following this statement belong to a dedicated section and should only
|
||||
* be processed when that section is selected.
|
||||
* @param section_number Begin of a section with the section number.
|
||||
*/
|
||||
#define SDV_INTERFACE_SECTION(section_number) \
|
||||
} \
|
||||
selector.DefineSection(section_number); \
|
||||
if (selector.Selected()) \
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @brief End of interface map.
|
||||
*/
|
||||
#define END_SDV_INTERFACE_MAP() \
|
||||
} \
|
||||
return nullptr; /* None found */ \
|
||||
}
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-macro-usage)
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief Interface access wrapper class.
|
||||
* @tparam IInterfaceAccess Interface type to wrap
|
||||
*/
|
||||
class CInterfacePtr
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new CInterfacePtr object.
|
||||
* @param[in] pInterface Pointer to the interface to wrap or nullptr when no interface is to be wrapped yet.
|
||||
*/
|
||||
CInterfacePtr(IInterfaceAccess* pInterface = nullptr) : m_pInterface(pInterface)
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Copy construct a new CInterfacePtr object
|
||||
* @param[in] rptrInterface Reference to the CInterfacePtr object to copy from.
|
||||
*/
|
||||
CInterfacePtr(const CInterfacePtr& rptrInterface) : m_pInterface(rptrInterface.m_pInterface.load())
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Move construct a new CInterfacePtr object
|
||||
* @param[in] rptrInterface Reference to the CInterfacePtr object to move from.
|
||||
*/
|
||||
CInterfacePtr(CInterfacePtr&& rptrInterface) noexcept
|
||||
{
|
||||
IInterfaceAccess* pInterface = rptrInterface.m_pInterface.load();
|
||||
rptrInterface.m_pInterface = nullptr;
|
||||
m_pInterface = pInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Default destructor.
|
||||
*/
|
||||
virtual ~CInterfacePtr() = default;
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
* @param[in] pInterface Pointer to the interface to wrap or nullptr to clear the wrapping.
|
||||
* @return Returns *this
|
||||
*/
|
||||
CInterfacePtr& operator=(IInterfaceAccess* pInterface)
|
||||
{
|
||||
m_pInterface = pInterface;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
* @param[in] rptrInterface Reference to the CInterfacePtr object to copy from.
|
||||
* @return Returns *this
|
||||
*/
|
||||
CInterfacePtr& operator=(const CInterfacePtr& rptrInterface)
|
||||
{
|
||||
m_pInterface = rptrInterface.m_pInterface.load();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move operator
|
||||
* @param[in] rptrInterface Reference to the CInterfacePtr object to move from.
|
||||
* @return Returns *this
|
||||
*/
|
||||
CInterfacePtr& operator=(CInterfacePtr&& rptrInterface) noexcept
|
||||
{
|
||||
IInterfaceAccess* pInterface = rptrInterface.m_pInterface.load();
|
||||
rptrInterface.m_pInterface = nullptr;
|
||||
m_pInterface = pInterface;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the interface
|
||||
*/
|
||||
operator IInterfaceAccess*()
|
||||
{
|
||||
return m_pInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the interface
|
||||
*/
|
||||
operator const IInterfaceAccess*() const
|
||||
{
|
||||
return m_pInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Is there a valid interface?
|
||||
* @return Returns 'true' when an interface is wrapped; 'false' otherwise.
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return static_cast<bool>(m_pInterface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return whether there is a valid interface.
|
||||
* @return Returns 'true' when an interface is wrapped; 'false' otherwise.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return static_cast<bool>(m_pInterface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets an interface by using the IInterfaceAccess::GetInterface function.
|
||||
* @tparam TIfc The interface type to request.
|
||||
* @return Returns a pointer to the requested interface if the object has itregistered, nullptr otherwise
|
||||
*/
|
||||
template <typename TIfc>
|
||||
TIfc* GetInterface() const
|
||||
{
|
||||
return m_pInterface ? m_pInterface.load()->GetInterface(GetInterfaceId<TIfc>()).template get<TIfc>() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Contained pointer to the interface.
|
||||
*/
|
||||
std::atomic<IInterfaceAccess*> m_pInterface{nullptr};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specialization for sdv::IInterfaceAccess interface.
|
||||
* @tparam TIfc The interface type to request.
|
||||
* @return Returns a pointer to the requested interface if the object has itregistered, nullptr otherwise
|
||||
*/
|
||||
template <>
|
||||
inline IInterfaceAccess* CInterfacePtr::GetInterface<IInterfaceAccess>() const
|
||||
{
|
||||
return m_pInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IInterfaceAccess smart pointer.
|
||||
*/
|
||||
using TInterfaceAccessPtr = CInterfacePtr;
|
||||
|
||||
/**
|
||||
* @brief Helper function for interface chaining using a member variable.
|
||||
* @tparam TMember Type of the member variable.
|
||||
* @param[in] rtMember Reference to the member to chain to.
|
||||
* @param[in] idInterface ID of the interface to request.
|
||||
* @return Pointer to the interface.
|
||||
*/
|
||||
template <typename TMember>
|
||||
inline sdv::interface_t InterfaceMapChainHelper(TMember& rtMember, interface_id idInterface)
|
||||
{
|
||||
return rtMember.GetInterface(idInterface);
|
||||
}
|
||||
|
||||
// Warning of cppchgeck for a potential const variable cannot be applied due to the non-const nature of interfaces. Suppress
|
||||
// warning.
|
||||
// cppcheck-suppress constParameterReference
|
||||
/**
|
||||
* @brief Helper function for interface chaining using a member variable.
|
||||
* @tparam IInterfaceAccess Type of the interface wrapped by the member variable.
|
||||
* @param[in] rptrMember Reference to the interface wrapper class to chain to.
|
||||
* @param[in] idInterface ID of the interface to request.
|
||||
* @return Pointer to the interface.
|
||||
*/
|
||||
inline sdv::interface_t InterfaceMapChainHelper(CInterfacePtr& rptrMember, interface_id idInterface)
|
||||
{
|
||||
return rptrMember ? static_cast<IInterfaceAccess*>(rptrMember)->GetInterface(idInterface) : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function for interface chaining using a member variable.
|
||||
* @tparam TMember Type of the member variable.
|
||||
* @param[in] ptMember Pointer to the member to chain to.
|
||||
* @param[in] idInterface ID of the interface.
|
||||
* @return Pointer to the interface.
|
||||
*/
|
||||
template <typename TMember>
|
||||
inline sdv::interface_t InterfaceMapChainHelper(TMember* ptMember, interface_id idInterface)
|
||||
{
|
||||
return ptMember ? ptMember->GetInterface(idInterface) : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function for interface chaining using a member variable.
|
||||
* @tparam TMember Type of the member variable.
|
||||
* @param[in] rptrMember Reference to the shared pointer to the member to chain to.
|
||||
* @param[in] idInterface ID of the interface.
|
||||
* @return Pointer to the interface.
|
||||
*/
|
||||
template <typename TMember>
|
||||
inline sdv::interface_t InterfaceMapChainHelper(std::shared_ptr<TMember>& rptrMember, interface_id idInterface)
|
||||
{
|
||||
return rptrMember ? rptrMember->GetInterface(idInterface) : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function for interface chaining using a member variable.
|
||||
* @tparam TMember Type of the member variable.
|
||||
* @param[in] rweakMember Reference to the weak pointer to the member to chain to.
|
||||
* @param[in] idInterface ID of the interface.
|
||||
* @return Pointer to the interface.
|
||||
*/
|
||||
template <typename TMember>
|
||||
inline sdv::interface_t InterfaceMapChainHelper(std::weak_ptr<TMember>& rweakMember, interface_id idInterface)
|
||||
{
|
||||
std::shared_ptr<TMember> ptrMember = rweakMember.lock();
|
||||
return InterfaceMapChainHelper(ptrMember, idInterface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Interface member helper class.
|
||||
* @tparam TInterface The interface the member is to implement.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
struct SInterfaceMemberHelper
|
||||
{
|
||||
/**
|
||||
* @brief Helper function for interface entries in the interface map.
|
||||
* @tparam TMember Type of the member variable.
|
||||
* @param[in] rtMember Reference to the member implementing the interface.
|
||||
* @param[in] idInterface ID of the interface.
|
||||
* @return Pointer to the interface.
|
||||
*/
|
||||
template <typename TMember>
|
||||
static sdv::interface_t InterfaceMapEntryHelper(TMember& rtMember, interface_id idInterface)
|
||||
{
|
||||
static_assert(std::is_same_v<TInterface, TMember> || std::is_base_of_v<TInterface, TMember>);
|
||||
if (sdv::GetInterfaceId<TInterface>() == idInterface)
|
||||
{
|
||||
return static_cast<TInterface*>(&rtMember);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function for interface entries in the interface map.
|
||||
* @tparam TMember Type of the member variable.
|
||||
* @param[in] ptMember Pointer to the member implementing the interface.
|
||||
* @param[in] idInterface ID of the interface.
|
||||
* @return Pointer to the interface.
|
||||
*/
|
||||
template <typename TMember>
|
||||
static sdv::interface_t InterfaceMapEntryHelper(TMember* ptMember, interface_id idInterface)
|
||||
{
|
||||
static_assert(std::is_same_v<TInterface, TMember> || std::is_base_of_v<TInterface, TMember>);
|
||||
if (sdv::GetInterfaceId<TInterface>() == idInterface)
|
||||
{
|
||||
return static_cast<TInterface*>(ptMember);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function for interface entries in the interface map.
|
||||
* @tparam TMember Type of the member variable.
|
||||
* @param[in] rptrMember Reference to the shared pointer to the member implementing the interface.
|
||||
* @param[in] idInterface ID of the interface.
|
||||
* @return Pointer to the interface.
|
||||
*/
|
||||
template <typename TMember>
|
||||
static sdv::interface_t InterfaceMapEntryHelper(std::shared_ptr<TMember>& rptrMember, interface_id idInterface)
|
||||
{
|
||||
static_assert(std::is_same_v<TInterface, TMember> || std::is_base_of_v<TInterface, TMember>);
|
||||
if (sdv::GetInterfaceId<TInterface>() == idInterface)
|
||||
{
|
||||
return static_cast<TInterface*>(rptrMember.get());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function for interface entries in the interface map.
|
||||
* @tparam TMember Type of the member variable.
|
||||
* @param[in] rweakMember Reference to the weak pointer to the member implementing the interface.
|
||||
* @param[in] idInterface ID of the interface.
|
||||
* @return Pointer to the interface.
|
||||
*/
|
||||
template <typename TMember>
|
||||
static sdv::interface_t InterfaceMapEntryHelper(std::weak_ptr<TMember>& rweakMember, interface_id idInterface)
|
||||
{
|
||||
static_assert(std::is_same_v<TInterface, TMember> || std::is_base_of_v<TInterface, TMember>);
|
||||
std::shared_ptr<TMember> ptrMember = rweakMember.lock();
|
||||
return InterfaceMapEntryHelper<TMember>(ptrMember, idInterface);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper class to implement the IObjectLifetime interface for objects not supporting this.
|
||||
*/
|
||||
class CObjectLifetimeWrapper : public IInterfaceAccess, public IObjectLifetime, public IObjectDestroy
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CObjectLifetimeWrapper() = default;
|
||||
|
||||
/**
|
||||
* @brief Destructor automatically destroying the object.
|
||||
*/
|
||||
~CObjectLifetimeWrapper()
|
||||
{}
|
||||
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(IObjectLifetime)
|
||||
SDV_INTERFACE_ENTRY(IObjectDestroy)
|
||||
SDV_INTERFACE_CHAIN_MEMBER(m_pObject)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief Create a object lifetime wrapper object.
|
||||
* @details Create an object lifetime wrapper object and assign the provided interface to the wrapper. The wrapper object
|
||||
* blocks calls to IObjectDestroy since it will take ober the management of object lifetime.
|
||||
* @param[in] pObject Interface of the object to wrap. This object needs to expose IObjectDestroy and could expose
|
||||
* IObjectLifetime.
|
||||
* @return Returns an interface giving access to a IObjectLifetime interface, forwarding all other interface calls.
|
||||
*/
|
||||
static IInterfaceAccess* CreateWrapper(IInterfaceAccess* pObject)
|
||||
{
|
||||
if (!pObject) return nullptr; // Nothing to manage
|
||||
std::unique_ptr<CObjectLifetimeWrapper> ptrWrapper = std::make_unique<CObjectLifetimeWrapper>();
|
||||
// Ignore cppcheck warning; normally the returned pointer should always have a value at this stage (otherwise an
|
||||
// exception was triggered).
|
||||
// cppcheck-suppress knownConditionTrueFalse
|
||||
if (!ptrWrapper)
|
||||
return nullptr;
|
||||
ptrWrapper->Increment();
|
||||
ptrWrapper->m_pObject = pObject;
|
||||
|
||||
// Store the pointer internally - this will keep the pointer alive, but invalidates ptrWrapper.
|
||||
std::unique_ptr<CObjectLifetimeWrapper>& rptrKeepAlive = ptrWrapper->m_ptrKeepAlive;
|
||||
rptrKeepAlive = std::move(ptrWrapper);
|
||||
|
||||
// Return the interface pointer
|
||||
return rptrKeepAlive.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increment the lifetime. Needs to be balanced by a call to Decrement. Overload of IObjectLifetime::Increment.
|
||||
*/
|
||||
virtual void Increment() override
|
||||
{
|
||||
m_iCounter++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decrement the lifetime. If the lifetime reaches zero, the object will be destroyed (through the exposed
|
||||
* IObjectDestroy interface). Overload of IObjectLifetime::Decrement.
|
||||
* @return Returns 'true' if the object was destroyed, false if not.
|
||||
*/
|
||||
virtual bool Decrement() override
|
||||
{
|
||||
if (!m_iCounter) return false;
|
||||
m_iCounter--;
|
||||
if (!m_iCounter)
|
||||
{
|
||||
IObjectDestroy* pObjectDestroy = CInterfacePtr(m_pObject).GetInterface<IObjectDestroy>();
|
||||
if (pObjectDestroy) pObjectDestroy->DestroyObject();
|
||||
m_pObject = nullptr;
|
||||
m_ptrKeepAlive.reset();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current lifetime count. Overload of IObjectLifetime::GetCount.
|
||||
* @remarks The GetCount function returns a momentary value, which can be changed at any moment.
|
||||
* @return Returns the current counter value.
|
||||
*/
|
||||
virtual uint32_t GetCount() const override
|
||||
{
|
||||
return static_cast<uint32_t>(m_iCounter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the object. Overload of IObjectDestroy::DestroyObject.
|
||||
* @attention After a call of this function, all exposed interfaces render invalid and should not be used any more.
|
||||
*/
|
||||
virtual void DestroyObject() override
|
||||
{
|
||||
// Destroy object is only allowed when the counter is 1.
|
||||
if (static_cast<int32_t>(m_iCounter) != 1)
|
||||
std::cerr << "Trying to destroy an object having references." << std::endl;
|
||||
if (static_cast<int32_t>(m_iCounter) > 0)
|
||||
Decrement();
|
||||
}
|
||||
|
||||
IInterfaceAccess* m_pObject = nullptr; ///< The interface pointer.
|
||||
std::atomic<int32_t> m_iCounter = 0; ///< The lifetime counter.
|
||||
std::unique_ptr<CObjectLifetimeWrapper> m_ptrKeepAlive; ///< The one instance of this wrapper class.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Object smart pointer. Implements destruction of the object.
|
||||
*/
|
||||
class CObjectPtr
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new CObjectPtr object.
|
||||
* @param[in] pInterface Pointer to the interface to wrap or nullptr when no interface is to be wrapped yet.
|
||||
*/
|
||||
CObjectPtr(IInterfaceAccess* pInterface = nullptr)
|
||||
{
|
||||
Assign(pInterface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy construct a new CInterfacePtr object
|
||||
* @param[in] rptrInterface Reference to the CInterfacePtr object to copy from.
|
||||
*/
|
||||
CObjectPtr(const CObjectPtr& rptrInterface) : m_ptrObject(rptrInterface.m_ptrObject)
|
||||
{
|
||||
IObjectLifetime* pObjectLifetime = GetInterface<IObjectLifetime>();
|
||||
if (pObjectLifetime) pObjectLifetime->Increment();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move construct a new CInterfacePtr object
|
||||
* @param[in] rptrInterface Reference to the CInterfacePtr object to move from.
|
||||
*/
|
||||
CObjectPtr(CObjectPtr&& rptrInterface) noexcept : m_ptrObject(std::move(rptrInterface.m_ptrObject))
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~CObjectPtr()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
* @param[in] pInterface Pointer to the interface to wrap or nullptr to clear the wrapping.
|
||||
* @return Returns *this
|
||||
*/
|
||||
CObjectPtr& operator=(IInterfaceAccess* pInterface)
|
||||
{
|
||||
Assign(pInterface);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
* @param[in] rptrInterface Reference to the CInterfacePtr object to copy from.
|
||||
* @return Returns *this
|
||||
*/
|
||||
CObjectPtr& operator=(const CObjectPtr& rptrInterface)
|
||||
{
|
||||
Clear();
|
||||
m_ptrObject = rptrInterface.m_ptrObject;
|
||||
IObjectLifetime* pObjectLifetime = GetInterface<IObjectLifetime>();
|
||||
if (pObjectLifetime) pObjectLifetime->Increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move operator
|
||||
* @param[in] rptrInterface Reference to the CInterfacePtr object to move from.
|
||||
* @return Returns *this
|
||||
*/
|
||||
CObjectPtr& operator=(CObjectPtr&& rptrInterface) noexcept
|
||||
{
|
||||
Attach(rptrInterface.Detach());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the interface
|
||||
*/
|
||||
operator IInterfaceAccess*()
|
||||
{
|
||||
return m_ptrObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the interface
|
||||
*/
|
||||
operator const IInterfaceAccess*() const
|
||||
{
|
||||
return m_ptrObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the interface
|
||||
*/
|
||||
operator CInterfacePtr() const
|
||||
{
|
||||
return m_ptrObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Is there a valid interface?
|
||||
* @return Returns 'true' when an interface is wrapped; 'false' otherwise.
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return whether there is a valid interface.
|
||||
* @return Returns 'true' when an interface is wrapped; 'false' otherwise.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return static_cast<bool>(m_ptrObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets an interface by using the IInterfaceAccess::GetInterface function.
|
||||
* @tparam TIfc The interface type to request.
|
||||
* @return Returns a pointer to the requested interface if the object has itregistered, nullptr otherwise
|
||||
*/
|
||||
template <typename TIfc>
|
||||
TIfc* GetInterface() const
|
||||
{
|
||||
return m_ptrObject.GetInterface<TIfc>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign the object to this object pointer and increment the lifetime counter.
|
||||
* @param[in] pObject Interface pointer to the object.
|
||||
*/
|
||||
void Assign(IInterfaceAccess* pObject)
|
||||
{
|
||||
Clear();
|
||||
if (!pObject) return;
|
||||
|
||||
IObjectLifetime* pLifetime = CInterfacePtr(pObject).GetInterface<IObjectLifetime>();
|
||||
if (pLifetime) // Object provides lifetime management. Use this...
|
||||
{
|
||||
m_ptrObject = pObject;
|
||||
pLifetime->Increment();
|
||||
}
|
||||
else // Create a lifetime management wrapper. Do not increase count... this has already been done during creation
|
||||
m_ptrObject = CObjectLifetimeWrapper::CreateWrapper(pObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the object and clear the interface.
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
IObjectLifetime* pLifetime = m_ptrObject.GetInterface<IObjectLifetime>();
|
||||
if (pLifetime) // Object provides lifetime management. Use this...
|
||||
pLifetime->Decrement();
|
||||
m_ptrObject = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach an object which is managed by lifetime. The lifetime counter is not increased.
|
||||
* @remarks Attachment only succeeds when the object exposes the IObjectLifetime pointer.
|
||||
* @param[in] pObject Pointer to the object.
|
||||
*/
|
||||
void Attach(IInterfaceAccess* pObject)
|
||||
{
|
||||
Clear();
|
||||
if (CInterfacePtr(pObject).GetInterface<IObjectLifetime>())
|
||||
m_ptrObject = pObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Detach the pointer without change the object lifetime. The internal pointer will beeome NULL.
|
||||
* @attention Detaching the pointer means it is not managed any more. A call to IObjectLifetime::Decrement needs to be done
|
||||
* manually.
|
||||
* @return The detached interface pointer.
|
||||
*/
|
||||
CInterfacePtr Detach()
|
||||
{
|
||||
if (!m_ptrObject) return CInterfacePtr();
|
||||
CInterfacePtr ptr = std::move(m_ptrObject);
|
||||
m_ptrObject = nullptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
CInterfacePtr m_ptrObject; ///< The object pointer.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief IObjectAccess smart pointer.
|
||||
*/
|
||||
using TObjectPtr = CObjectPtr;
|
||||
|
||||
} // namespace sdv
|
||||
|
||||
|
||||
#ifndef DONT_LOAD_CORE_TYPES
|
||||
#include "mem_access.h"
|
||||
#endif
|
||||
|
||||
#endif // !defined INTERFACE_IMPL_H
|
||||
355
export/support/iterator.h
Normal file
355
export/support/iterator.h
Normal file
@@ -0,0 +1,355 @@
|
||||
#ifndef SDV_ITERATOR_H
|
||||
#define SDV_ITERATOR_H
|
||||
|
||||
#include <iterator>
|
||||
#ifndef DONT_LOAD_CORE_TYPES
|
||||
#include "../interfaces/core_types.h"
|
||||
#endif
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* @brief Index based iterators used for linear array based containers.
|
||||
* @tparam TContainer Container type to use for this iterator.
|
||||
* @tparam bConstIterator When set, the iterator is a const iterator not allowing to change values within the container.
|
||||
* @tparam bReserseIterator When set, the iterator starts at the end instead of at the beginning and decreases the location.
|
||||
*/
|
||||
template <class TContainer, bool bConstIterator, bool bReverseIterator>
|
||||
class index_iterator
|
||||
{
|
||||
friend index_iterator<TContainer, !bConstIterator, bReverseIterator>;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Container type reference
|
||||
*/
|
||||
using container_reference = std::conditional_t<bConstIterator, const TContainer&, TContainer&>;
|
||||
|
||||
/**
|
||||
* @brief Contaioner type pointer
|
||||
*/
|
||||
using container_pointer = std::conditional_t<bConstIterator, const TContainer*, TContainer*>;
|
||||
|
||||
/**
|
||||
* @brief Iterator category
|
||||
*/
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
|
||||
/**
|
||||
* @brief Value type
|
||||
*/
|
||||
using value_type = typename TContainer::value_type;
|
||||
|
||||
/**
|
||||
* @brief Indexing type
|
||||
*/
|
||||
using difference_type = size_t;
|
||||
|
||||
/**
|
||||
* @brief Value type pointer
|
||||
*/
|
||||
using pointer = std::conditional_t<bConstIterator, const value_type*, value_type*>;
|
||||
|
||||
/**
|
||||
* @brief Value type reference
|
||||
*/
|
||||
using reference = std::conditional_t<bConstIterator, const value_type&, value_type&>;
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
index_iterator() {}
|
||||
|
||||
/**
|
||||
* @brief Iterator initialization
|
||||
* @param[in] pContainer Pointer to the container.
|
||||
*/
|
||||
index_iterator(container_pointer pContainer) : m_pContainer(pContainer)
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] rit Reference to the iterator to copy from.
|
||||
*/
|
||||
index_iterator(const index_iterator& rit) : m_pContainer(rit.m_pContainer), m_nIndex(rit.m_nIndex)
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] rit Reference to the iterator to copy from.
|
||||
*/
|
||||
index_iterator(const index_iterator<TContainer, !bConstIterator, bReverseIterator>& rit) :
|
||||
m_pContainer(const_cast<container_pointer>(rit.m_pContainer)), m_nIndex(rit.m_nIndex)
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
* @param[in] rit Reference to the iterator to move from.
|
||||
*/
|
||||
index_iterator(index_iterator&& rit) noexcept : m_pContainer(rit.m_pContainer), m_nIndex(rit.m_nIndex)
|
||||
{
|
||||
rit.m_pContainer = nullptr;
|
||||
rit.m_nIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
* @param[in] rit Reference to the iterator to copy from.
|
||||
* @return Returns a reference to the iterator.
|
||||
*/
|
||||
index_iterator& operator=(const index_iterator& rit)
|
||||
{
|
||||
m_pContainer = rit.m_pContainer;
|
||||
m_nIndex = rit.m_nIndex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
* @param[in] rit Reference to the iterator to copy from.
|
||||
* @return Returns a reference to the iterator.
|
||||
*/
|
||||
index_iterator& operator=(const index_iterator<TContainer, !bConstIterator, bReverseIterator>& rit)
|
||||
{
|
||||
m_pContainer = rit.m_pContainer;
|
||||
m_nIndex = rit.m_nIndex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move operator
|
||||
* @param[in] rit Reference to the iterator to move from.
|
||||
* @return Returns a reference to the iterator.
|
||||
*/
|
||||
index_iterator& operator=(index_iterator&& rit) noexcept
|
||||
{
|
||||
m_pContainer = rit.m_pContainer;
|
||||
m_nIndex = rit.m_nIndex;
|
||||
rit.m_pContainer = nullptr;
|
||||
rit.m_nIndex = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Does the iterator iterate the same container.
|
||||
* @param[in] rContainer Reference to the container to check whether the iterators are iterating the same container.
|
||||
* @return Returns 'true' when the iterator iterates the same container; otherwise returns 'false'.
|
||||
*/
|
||||
bool is_valid(container_reference rContainer) const
|
||||
{
|
||||
return m_pContainer == &rContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare two iterators for iterating the same container and pointing to the same position.
|
||||
* @param[in] rit Reference to the iterator to use for the comparison.
|
||||
* @return Returns 'true' when the iterators point to the same container and have the same position.
|
||||
*/
|
||||
bool operator==(const index_iterator& rit) const
|
||||
{
|
||||
return m_pContainer == rit.m_pContainer && m_nIndex == rit.m_nIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare two iterators for iterating the same container and pointing to the same position.
|
||||
* @param[in] rit Reference to the iterator to use for the comparison.
|
||||
* @return Returns 'true' when the iterators point to the same container and have the same position.
|
||||
*/
|
||||
bool operator==(const index_iterator<TContainer, !bConstIterator, bReverseIterator>& rit) const
|
||||
{
|
||||
return m_pContainer == rit.m_pContainer && m_nIndex == rit.m_nIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare two iterators for iterating the different containers or pointing to the another position.
|
||||
* @param[in] rit Reference to the iterator to use for the comparison.
|
||||
* @return Returns 'true' when the iterators point to different containers or have different positions.
|
||||
*/
|
||||
bool operator!=(const index_iterator& rit) const
|
||||
{
|
||||
return !(*this == rit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare two iterators for iterating the different containers or pointing to the another position.
|
||||
* @param[in] rit Reference to the iterator to use for the comparison.
|
||||
* @return Returns 'true' when the iterators point to different containers or have different positions.
|
||||
*/
|
||||
bool operator!=(const index_iterator<TContainer, !bConstIterator, bReverseIterator>& rit) const
|
||||
{
|
||||
return !(*this == rit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value from the container at the location the iterator is pointing to.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
reference operator*() const
|
||||
{
|
||||
size_t nIndex = m_nIndex;
|
||||
if (!m_pContainer || m_nIndex >= m_pContainer->size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(nIndex);
|
||||
exception.uiSize = static_cast<uint32_t>(m_pContainer ? m_pContainer->size() : 0);
|
||||
throw exception;
|
||||
}
|
||||
if constexpr (bReverseIterator)
|
||||
nIndex = m_pContainer->size() - m_nIndex - 1;
|
||||
return (*m_pContainer)[nIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pointer operation the value from the container at the location the iterator is pointing to.
|
||||
* @remarks Only valid for container storing pointers.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
pointer operator->() const
|
||||
{
|
||||
return std::pointer_traits<pointer>::pointer_to(**this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increase the iterator with one position. Doesn't go past the one position behind the back.
|
||||
* @return Reference to the iterator.
|
||||
*/
|
||||
index_iterator& operator++()
|
||||
{
|
||||
if (m_pContainer && m_nIndex < m_pContainer->size())
|
||||
m_nIndex++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy the current iterator and increase the copied iterator with one position. Doesn't go past the one
|
||||
* position behind the back.
|
||||
* @return Copied and increased iterator.
|
||||
*/
|
||||
index_iterator operator++(int)
|
||||
{
|
||||
index_iterator itCopy = *this;
|
||||
operator++();
|
||||
return itCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decrease the iterator with one position. Doesn't go before the front position.
|
||||
* @return Reference to the iterator.
|
||||
*/
|
||||
index_iterator& operator--() noexcept
|
||||
{
|
||||
if (m_pContainer && m_nIndex > 0)
|
||||
m_nIndex--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy the current iterator and decrease the copied iterator with one position. Doesn't go before the front
|
||||
* position.
|
||||
* @return Copied and decreased iterator.
|
||||
*/
|
||||
index_iterator operator--(int) noexcept
|
||||
{
|
||||
index_iterator itCopy = *this;
|
||||
operator--();
|
||||
return itCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increase the iterator with nOsset positions. Doesn't go past the one position behind the back.
|
||||
* @param[in] nOffset The amount of positions to increase.
|
||||
* @return Reference to the iterator.
|
||||
*/
|
||||
index_iterator& operator+=(size_t nOffset) noexcept
|
||||
{
|
||||
if (!m_pContainer) return *this;
|
||||
if (nOffset > m_pContainer->size() - m_nIndex)
|
||||
m_nIndex = m_pContainer->size();
|
||||
else
|
||||
m_nIndex += nOffset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy the current iterator and increase the copied iterator with nOffset positions. Doesn't go past the one
|
||||
* position behind the back.
|
||||
* @param[in] nOffset The amount of positions to increase.
|
||||
* @return Copied and increased iterator.
|
||||
*/
|
||||
index_iterator operator+(size_t nOffset) const noexcept
|
||||
{
|
||||
index_iterator itCopy = *this;
|
||||
itCopy += nOffset;
|
||||
return itCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decrease the iterator with nOffset positions. Doesn't go before the front position.
|
||||
* @param[in] nOffset The amount of positions to decrease.
|
||||
* @return Reference to the iterator.
|
||||
*/
|
||||
index_iterator& operator-=(size_t nOffset) noexcept
|
||||
{
|
||||
if (!m_pContainer) return *this;
|
||||
if (m_nIndex > nOffset)
|
||||
m_nIndex -= nOffset;
|
||||
else if (m_nIndex)
|
||||
m_nIndex = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy the current iterator and decrease the copied iterator with nOffset positions. Doesn't go before the
|
||||
* front position.
|
||||
* @param[in] nOffset The amount of positions to increase.
|
||||
* @return Copied and decreased iterator.
|
||||
*/
|
||||
index_iterator operator-(size_t nOffset) const noexcept
|
||||
{
|
||||
index_iterator itCopy = *this;
|
||||
itCopy -= nOffset;
|
||||
return itCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subtract the indices of two iterators of the same type.
|
||||
* @param[in] it The iterator to use for subtraction.
|
||||
* @return The difference between the contained index and the index of the supplied iterator.
|
||||
*/
|
||||
difference_type operator-(index_iterator it) const
|
||||
{
|
||||
if (m_pContainer != it.m_pContainer) return 0;
|
||||
if (m_nIndex > it.m_nIndex)
|
||||
return m_nIndex - it.m_nIndex;
|
||||
else
|
||||
return it.m_nIndex - m_nIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value from the container at the location the iterator is pointing to added with an offset.
|
||||
* @param[in] nOffset The offset to increase the location.
|
||||
* @return Reference to the value at the location increased with an offset.
|
||||
*/
|
||||
reference operator[](size_t nOffset) const
|
||||
{
|
||||
if (!m_pContainer || m_pContainer->empty())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(nOffset + m_nIndex);
|
||||
exception.uiSize = static_cast<uint32_t>(0);
|
||||
throw exception;
|
||||
}
|
||||
return *(operator+(nOffset));
|
||||
}
|
||||
|
||||
private:
|
||||
container_pointer m_pContainer = nullptr; ///< Pointer to the container.
|
||||
size_t m_nIndex = 0; ///< Current index within the container.
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace sdv
|
||||
|
||||
#endif // !defined SDV_ITERATOR_H
|
||||
310
export/support/local_service_access.h
Normal file
310
export/support/local_service_access.h
Normal file
@@ -0,0 +1,310 @@
|
||||
#ifndef LOCAL_SERVICE_ACCESS_H
|
||||
#define LOCAL_SERVICE_ACCESS_H
|
||||
|
||||
#include "../interfaces/core.h"
|
||||
#include "../interfaces/log.h"
|
||||
#include "../interfaces/repository.h"
|
||||
#include "../interfaces/com.h"
|
||||
#include "interface_ptr.h"
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Needed for getpid()
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
namespace sdv
|
||||
{
|
||||
// Forward declaration
|
||||
interface IInterfaceAccess;
|
||||
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
namespace core
|
||||
{
|
||||
#ifndef SDV_CUSTOM_GETOBJECT
|
||||
/**
|
||||
* @brief Get an object from the repository service.
|
||||
* @attention This function only work when called from modules loaded via the repository service.
|
||||
* @param[in] rssObjectName Reference to the name of the requested object (as defined via DECLARE_OBJECT_CLASS_NAME).
|
||||
* @return Returns the smart interface pointer of the object instance if found or nullptr otherwise.
|
||||
*/
|
||||
inline TInterfaceAccessPtr GetObject(const std::string& rssObjectName)
|
||||
{
|
||||
if (!GetCore()) return nullptr;
|
||||
IObjectAccess* pRepository = GetCore<IObjectAccess>();
|
||||
if (!pRepository) return nullptr;
|
||||
return pRepository->GetObject(rssObjectName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get an object from the repository service.
|
||||
* @attention This function can only be used on controlled objects. Local object are not returned using this function.
|
||||
* @param[in] tObjectID Object ID of the object instantiation.
|
||||
* @return Returns the smart interface pointer of the object instance if found or nullptr otherwise.
|
||||
*/
|
||||
inline TInterfaceAccessPtr GetObject(TObjectID tObjectID)
|
||||
{
|
||||
if (!GetCore()) return nullptr;
|
||||
IObjectAccess* pRepository = GetCore<IObjectAccess>();
|
||||
if (!pRepository) return nullptr;
|
||||
return pRepository->GetObjectByID(tObjectID);
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* @brief Get an object from the repository service.
|
||||
* @attention This function only work when called from modules loaded via the repository service.
|
||||
* @param[in] rssObjectName Reference to the name of the requested object (as defined via DECLARE_OBJECT_CLASS_NAME).
|
||||
* @return Returns the smart interface pointer of the object instance if found or nullptr otherwise.
|
||||
*/
|
||||
TInterfaceAccessPtr GetObject(const std::string& rssObjectName);
|
||||
|
||||
/**
|
||||
* @brief Get an object from the repository service.
|
||||
* @attention This function can only be used on controlled objects. Local object are not returned using this function.
|
||||
* @param[in] tObjectID Object ID of the object instantiation.
|
||||
* @return Returns the smart interface pointer of the object instance if found or nullptr otherwise.
|
||||
*/
|
||||
TInterfaceAccessPtr GetObject(TObjectID tObjectID);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get an object from the repository service.
|
||||
* @tparam TInterface The type of interface to return.
|
||||
* @attention This function can only be used on controlled objects. Local object are not returned using this function.
|
||||
* @param[in] rssObjectName Reference to the name of the requested object (as defined via DECLARE_OBJECT_CLASS_NAME).
|
||||
* @return Returns the interface pointer of the object instance if found or nullptr otherwise.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
inline TInterface* GetObject(const std::string& rssObjectName)
|
||||
{
|
||||
return GetObject(rssObjectName).GetInterface<TInterface>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get an object from the repository service.
|
||||
* @tparam TInterface The type of interface to return.
|
||||
* @attention This function can only be used on controlled objects. Local object are not returned using this function.
|
||||
* @param[in] tObjectID Object ID of the object instantiation.
|
||||
* @return Returns the interface pointer of the object instance if found or nullptr otherwise.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
inline TInterface* GetObject(TObjectID tObjectID)
|
||||
{
|
||||
return GetObject(tObjectID).GetInterface<TInterface>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log function enables logging for SDV.
|
||||
* @param[in] eSeverity Severity level of the log message which will be logged, e.g. Info, Warning, Error etc.
|
||||
* @param[in] rssSrcFile Name of the file from which the message is logged.
|
||||
* @param[in] uiSrcLine Line of the file from which the message is logged.
|
||||
* @param[in] rssMessage Reference to the log message to be logged.
|
||||
*/
|
||||
inline void Log(ELogSeverity eSeverity, const u8string& rssSrcFile, uint32_t uiSrcLine, const u8string& rssMessage)
|
||||
{
|
||||
ILogger* pLogger = GetCore() ? GetCore<ILogger>() : nullptr;
|
||||
#ifdef _WIN32
|
||||
if (pLogger) pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, _getpid(), "", rssMessage);
|
||||
#elif defined __unix__
|
||||
if (pLogger) pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, getpid(), "", rssMessage);
|
||||
#else
|
||||
#error The OS is currently not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log a message with line and position.
|
||||
* @param severity The severity of the message. One of the entries from ELogServerity.
|
||||
*/
|
||||
#define SDV_LOG(severity, ...) sdv::core::internal::CSDVLogImpl(severity, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a trace message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_TRACE(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::trace, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a debug message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_DEBUG(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::debug, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log an information message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_INFO(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::info, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a warning message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_WARNING(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::warning, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log an error message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_ERROR(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::error, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a fatal message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_FATAL(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::fatal, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* @brief Template to log messages with line and position.
|
||||
* @param[in] eSeverity Severity level of the message.
|
||||
* @param[in] szSrcFile Name of the file from which the message is logged. Specified by C++ standard.
|
||||
* @param[in] uiSrcLine Line of the file from which the message is logged. Specified by C++ standard.
|
||||
* @param[in] ...args identifier specified by C++ standard that uses the ellipsis notation in the parameters.
|
||||
*/
|
||||
template <typename ...Args>
|
||||
inline void CSDVLogImpl(ELogSeverity eSeverity, const char* szSrcFile, uint32_t uiSrcLine, Args&& ...args)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
(stream << ... << std::forward<Args>(args));
|
||||
|
||||
Log(eSeverity, szSrcFile ? szSrcFile : "", uiSrcLine, stream.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a utility
|
||||
* @param[in] rssUtilityName Reference to the utility name.
|
||||
* @param[in] rssUtilityConfig Optional reference to the utility configuration.
|
||||
* @return Smart pointer to the utility or NULL when the utility could not be found.
|
||||
*/
|
||||
inline TObjectPtr CreateUtility(const std::string& rssUtilityName, const std::string& rssUtilityConfig = std::string())
|
||||
{
|
||||
TInterfaceAccessPtr ptrRepository = GetObject("RepositoryService");
|
||||
IRepositoryUtilityCreate* pUtilityCreate = ptrRepository.GetInterface<IRepositoryUtilityCreate>();
|
||||
if (!pUtilityCreate) return nullptr;
|
||||
return pUtilityCreate->CreateUtility(rssUtilityName, rssUtilityConfig);
|
||||
}
|
||||
} // namespace core
|
||||
|
||||
namespace app
|
||||
{
|
||||
/**
|
||||
* @brief Get application attribute.
|
||||
* @param[in] rssAttribute Name of the attribute.
|
||||
* @return The attribute value or an empty any-value if the attribute wasn't found or didn't have a value.
|
||||
*/
|
||||
inline any_t GetAppAttribute(const std::string& rssAttribute)
|
||||
{
|
||||
const IAttributes* ptrAppAttributes = core::GetObject<IAttributes>("AppControlService");
|
||||
if (!ptrAppAttributes) return {};
|
||||
return ptrAppAttributes->Get(rssAttribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the current application is configured for silent console reporting.
|
||||
* @return Returns whether the silent console reporting has been enabled.
|
||||
*/
|
||||
inline bool ConsoleIsSilent()
|
||||
{
|
||||
return GetAppAttribute("console.info_level") == "silent";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the current application is configured for verbose console reporting.
|
||||
* @return Returns whether the verbose console reporting has been enabled.
|
||||
*/
|
||||
inline bool ConsoleIsVerbose()
|
||||
{
|
||||
return GetAppAttribute("console.info_level") == "verbose";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the instance ID of the application.
|
||||
* @return The instance ID.
|
||||
*/
|
||||
inline uint32_t GetAppInstanceID()
|
||||
{
|
||||
return GetAppAttribute("app.instance_id");
|
||||
}
|
||||
} // namespace app
|
||||
|
||||
namespace com
|
||||
{
|
||||
/**
|
||||
* @brief Create a repository connection to a local server.
|
||||
* @param[in] uiInstanceID Optionally the instance ID of the target system to connect to or 0 (default) to connect to the
|
||||
* instance identified by app-control.
|
||||
* @param[in] nRetries Number of retries to connect (optional, default 30, minimum 3).
|
||||
* @return Returns a smart pointer to the repository proxy. Disconnection takes place when IObjectDestroy::DestroyObject is
|
||||
* called.
|
||||
*/
|
||||
inline TObjectPtr ConnectToLocalServerRepository(uint32_t uiInstanceID = 0, size_t nRetries = 30)
|
||||
{
|
||||
com::IClientConnect* pClientConnect = core::GetObject<com::IClientConnect>("ConnectionService");
|
||||
if (!pClientConnect)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Could not access the connection service." << std::endl;
|
||||
return {};
|
||||
}
|
||||
|
||||
// Connect the client to the server and return the server repository interface.
|
||||
std::string ssConnectString = R"code([Client]
|
||||
Type = "Local"
|
||||
)code";
|
||||
if (uiInstanceID)
|
||||
ssConnectString += "Instance = " + std::to_string(uiInstanceID) + R"code(
|
||||
)code";
|
||||
try
|
||||
{
|
||||
// Try to connect (30 times with 1 second in between).
|
||||
size_t nCnt = 0;
|
||||
sdv::TObjectPtr ptrRepository;
|
||||
while (!ptrRepository && nCnt < nRetries)
|
||||
{
|
||||
nCnt++;
|
||||
ptrRepository = pClientConnect->Connect(ssConnectString);
|
||||
if (!ptrRepository)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
|
||||
// Return the result
|
||||
return ptrRepository;
|
||||
}
|
||||
catch (const XAccessDenied& /*rExcept*/)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "Access denied trying to connect to a local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << "." << std::endl;
|
||||
return {};
|
||||
}
|
||||
catch (const XNotFound& /*rExcept*/)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "Local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << " not found." << std::endl;
|
||||
return {};
|
||||
}
|
||||
catch (const XInvalidState& rExcept)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "The local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << " is in an invalid state: " << rExcept.what() <<
|
||||
std::endl;
|
||||
return {};
|
||||
}
|
||||
catch (const XTimeout& /*rExcept*/)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "Timeout occurred trying to connect to a local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << "." << std::endl;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
} // namespace sdv
|
||||
|
||||
#endif // !defined LOCAL_SERVICE_ACCESS_H
|
||||
85
export/support/mem_access.h
Normal file
85
export/support/mem_access.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef MEM_SUPPORT_H
|
||||
#define MEM_SUPPORT_H
|
||||
|
||||
#include "../interfaces/mem.h"
|
||||
#include <map>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include "interface_ptr.h"
|
||||
#include "sdv_core.h"
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
// Forward declarations
|
||||
TInterfaceAccessPtr GetCore();
|
||||
template <typename TInterface>
|
||||
TInterface* GetCore();
|
||||
|
||||
/**
|
||||
* @brief Get access to the memory manager.
|
||||
* @return Pointer to the memory allocation interface of the memory manager.
|
||||
*/
|
||||
inline sdv::core::IMemoryAlloc* GetMemMgr()
|
||||
{
|
||||
static sdv::core::IMemoryAlloc* pAlloc = nullptr;
|
||||
static const sdv::IInterfaceAccess* pLocalServices = nullptr;
|
||||
|
||||
// cppcheck warns that GetCore is always returning a pointer. This mechanism is preparing for the situation where the
|
||||
// core might be shut down and therefore there is no memory management any more. Suppress the warning.
|
||||
// cppcheck-suppress knownConditionTrueFalse
|
||||
if (GetCore())
|
||||
{
|
||||
if (GetCore() != pLocalServices || !pAlloc)
|
||||
pAlloc = GetCore<IMemoryAlloc>();
|
||||
}
|
||||
else
|
||||
pAlloc = nullptr;
|
||||
pLocalServices = GetCore();
|
||||
return pAlloc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate memory as byte pointer.
|
||||
* @param[in] nAmount The amount of bytes to allocate.
|
||||
* @return Returns a pointer to the allocated memory or NULL when the allocation failed.
|
||||
*/
|
||||
inline pointer<uint8_t> AllocMemBytes(size_t nAmount)
|
||||
{
|
||||
sdv::core::IMemoryAlloc* pMemMgr = GetMemMgr();
|
||||
if (!pMemMgr)
|
||||
throw sdv::core::XNoMemMgr{};
|
||||
pointer<uint8_t> ptrBuffer = pMemMgr->Allocate(static_cast<uint32_t>(nAmount));
|
||||
if (!ptrBuffer)
|
||||
{
|
||||
sdv::core::XAllocFailed exception;
|
||||
exception.uiSize = static_cast<uint32_t>(nAmount);
|
||||
throw exception;
|
||||
}
|
||||
return ptrBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate memory
|
||||
* @tparam T The type to use for the allocation. Default is uint8_t.
|
||||
* @param[in] nAmount The amount of elements to allocate memory for.
|
||||
* @return Returns a pointer to the allocated memory of type T or NULL when the allocation failed.
|
||||
*/
|
||||
template <typename T /*= uint8_t*/>
|
||||
inline pointer<T> AllocMem(size_t nAmount)
|
||||
{
|
||||
return make_ptr<T>(nAmount);
|
||||
//pointer<uint8_t> ptrBuffer = AllocMemBytes(nAmount * sizeof(T));
|
||||
//T* pT = reinterpret_cast<T*>(ptrBuffer.get());
|
||||
//for (size_t nIndex = 0; nIndex < nAmount; nIndex++)
|
||||
// new (pT + nIndex) T();
|
||||
//pointer<T> ptr;
|
||||
//ptr.attach(std::move(ptrBuffer));
|
||||
//return ptr;
|
||||
}
|
||||
} // namespace core
|
||||
} // namespace sdv
|
||||
|
||||
|
||||
#endif // !defined(MEM_SUPPORT_H)
|
||||
665
export/support/pointer.h
Normal file
665
export/support/pointer.h
Normal file
@@ -0,0 +1,665 @@
|
||||
#ifndef SDV_PTR_H
|
||||
#define SDV_PTR_H
|
||||
|
||||
#include <ostream>
|
||||
#include <atomic>
|
||||
#include <algorithm>
|
||||
#include "iterator.h"
|
||||
#ifndef DONT_LOAD_CORE_TYPES
|
||||
#include "../interfaces/core_types.h"
|
||||
#endif
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
// Forward declaration
|
||||
template <typename, size_t>
|
||||
class pointer;
|
||||
|
||||
/**
|
||||
* @brief Managed pointer class.
|
||||
* @details Buffer management class. There are two versions of buffer management, fixed buffer management (nFixedSize template
|
||||
* parameter larger than 0) and dynamic buffer management (nFixedSize template parameter is 0). The fixed buffer management
|
||||
* contains a fixed memory allocation of the amount of elements (capacity) and manages the size within this buffer. Copies of
|
||||
* this pointer class will copy the buffer as well. The dynamic buffer behaves like a shared pointer. Copies of the pointer class will
|
||||
* copy the pointer, but not the content. The lifetime of the content is managed through reference counter. The functions of
|
||||
* this class are similar to the functions of the std::shared_ptr class.
|
||||
* @tparam T Type to use for the buffer allocation.
|
||||
* @tparam nFixedSize Size of the fixed size buffer or 0 for a dynamic sized buffer.
|
||||
*/
|
||||
template <typename T, size_t nFixedSize = 0>
|
||||
class pointer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief The element type of this pointer.
|
||||
*/
|
||||
using element_type = T;
|
||||
|
||||
/**
|
||||
* @brief The size of this pointer allocation element in bytes.
|
||||
*/
|
||||
static const size_t size_bytes = nFixedSize * sizeof(T);
|
||||
|
||||
/**
|
||||
* @brief The size of this pointer allocation in bytes aligned to 64-bits.
|
||||
*/
|
||||
static const size_t aligned_size_bytes = nFixedSize * sizeof(T) + ((nFixedSize * sizeof(T) % 8) ? (8 - nFixedSize * sizeof(T) % 8) : 0);
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
pointer() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Copy constructor of same pointer type.
|
||||
* @param[in] rptr Reference to the pointer to copy.
|
||||
*/
|
||||
pointer(const pointer& rptr);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor of other pointer types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided pointer.
|
||||
* @param[in] rptr Reference to the pointer to copy.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
pointer(const pointer<T, nFixedSize2>& rptr);
|
||||
|
||||
/**
|
||||
* @brief Move constructor of same pointer type.
|
||||
* @param[in] rptr Reference to the pointer to copy.
|
||||
*/
|
||||
pointer(pointer&& rptr);
|
||||
|
||||
/**
|
||||
* @brief Move constructor of other pointer types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided pointer.
|
||||
* @param[in] rptr Reference to the pointer to copy.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
pointer(pointer<T, nFixedSize2>&& rptr);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~pointer();
|
||||
|
||||
/**
|
||||
* @brief Assignment operator of same pointer type.
|
||||
* @param[in] rptr Reference to the pointer to assign.
|
||||
* @return Reference to this pointer.
|
||||
*/
|
||||
pointer& operator=(const pointer& rptr);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator of other pointer types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided pointer.
|
||||
* @param[in] rptr Reference to the pointer to assign.
|
||||
* @return Reference to this pointer.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
pointer& operator=(const pointer<T, nFixedSize2>& rptr);
|
||||
|
||||
/**
|
||||
* @brief Move operator of same pointer type.
|
||||
* @param[in] rptr Reference to the pointer to assign.
|
||||
* @return Reference to this pointer.
|
||||
*/
|
||||
pointer& operator=(pointer&& rptr);
|
||||
|
||||
/**
|
||||
* @brief Move operator of other pointer types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided pointer.
|
||||
* @param[in] rptr Reference to the pointer to assign.
|
||||
* @return Reference to this pointer.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
pointer& operator=(pointer<T, nFixedSize2>&& rptr);
|
||||
|
||||
/**
|
||||
* @brief Reduces the reference count and if zero deletes the allocation. Clears the pointer.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* @brief Swaps this pointer with the provided pointer.
|
||||
* tparam nFixedSizeRight The fixed size of the provided pointer.
|
||||
* @param[in] rptr Reference to the provided pointer to swap with.
|
||||
*/
|
||||
template <size_t nFixedSizeRight>
|
||||
void swap(pointer<T, nFixedSizeRight>& rptr);
|
||||
|
||||
/**
|
||||
* @brief Get access to the underlying buffer.
|
||||
* @return Pointer to the buffer.
|
||||
*/
|
||||
element_type* get() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get a reference to the pointer.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
T& operator*() const;
|
||||
|
||||
/**
|
||||
* @brief Get a reference to the pointer.
|
||||
* @return Pointer to the value.
|
||||
*/
|
||||
T* operator->() const;
|
||||
|
||||
/**
|
||||
* @brief Get the indexed value of the pointer.
|
||||
* @param[in] nIndex Index to request the value of.
|
||||
* @return Reference to the indexed value.
|
||||
*/
|
||||
element_type& operator[](size_t nIndex) const;
|
||||
|
||||
/**
|
||||
* @brief Return whether a pointer is assigned.
|
||||
* @return Returns 'true' when a pointer is assigned; 'false' otherwise.
|
||||
*/
|
||||
operator bool() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return the amount of elements allocated for this pointer.
|
||||
* @return The size of the pointer.
|
||||
*/
|
||||
size_t size() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Resize the pointer.
|
||||
* @param[in] nSize Size of the new pointer.
|
||||
*/
|
||||
void resize(size_t nSize);
|
||||
|
||||
/**
|
||||
* @brief Return the capacity (in amount of elements) this buffer can hold.
|
||||
* @return The capacity of the buffer pointed to by this pointer.
|
||||
*/
|
||||
size_t capacity() const noexcept;
|
||||
|
||||
private:
|
||||
uint32_t m_uiSize = 0; ///< Amount of elements allocated.
|
||||
uint32_t m_uiReserved = 0; ///< Reserved for alignment purposes.
|
||||
union
|
||||
{
|
||||
T m_rgtData[nFixedSize] = {}; ///< The size of the buffer.
|
||||
uint8_t m_rguiBuffer[aligned_size_bytes]; ///< The buffer aligned to 64 bits.
|
||||
};
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
/// @cond DOXYGEN_IGNORE
|
||||
// Forward declaration
|
||||
interface IInternalMemAlloc;
|
||||
template <typename T>
|
||||
pointer<T, 0> make_ptr(IInternalMemAlloc* pAllocator, size_t nSize = 1);
|
||||
/// @endcond
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a pointer class using the allocator and allocating the memory with the given size.
|
||||
* @tparam T Type to use for the allocation.
|
||||
* @param[in] nSize Size to allocate (in elements).
|
||||
* @return The pointer class.
|
||||
*/
|
||||
template <typename T>
|
||||
pointer<T> make_ptr(size_t nSize = 1);
|
||||
|
||||
/**
|
||||
* @brief Specialization for dynamic sized buffer management.
|
||||
* @tparam T Type to use for the buffer allocation.
|
||||
*/
|
||||
template <typename T>
|
||||
class pointer<T, 0>
|
||||
{
|
||||
friend pointer<T> internal::make_ptr<T>(internal::IInternalMemAlloc* pAllocator, size_t nSize /*= 1*/);
|
||||
friend pointer<T> make_ptr<T>(size_t);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The element type of this pointer.
|
||||
*/
|
||||
using element_type = T;
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
pointer() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Copy constructor of same pointer type.
|
||||
* @param[in] rptr Reference to the pointer to copy.
|
||||
*/
|
||||
pointer(const pointer& rptr);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor of other pointer types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided pointer.
|
||||
* @param[in] rptr Reference to the pointer to copy.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
pointer(const pointer<T, nFixedSize2>& rptr);
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
* @param[in] rptr Reference to the pointer to move.
|
||||
*/
|
||||
pointer(pointer&& rptr) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Move constructor of other pointer types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided pointer.
|
||||
* @param[in] rptr Reference to the pointer to copy.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
pointer(const pointer<T, nFixedSize2>&& rptr);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~pointer();
|
||||
|
||||
/**
|
||||
* @brief Assignment operator of same pointer type.
|
||||
* @param[in] rptr Reference to the pointer to assign.
|
||||
* @return Reference to this pointer.
|
||||
*/
|
||||
pointer& operator=(const pointer& rptr);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator of other pointer types.
|
||||
* @param[in] rptr Reference to the pointer to assign.
|
||||
* @return Reference to this pointer.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
pointer& operator=(const pointer<T, nFixedSize2>& rptr);
|
||||
|
||||
/**
|
||||
* @brief Move operator of same pointer type.
|
||||
* @param[in] rptr Reference to the pointer to move.
|
||||
* @return Reference to this pointer.
|
||||
*/
|
||||
pointer& operator=(pointer&& rptr) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Move operator of other pointer types.
|
||||
* @param[in] rptr Reference to the pointer to assign.
|
||||
* @return Reference to this pointer.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
pointer& operator=(pointer<T, nFixedSize2>&& rptr);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Attach an uint8_t buffer.
|
||||
* @param[in] rptrBuffer Reference to the pointer to attach.
|
||||
*/
|
||||
void attach(pointer<uint8_t>&& rptrBuffer);
|
||||
|
||||
/**
|
||||
* @brief Detach the uint8_t buffer.
|
||||
* @return Reference to the pointer to detach.
|
||||
*/
|
||||
pointer<uint8_t>&& detach();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Reduces the reference count and if zero deletes the allocation. Clears the pointer.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* @brief Swaps this pointer with the provided pointer.
|
||||
* tparam nFixedSizeRight The fixed size of the provided pointer.
|
||||
* @param[in] rptr Reference to the provided pointer to swap with.
|
||||
*/
|
||||
template <size_t nFixedSizeRight>
|
||||
void swap(pointer<T, nFixedSizeRight>& rptr);
|
||||
|
||||
/**
|
||||
* @brief Get access to the underlying buffer.
|
||||
* @return Pointer to the buffer.
|
||||
*/
|
||||
element_type* get() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get a reference to the pointer.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
T& operator*() const;
|
||||
|
||||
/**
|
||||
* @brief Get a reference to the pointer.
|
||||
* @return Pointer to the value.
|
||||
*/
|
||||
T* operator->() const;
|
||||
|
||||
/**
|
||||
* @brief Get the indexed value of the pointer.
|
||||
* @param[in] nIndex Index to request the value of.
|
||||
* @return Reference to the indexed value.
|
||||
*/
|
||||
element_type& operator[](size_t nIndex) const;
|
||||
|
||||
/**
|
||||
* @brief Return whether a pointer is assigned.
|
||||
* @return Returns 'true' when a pointer is assigned; 'false' otherwise.
|
||||
*/
|
||||
operator bool() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return the amount of elements allocated for this pointer.
|
||||
* @return The size of the pointer.
|
||||
*/
|
||||
size_t size() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Resize the pointer.
|
||||
* @attention A call to this function is not synchronized with other functions.
|
||||
* @param[in] nSize Size of the new pointer.
|
||||
*/
|
||||
void resize(size_t nSize);
|
||||
|
||||
/**
|
||||
* @brief Return the capacity (in amount of elements) this buffer can hold.
|
||||
* @return The capacity of the buffer pointed to by this pointer.
|
||||
*/
|
||||
size_t capacity() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get reference count on current shares.
|
||||
* @return Reference count.
|
||||
*/
|
||||
size_t ref_count() const noexcept;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief The internal data structure holding the pointer information.
|
||||
*/
|
||||
struct SAllocation
|
||||
{
|
||||
internal::IInternalMemAlloc* pAllocator = nullptr; ///< Pointer to the memory allocator.
|
||||
T* pData = nullptr; ///< Pointer to the data.
|
||||
uint32_t uiSize = 0; ///< Amount of bytes allocated.
|
||||
std::atomic_uint32_t uiRefCnt = 0; ///< Reference count.
|
||||
};
|
||||
|
||||
SAllocation* m_psAllocation = nullptr; ///< Actual pointer to the allocation
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Swap two pointers.
|
||||
* @tparam T Type to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrLeft Reference to the first pointer.
|
||||
* @param[in] rptrRight Reference to the second pointer.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
void swap(pointer<T, nFixedSizeLeft>& rptrLeft, pointer<T, nFixedSizeRight>& rptrRight);
|
||||
|
||||
/**
|
||||
* @brief Compare two pointers for equality.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @return Returns 'true' when both pointers are equal; false when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator==(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare two pointers for inequality.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @return Returns 'true' when both pointers are not equal; false when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator!=(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether one pointer is smaller than another pointer.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @return Returns 'true' when the left pointer is smaller than the right pointer; false when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator<(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether one pointer is smaller than or equal to another pointer.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @return Returns 'true' when the left pointer is smaller than or equal to the right pointer; false when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator<=(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether one pointer is larger than another pointer.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @return Returns 'true' when the left pointer is larger than the right pointer; false when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator>(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether one pointer is larger than or equal to another pointer.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @return Returns 'true' when the left pointer is larger than or equal to the right pointer; false when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator>=(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left pointer is equal too NULL.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if the left pointer equals NULL; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
bool operator==(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t pNull) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the right pointer is equal too NULL.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if the right pointer equals NULL; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
bool operator==(std::nullptr_t pNull, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left pointer is not equal too NULL.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if the left pointer does not equal to NULL; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
bool operator!=(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t pNull) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the right pointer is not equal too NULL.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if the right pointer does not equal to NULL; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
bool operator!=(std::nullptr_t pNull, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left pointer is smaller than NULL.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if the left pointer is smaller than NULL; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
bool operator<(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t pNull) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the NULL is smaller than the left pointer.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if NULL is smaller than the left pointer; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
bool operator<(std::nullptr_t pNull, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left pointer is smaller than or equal to NULL.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if the left pointer is smaller than or equal to NULL; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
bool operator<=(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t pNull) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the NULL is smaller than or equal to the left pointer.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if NULL is smaller than or equal to the left pointer; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
bool operator<=(std::nullptr_t pNull, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left pointer is larger than NULL.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if the left pointer is larger than NULL; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
bool operator>(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t pNull) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the NULL is larger than the left pointer.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if NULL is larger than the left pointer; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
bool operator>(std::nullptr_t pNull, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left pointer is smaller than or equal to NULL.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left pointer.
|
||||
* @param[in] rptrLeft Reference to the left pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if the left pointer is smaller than or equal to NULL; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
bool operator>=(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t pNull) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the NULL is smaller than or equal to the left pointer.
|
||||
* @tparam T Type of the pointer to use as a base.
|
||||
* @tparam nFixedSizeRight The fixed size of the right pointer.
|
||||
* @param[in] rptrRight Reference to the right pointer.
|
||||
* @param[in] pNull Pointer to a nullptr.
|
||||
* @return Returns 'true' if NULL is smaller than or equal to the left pointer; 'false' when not.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
bool operator>=(std::nullptr_t pNull, const pointer<T, nFixedSizeRight>& rptrRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Stream the value of a the pointer to an output stream.
|
||||
* @tparam T Type of pointer.
|
||||
* @tparam U Character type of output stream.
|
||||
* @tparam V Character traits of output stream.
|
||||
* @tparam nFixedSize The fixed size of the pointer.
|
||||
* @param[in] rstream Reference to the stream.
|
||||
* @param[in] rptr Reference to the pointer.
|
||||
* @return Reference to the stream.
|
||||
*/
|
||||
template <class T, class U, class V, size_t nFixedSize>
|
||||
std::basic_ostream<U, V>& operator<<(std::basic_ostream<U, V>& rstream, const pointer<T, nFixedSize>& rptr);
|
||||
|
||||
/**
|
||||
* @brief C++ library stream support - reading from stream.
|
||||
* @tparam TTraits Character traits of the stream buffer.
|
||||
* @param[in, out] pStreamBuf Pointer to the stream buffer to read from.
|
||||
* @return Pointer object created from the stream buffer.
|
||||
*/
|
||||
template <typename TTraits = std::char_traits<char>>
|
||||
pointer<uint8_t> from_stream(std::basic_streambuf<char, TTraits>* pStreamBuf);
|
||||
|
||||
/**
|
||||
* @brief C++ library stream support - writing to stream.
|
||||
* @tparam TTraits Character traits of the stream buffer.
|
||||
* @param[in] rptr Reference to the pointer to write to the stream.
|
||||
* @param[in, out] pStreamBuf Pointer to the stream buffer to write to.
|
||||
*/
|
||||
template <typename TTraits = std::char_traits<char>>
|
||||
void to_stream(const pointer<uint8_t>& rptr, std::basic_streambuf<char, TTraits>* pStreamBuf);
|
||||
|
||||
/**
|
||||
* @brief For the uint8_t pointer a specific cast operation exists.
|
||||
* @attention Use with care. There is no guarantee that the pointer corresponds to the layout of the requested type. If
|
||||
* possible use serialization instead.
|
||||
* @tparam T Type to cast to. T must be a standard-layout-type.
|
||||
* @param[in] rptr Reference to the pointer containing the data buffer.
|
||||
* @param[in] nOffset Offset the type starts.
|
||||
* @return Returns a casted pointer if the buffer is large enough (offset + sizeof(T)); NULL otherwise.
|
||||
*/
|
||||
template <typename T>
|
||||
T* cast(pointer<uint8_t>& rptr, size_t nOffset = 0);
|
||||
|
||||
/**
|
||||
* @brief For the uint8_t pointer a specific cast operation exists.
|
||||
* @attention Use with care. There is no guarantee that the pointer corresponds to the layout of the requested type. If
|
||||
* possible use serialization instead.
|
||||
* @tparam T Type to cast to. T must be a standard-layout-type.
|
||||
* @param[in] rptr Reference to the pointer containing the data buffer.
|
||||
* @param[in] nOffset Offset the type starts.
|
||||
* @return Returns a casted pointer if the buffer is large enough (offset + sizeof(T)); NULL otherwise.
|
||||
*/
|
||||
template <typename T>
|
||||
const T* cast(const pointer<uint8_t>& rptr, size_t nOffset = 0);
|
||||
|
||||
} // namespace sdv
|
||||
|
||||
#include "pointer.inl"
|
||||
|
||||
#endif // !defined SDV_PTR_H
|
||||
877
export/support/pointer.inl
Normal file
877
export/support/pointer.inl
Normal file
@@ -0,0 +1,877 @@
|
||||
#ifndef SDV_PTR_INL
|
||||
#define SDV_PTR_INL
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifndef SDV_PTR_H
|
||||
#error Do not include "pointer.inl" directly. Include "pointer.h" instead!
|
||||
#endif //!defined SDV_PTR_H
|
||||
|
||||
#include "pointer.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
// There are some versions of GCC that produce bogus warnings for -Wstringop-overflow (e.g. version 9.4 warns, 11.4 not - changing
|
||||
// the compile order without changing the logical behavior, will produce different results).
|
||||
// See also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100477
|
||||
// And https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115074
|
||||
// Suppress this warning for the string class.
|
||||
// NOTE 03.08.2025: Additional bogus warnigs/errors are suppressed for newer versions of the compiler.
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Prevent static code analysis warnings about noexcept for mode constructors and operators. Due to a constexpr if statement,
|
||||
// the constructor might or might not use exceptions and therefore noexcept might or might not be applied.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26439)
|
||||
#endif
|
||||
|
||||
/// @cond DOXYGEN_IGNORE
|
||||
namespace sdv
|
||||
{
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline pointer<T, nFixedSize>::pointer() noexcept
|
||||
{
|
||||
// Ensure the layout is the same on all platforms.
|
||||
static_assert(offsetof(pointer, m_uiSize) == 0);
|
||||
static_assert(offsetof(pointer, m_rgtData) == 8);
|
||||
static_assert(sizeof(pointer) == 8 + aligned_size_bytes);
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline pointer<T, nFixedSize>::pointer(const pointer& rptr)
|
||||
{
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
template <size_t nFixedSize2>
|
||||
inline pointer<T, nFixedSize>::pointer(const pointer<T, nFixedSize2>& rptr)
|
||||
{
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline pointer<T, nFixedSize>::pointer(pointer&& rptr)
|
||||
{
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
rptr.reset();
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
template <size_t nFixedSize2>
|
||||
inline pointer<T, nFixedSize>::pointer(pointer<T, nFixedSize2>&& rptr)
|
||||
{
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
rptr.reset();
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline pointer<T, nFixedSize>::~pointer()
|
||||
{
|
||||
if constexpr (!std::is_scalar_v<T>)
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < nFixedSize; nIndex++)
|
||||
m_rgtData[nIndex].~T();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
// Member m_uiReserved is not copied. Suppress static code analysis warning.
|
||||
// cppcheck-suppress operatorEqVarError
|
||||
inline pointer<T, nFixedSize>& pointer<T, nFixedSize>::operator=(const pointer& rptr)
|
||||
{
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
template <size_t nFixedSize2>
|
||||
// Member m_uiReserved is not copied. Suppress static code analysis warning.
|
||||
// cppcheck-suppress operatorEqVarError
|
||||
inline pointer<T, nFixedSize>& pointer<T, nFixedSize>::operator=(const pointer<T, nFixedSize2>& rptr)
|
||||
{
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
// Member m_uiReserved is not copied. Suppress static code analysis warning.
|
||||
// cppcheck-suppress operatorEqVarError
|
||||
inline pointer<T, nFixedSize>& pointer<T, nFixedSize>::operator=(pointer&& rptr)
|
||||
{
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
rptr.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
template <size_t nFixedSize2>
|
||||
// Member m_uiReserved is not copied. Suppress static code analysis warning.
|
||||
// cppcheck-suppress operatorEqVarError
|
||||
inline pointer<T, nFixedSize>& pointer<T, nFixedSize>::operator=(pointer<T, nFixedSize2>&& rptr)
|
||||
{
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
rptr.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline void pointer<T, nFixedSize>::reset()
|
||||
{
|
||||
resize(0);
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
template <size_t nFixedSizeRight>
|
||||
inline void pointer<T, nFixedSize>::swap(pointer<T, nFixedSizeRight>& rptr)
|
||||
{
|
||||
// Copy the provided content into a temporary buffer.
|
||||
T rgtTemp[nFixedSizeRight];
|
||||
size_t nSizeRight = rptr.size();
|
||||
std::copy_n(rptr.get(), nSizeRight, rgtTemp);
|
||||
|
||||
// Copy the member buffer into the buffer of the provided pointer
|
||||
rptr.resize(size());
|
||||
std::copy_n(get(), size(), rptr.get());
|
||||
|
||||
// Copy the temporary buffer into this class' buffer.
|
||||
resize(nSizeRight);
|
||||
std::copy_n(rgtTemp, nSizeRight, get());
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline typename pointer<T, nFixedSize>::element_type* pointer<T, nFixedSize>::get() const noexcept
|
||||
{
|
||||
return const_cast<element_type*>(m_rgtData);
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline T& pointer<T, nFixedSize>::operator*() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline T* pointer<T, nFixedSize>::operator->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline typename pointer<T, nFixedSize>::element_type& pointer<T, nFixedSize>::operator[](size_t nIndex) const
|
||||
{
|
||||
if (nIndex >= size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(nIndex);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return get()[nIndex];
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline pointer<T, nFixedSize>::operator bool() const noexcept
|
||||
{
|
||||
// Always true
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline size_t pointer<T, nFixedSize>::size() const noexcept
|
||||
{
|
||||
return m_uiSize;
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline void pointer<T, nFixedSize>::resize(size_t nSize)
|
||||
{
|
||||
// Replace all deleted elements with the default constructed elements
|
||||
for (size_t nIndex = nSize; nIndex < std::min(nFixedSize, static_cast<size_t>(m_uiSize)); nIndex++)
|
||||
{
|
||||
// Destruct the existing and construct the new
|
||||
if constexpr (!std::is_scalar_v<T>)
|
||||
{
|
||||
m_rgtData[nIndex].~T();
|
||||
new (m_rgtData + nIndex) T();
|
||||
}
|
||||
else
|
||||
if (nIndex < nFixedSize)
|
||||
m_rgtData[nIndex] = static_cast<T>(0);
|
||||
|
||||
}
|
||||
|
||||
if (nSize > nFixedSize)
|
||||
{
|
||||
XBufferTooSmall exception;
|
||||
exception.uiSize = static_cast<uint64_t>(nSize);
|
||||
exception.uiCapacity = static_cast<uint64_t>(nFixedSize);
|
||||
throw exception;
|
||||
}
|
||||
|
||||
m_uiSize = static_cast<uint32_t>(nSize);
|
||||
}
|
||||
|
||||
template <typename T, size_t nFixedSize>
|
||||
inline size_t pointer<T, nFixedSize>::capacity() const noexcept
|
||||
{
|
||||
return nFixedSize;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline pointer<T, 0>::pointer() noexcept
|
||||
{
|
||||
// The size of the pointer class should not be larger than the size of a pointer.
|
||||
static_assert(sizeof(pointer<T>) == sizeof(T*));
|
||||
|
||||
// The size of the allocation class should be the size of two pointers and two ints. This is important to ensure that the
|
||||
// location of each element is exactly the same for every process regardless of compiler and library version.
|
||||
static_assert(sizeof(SAllocation) == sizeof(internal::IInternalMemAlloc*) + sizeof(T*) + sizeof(uint32_t) * 2);
|
||||
}
|
||||
|
||||
namespace core
|
||||
{
|
||||
// Forward declarations
|
||||
pointer<uint8_t> AllocMemBytes(size_t nAmount);
|
||||
} // namespace core
|
||||
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* @brief Internal memory allocation interface doing the actual allocation. This interface is not exposed publicly and
|
||||
* should only be used by the memory manager.
|
||||
*/
|
||||
interface IInternalMemAlloc
|
||||
{
|
||||
/**
|
||||
* @brief Allocate memory.
|
||||
* @param[in] nSize The size of the memory to allocate (in bytes).
|
||||
* @return Pointer to the memory allocation or NULL when memory allocation failed.
|
||||
*/
|
||||
virtual void* Alloc(size_t nSize) = 0;
|
||||
|
||||
/**
|
||||
* @brief Reallocate memory.
|
||||
* @param[in] pData Pointer to a previous allocation or NULL when no previous allocation was available.
|
||||
* @param[in] nSize The size of the memory to allocate (in bytes).
|
||||
* @return Pointer to the memory allocation or NULL when memory allocation failed.
|
||||
*/
|
||||
virtual void* Realloc(void* pData, size_t nSize) = 0;
|
||||
|
||||
/**
|
||||
* @brief Free a memory allocation.
|
||||
* @param[in] pData Pointer to a previous allocation.
|
||||
*/
|
||||
virtual void Free(void* pData) = 0;
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
template <typename T>
|
||||
inline pointer<T, 0>::pointer(const pointer& rptr)
|
||||
{
|
||||
m_psAllocation = rptr.m_psAllocation;
|
||||
if (m_psAllocation)
|
||||
m_psAllocation->uiRefCnt++;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <size_t nFixedSize2>
|
||||
inline pointer<T, 0>::pointer(const pointer<T, nFixedSize2>& rptr)
|
||||
{
|
||||
// Fixed sized buffer; copy the content
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline pointer<T, 0>::pointer(pointer&& rptr) noexcept
|
||||
{
|
||||
m_psAllocation = rptr.m_psAllocation;
|
||||
rptr.m_psAllocation = nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <size_t nFixedSize2>
|
||||
inline pointer<T, 0>::pointer(const pointer<T, nFixedSize2>&& rptr)
|
||||
{
|
||||
// Fixed sized buffer; copy the content and reset supplied pointer
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
rptr.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline pointer<T, 0>::~pointer()
|
||||
{
|
||||
try
|
||||
{
|
||||
reset();
|
||||
}
|
||||
catch (const sdv::XSysExcept&)
|
||||
{
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline pointer<T>& pointer<T, 0>::operator=(const pointer& rptr)
|
||||
{
|
||||
// Dynamic buffer, share the allocation
|
||||
reset();
|
||||
m_psAllocation = rptr.m_psAllocation;
|
||||
if (m_psAllocation)
|
||||
m_psAllocation->uiRefCnt++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <size_t nFixedSize2>
|
||||
inline pointer<T>& pointer<T, 0>::operator=(const pointer<T, nFixedSize2>& rptr)
|
||||
{
|
||||
// Fixed sized buffer; copy the content
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline pointer<T>& pointer<T, 0>::operator=(pointer<T>&& rptr) noexcept
|
||||
{
|
||||
// Dynamic buffer, take over the allocation.
|
||||
try
|
||||
{
|
||||
reset();
|
||||
}
|
||||
catch (const sdv::XSysExcept&)
|
||||
{
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
}
|
||||
m_psAllocation = rptr.m_psAllocation;
|
||||
rptr.m_psAllocation = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <size_t nFixedSize2>
|
||||
inline pointer<T>& pointer<T, 0>::operator=(pointer<T, nFixedSize2>&& rptr)
|
||||
{
|
||||
// Fixed sized buffer; copy the content and reset supplied pointer
|
||||
resize(rptr.size());
|
||||
std::copy_n(rptr.get(), rptr.size(), get());
|
||||
rptr.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void pointer<T, 0>::attach(pointer<uint8_t>&& rptrBuffer)
|
||||
{
|
||||
// Move buffer pointer (structures are identical).
|
||||
operator=(std::move(*reinterpret_cast<pointer<T>*>(&rptrBuffer)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline pointer<uint8_t>&& pointer<T, 0>::detach()
|
||||
{
|
||||
// Move this pointer (structures are identical).
|
||||
return std::move(*reinterpret_cast<pointer<uint8_t>*>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void pointer<T, 0>::reset()
|
||||
{
|
||||
// Reduce allocation sharing reference counter. If 0, no more share; delete allocation.
|
||||
if (!m_psAllocation) return;
|
||||
if (!m_psAllocation->pAllocator) throw core::XNoMemMgr();
|
||||
if (!m_psAllocation->uiRefCnt)
|
||||
{
|
||||
XInvalidRefCount exception;
|
||||
exception.uiCount = 0;
|
||||
throw exception;
|
||||
}
|
||||
if (!--m_psAllocation->uiRefCnt)
|
||||
{
|
||||
// Call the destructor on all elements
|
||||
if constexpr (!std::is_scalar_v<T>)
|
||||
{
|
||||
for (size_t nIndex = 0; m_psAllocation->pData && nIndex < m_psAllocation->uiSize / sizeof(T); nIndex++)
|
||||
m_psAllocation->pData[nIndex].~T();
|
||||
}
|
||||
|
||||
// Delete the data
|
||||
if (m_psAllocation->pData)
|
||||
m_psAllocation->pAllocator->Free(m_psAllocation->pData);
|
||||
|
||||
// Delete the allocation structure
|
||||
delete m_psAllocation;
|
||||
}
|
||||
m_psAllocation = nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <size_t nFixedSizeRight>
|
||||
inline void pointer<T, 0>::swap(pointer<T, nFixedSizeRight>& rptr)
|
||||
{
|
||||
if constexpr (nFixedSizeRight != 0)
|
||||
{
|
||||
// Fixed sized buffer; copy the content
|
||||
// Copy the provided content into a temporary buffer.
|
||||
T rgtTemp[nFixedSizeRight];
|
||||
size_t nSizeRight = rptr.size();
|
||||
std::copy_n(rptr.get(), nSizeRight, rgtTemp);
|
||||
|
||||
// Copy the member buffer into the buffer of the provided pointer
|
||||
rptr.resize(size());
|
||||
std::copy_n(get(), size(), rptr.get());
|
||||
|
||||
// Copy the temporary buffer into this class' buffer.
|
||||
resize(nSizeRight);
|
||||
std::copy_n(rgtTemp, nSizeRight, get());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dynamic sized buffer; exchange the pointer
|
||||
SAllocation* pTemp = m_psAllocation;
|
||||
m_psAllocation = rptr.m_psAllocation;
|
||||
rptr.m_psAllocation = pTemp;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename pointer<T, 0>::element_type* pointer<T, 0>::get() const noexcept
|
||||
{
|
||||
return m_psAllocation ? m_psAllocation->pData : nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T& pointer<T, 0>::operator*() const
|
||||
{
|
||||
if (!m_psAllocation) throw XNullPointer();
|
||||
return *get();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* pointer<T, 0>::operator->() const
|
||||
{
|
||||
if (!m_psAllocation) throw XNullPointer();
|
||||
return get();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename pointer<T, 0>::element_type& pointer<T, 0>::operator[](size_t nIndex) const
|
||||
{
|
||||
if (!m_psAllocation) throw XNullPointer();
|
||||
if (nIndex >= size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(nIndex);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return get()[nIndex];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline pointer<T, 0>::operator bool() const noexcept
|
||||
{
|
||||
return m_psAllocation && m_psAllocation->pData;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline size_t pointer<T, 0>::size() const noexcept
|
||||
{
|
||||
return m_psAllocation ? m_psAllocation->uiSize / sizeof(T) : 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void pointer<T, 0>::resize(size_t nSize)
|
||||
{
|
||||
if (!m_psAllocation || !m_psAllocation->pAllocator || !m_psAllocation->pData)
|
||||
{
|
||||
operator=(std::move(make_ptr<T>(nSize)));
|
||||
return;
|
||||
}
|
||||
size_t nTotalSize = nSize * sizeof(T);
|
||||
|
||||
// Is the new size smaller than the old size, call the destructors for the deleted
|
||||
if (nSize < m_psAllocation->uiSize / sizeof(T))
|
||||
{
|
||||
if constexpr (!std::is_scalar_v<T>)
|
||||
{
|
||||
for (size_t nIndex = nSize; nIndex < m_psAllocation->uiSize / sizeof(T); nIndex++)
|
||||
m_psAllocation->pData[nIndex].~T();
|
||||
}
|
||||
|
||||
// Since the destructors are called; update the size info already.
|
||||
m_psAllocation->uiSize = static_cast<uint32_t>(nSize * sizeof(T));
|
||||
}
|
||||
|
||||
// Treat reallocation differently between objects and scalars. Objects might have pointers and therefore need to be
|
||||
// copied. Scalars can be reallocated without reinitialization.
|
||||
T* ptAllocation = nullptr;
|
||||
if constexpr (std::is_scalar_v<T>)
|
||||
{
|
||||
ptAllocation = reinterpret_cast<T*>(m_psAllocation->pAllocator->Realloc(m_psAllocation->pData, nTotalSize));
|
||||
if (nTotalSize && !ptAllocation)
|
||||
{
|
||||
core::XAllocFailed exception;
|
||||
exception.uiSize = static_cast<uint32_t>(nTotalSize);
|
||||
throw exception;
|
||||
}
|
||||
|
||||
// Is the new size larger than the old size, call the constructors for the new elements
|
||||
for (size_t nIndex = m_psAllocation->uiSize / sizeof(T); nIndex < nSize; nIndex++)
|
||||
ptAllocation[nIndex] = static_cast<T>(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate new size
|
||||
ptAllocation = reinterpret_cast<T*>(m_psAllocation->pAllocator->Alloc(nTotalSize));
|
||||
if (nTotalSize && !ptAllocation)
|
||||
{
|
||||
core::XAllocFailed exception;
|
||||
exception.uiSize = static_cast<uint32_t>(nTotalSize);
|
||||
throw exception;
|
||||
}
|
||||
|
||||
// Move the elements from the existing allocation to the new allocation.
|
||||
for (size_t nIndex = 0; nIndex < std::min(static_cast<size_t>(m_psAllocation->uiSize / sizeof(T)), nSize); nIndex++)
|
||||
new (ptAllocation + nIndex) T(std::move(m_psAllocation->pData[nIndex]));
|
||||
|
||||
// Is the new size larger than the old size, call the constructors for the new elements
|
||||
for (size_t nIndex = m_psAllocation->uiSize / sizeof(T); nIndex < nSize; nIndex++)
|
||||
new (ptAllocation + nIndex) T();
|
||||
|
||||
// Free the old data.
|
||||
if (m_psAllocation->pData) m_psAllocation->pAllocator->Free(m_psAllocation->pData);
|
||||
}
|
||||
|
||||
// Set new information
|
||||
m_psAllocation->pData = ptAllocation;
|
||||
m_psAllocation->uiSize = static_cast<uint32_t>(nSize * sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline size_t pointer<T, 0>::capacity() const noexcept
|
||||
{
|
||||
return m_psAllocation ? m_psAllocation->uiSize / sizeof(T) : 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline size_t pointer<T, 0>::ref_count() const noexcept
|
||||
{
|
||||
return m_psAllocation ? static_cast<size_t>(m_psAllocation->uiRefCnt) : 0;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline void swap(pointer<T, nFixedSizeLeft>& rptrLeft, pointer<T, nFixedSizeRight>& rptrRight)
|
||||
{
|
||||
rptrLeft.swap(rptrRight);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator==(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
if constexpr (nFixedSizeLeft || nFixedSizeRight) // Compare content
|
||||
{
|
||||
// Prevent comparing NULL-pointer.
|
||||
if (rptrLeft.get() == rptrRight.get()) return true; // Pointers are identical; comparing same object.
|
||||
if (!rptrLeft.size() && !rptrRight.size()) return true; // Both pointers are empty.
|
||||
if (rptrLeft.get() && !rptrRight.get()) return false; // Right is NULL; left not.
|
||||
if (!rptrLeft.get() && rptrRight.get()) return false; // Left is NULL; right not.
|
||||
return std::equal(rptrLeft.get(), rptrLeft.get() + rptrLeft.size(),
|
||||
rptrRight.get(), rptrRight.get() + rptrRight.size());
|
||||
} else // Compare pointers
|
||||
return rptrLeft.get() == rptrRight.get();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator!=(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
return !operator==(rptrLeft, rptrRight);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator<(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
if constexpr (nFixedSizeLeft || nFixedSizeRight) // Compare content
|
||||
return std::lexicographical_compare(rptrLeft.get(), rptrLeft.get() + rptrLeft.size(),
|
||||
rptrRight.get(), rptrRight.get() + rptrRight.size());
|
||||
else // Compare pointers
|
||||
return rptrLeft.get() < rptrRight.get();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator<=(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
if constexpr (nFixedSizeLeft || nFixedSizeRight) // Compare content
|
||||
return !std::lexicographical_compare(rptrRight.get(), rptrRight.get() + rptrRight.size(),
|
||||
rptrLeft.get(), rptrLeft.get() + rptrLeft.size());
|
||||
else // Compare pointers
|
||||
return rptrLeft.get() <= rptrRight.get();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator>(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
if constexpr (nFixedSizeLeft || nFixedSizeRight) // Compare content
|
||||
return std::lexicographical_compare(rptrRight.get(), rptrRight.get() + rptrRight.size(),
|
||||
rptrLeft.get(), rptrLeft.get() + rptrLeft.size());
|
||||
else // Compare pointers
|
||||
return rptrLeft.get() > rptrRight.get();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator>=(const pointer<T, nFixedSizeLeft>& rptrLeft, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
if constexpr (nFixedSizeLeft || nFixedSizeRight) // Compare content
|
||||
return !std::lexicographical_compare(rptrLeft.get(), rptrLeft.get() + rptrLeft.size(),
|
||||
rptrRight.get(), rptrRight.get() + rptrRight.size());
|
||||
else // Compare pointers
|
||||
return rptrLeft.get() >= rptrRight.get();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
inline bool operator==(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t) noexcept
|
||||
{
|
||||
return rptrLeft.get() == nullptr;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
inline bool operator==(std::nullptr_t, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
return nullptr == rptrRight.get();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
inline bool operator!=(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t) noexcept
|
||||
{
|
||||
return rptrLeft.get() != nullptr;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
inline bool operator!=(std::nullptr_t, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
return nullptr != rptrRight.get();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
inline bool operator<(const pointer<T, nFixedSizeLeft>& /*rptrLeft*/, std::nullptr_t) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
inline bool operator<(std::nullptr_t, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
return nullptr != rptrRight.get();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
inline bool operator<=(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t) noexcept
|
||||
{
|
||||
return rptrLeft.get() == nullptr;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
inline bool operator<=(std::nullptr_t, const pointer<T, nFixedSizeRight>& /*rptrRight*/) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
inline bool operator>(const pointer<T, nFixedSizeLeft>& rptrLeft, std::nullptr_t) noexcept
|
||||
{
|
||||
return rptrLeft.get() != nullptr;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
inline bool operator>(std::nullptr_t, const pointer<T, nFixedSizeRight>& /*rptrRight*/) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft>
|
||||
inline bool operator>=(const pointer<T, nFixedSizeLeft>& /*rptrLeft*/, std::nullptr_t) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeRight>
|
||||
inline bool operator>=(std::nullptr_t, const pointer<T, nFixedSizeRight>& rptrRight) noexcept
|
||||
{
|
||||
return nullptr == rptrRight.get();
|
||||
}
|
||||
|
||||
template <class T, class U, class V, size_t nFixedSize>
|
||||
inline std::basic_ostream<U, V>& operator<<(std::basic_ostream<U, V>& rstream, const pointer<T, nFixedSize>& rptr)
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < rptr.size(); nIndex++)
|
||||
rstream << rptr[nIndex];
|
||||
return rstream;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline pointer<T> make_ptr(size_t nSize /*= 1*/)
|
||||
{
|
||||
pointer<uint8_t> ptrBuffer = core::AllocMemBytes(nSize * sizeof(T));
|
||||
T* pT = reinterpret_cast<T*>(ptrBuffer.get());
|
||||
for (size_t nIndex = 0; nIndex < nSize; nIndex++)
|
||||
new (pT + nIndex) T();
|
||||
pointer<T> ptr;
|
||||
ptr.attach(std::move(ptrBuffer));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* @brief Create a pointer class using the allocator and allocating the memory with the given size.
|
||||
* @tparam T Type to use for the allocation.
|
||||
* @param[in] pAllocator Pointer to the allocator. Must not be NULL.
|
||||
* @param[in] nSize Size to allocate (in elements).
|
||||
* @return The pointer class.
|
||||
*/
|
||||
template <typename T>
|
||||
inline pointer<T> make_ptr(internal::IInternalMemAlloc* pAllocator, size_t nSize /*= 1*/)
|
||||
{
|
||||
pointer<T> pointer;
|
||||
if (!pAllocator) throw core::XNoMemMgr();
|
||||
size_t nTotalSize = nSize * sizeof(T);
|
||||
|
||||
// Create a new allocation structure
|
||||
using SAllocation = std::remove_pointer_t<decltype(pointer.m_psAllocation)>;
|
||||
pointer.m_psAllocation = new SAllocation;
|
||||
if (!pointer.m_psAllocation)
|
||||
{
|
||||
core::XAllocFailed exception;
|
||||
exception.uiSize = static_cast<uint32_t>(sizeof(SAllocation));
|
||||
throw exception;
|
||||
}
|
||||
pointer.m_psAllocation->pAllocator = pAllocator;
|
||||
|
||||
// Allocate the amount of elements
|
||||
pointer.m_psAllocation->pData = reinterpret_cast<T*>(pAllocator->Alloc(nTotalSize));
|
||||
if (!pointer.m_psAllocation->pData)
|
||||
{
|
||||
core::XAllocFailed exception;
|
||||
exception.uiSize = static_cast<uint32_t>(nTotalSize);
|
||||
throw exception;
|
||||
}
|
||||
|
||||
// Call the constructors for each memory allocation
|
||||
if constexpr (std::is_scalar_v<T>)
|
||||
std::fill(pointer.m_psAllocation->pData, pointer.m_psAllocation->pData + nSize, static_cast<T>(0));
|
||||
else
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < nSize; nIndex++)
|
||||
new (pointer.m_psAllocation->pData + nIndex) T();
|
||||
}
|
||||
|
||||
// Fill in allocation details
|
||||
pointer.m_psAllocation->uiSize = static_cast<uint32_t>(nSize * sizeof(T));
|
||||
pointer.m_psAllocation->uiRefCnt = 1;
|
||||
return pointer;
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
template <typename TTraits /*= std::char_traits<char>*/>
|
||||
inline pointer<uint8_t> from_stream(std::basic_streambuf<char, TTraits>* pStreamBuf)
|
||||
{
|
||||
if (!pStreamBuf) throw sdv::XNullPointer();
|
||||
|
||||
// Determine the size of the buffer.
|
||||
std::streampos current_pos = pStreamBuf->pubseekoff(0, std::ios::cur, std::ios::in);
|
||||
std::streampos end_pos = pStreamBuf->pubseekoff(0, std::ios::end, std::ios::in);
|
||||
pStreamBuf->pubseekpos(current_pos, std::ios::in);
|
||||
|
||||
// Allocate the buffer
|
||||
pointer<uint8_t, 0> ptr;
|
||||
ptr.resize(end_pos);
|
||||
|
||||
// Fill the buffer
|
||||
size_t nPos = 0;
|
||||
while (true)
|
||||
{
|
||||
auto nAvail = pStreamBuf->in_avail();
|
||||
if (nAvail)
|
||||
{
|
||||
if (ptr.size() < nPos + nAvail)
|
||||
ptr.resize(nPos + nAvail);
|
||||
pStreamBuf->sgetn(reinterpret_cast<char*>(ptr.get() + nPos), nAvail);
|
||||
nPos += nAvail;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto nVal = pStreamBuf->sbumpc();
|
||||
if (nVal == TTraits::eof()) break;
|
||||
else
|
||||
{
|
||||
if (ptr.size() < nPos + 1)
|
||||
ptr.resize(nPos + 1);
|
||||
ptr[nPos] = static_cast<uint8_t>(nVal);
|
||||
nPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resize needed?
|
||||
if (nPos != ptr.size())
|
||||
ptr.resize(nPos);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename TTraits /*= std::char_traits<char>*/>
|
||||
inline void to_stream(const pointer<uint8_t>& rptr, std::basic_streambuf<char, TTraits>* pStreamBuf)
|
||||
{
|
||||
if (!pStreamBuf) throw sdv::XNullPointer();
|
||||
if (rptr.size())
|
||||
pStreamBuf->sputn(reinterpret_cast<const char*>(rptr.get()), rptr.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* cast(pointer<uint8_t>& rptr, size_t nOffset /*= 0*/)
|
||||
{
|
||||
if (nOffset + sizeof(T) > rptr.size()) return nullptr;
|
||||
return reinterpret_cast<T*>(rptr.get() + nOffset);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const T* cast(const pointer<uint8_t>& rptr, size_t nOffset /*= 0*/)
|
||||
{
|
||||
if (nOffset + sizeof(T) > rptr.size()) return nullptr;
|
||||
return reinterpret_cast<const T*>(rptr.get() + nOffset);
|
||||
}
|
||||
|
||||
} // namespace sdv
|
||||
/// @endcond
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // !defined SDV_PTR_INL
|
||||
464
export/support/pssup.h
Normal file
464
export/support/pssup.h
Normal file
@@ -0,0 +1,464 @@
|
||||
#ifndef SDV_PS_SUPPORT_H
|
||||
#define SDV_PS_SUPPORT_H
|
||||
|
||||
#include "../interfaces/core_ps.h"
|
||||
#include "../interfaces/serdes/core_ps_serdes.h"
|
||||
#include "../interfaces/serdes/core_types_serdes.h"
|
||||
|
||||
/**
|
||||
* @brief Compare two marshall IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is identical to the second ID.
|
||||
*/
|
||||
bool operator==(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare the marshall ID with zero.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] nVal The value to use for comparison (only 0 is allowed).
|
||||
* @return Returns whether the ID is zero.
|
||||
*/
|
||||
bool operator==(const sdv::ps::TMarshallID& rtID1, size_t nVal);
|
||||
|
||||
/**
|
||||
* @brief Compare the marshall ID with zero.
|
||||
* @param[in] nVal The value to use for comparison (only 0 is allowed).
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the ID is zero.
|
||||
*/
|
||||
bool operator==(size_t nVal, const sdv::ps::TMarshallID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two marshall IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is different from the second ID.
|
||||
*/
|
||||
bool operator!=(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare the marshall ID with zero.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] nVal The value to use for comparison (only 0 is allowed).
|
||||
* @return Returns whether the ID is not zero.
|
||||
*/
|
||||
bool operator!=(const sdv::ps::TMarshallID& rtID1, size_t nVal);
|
||||
|
||||
/**
|
||||
* @brief Compare the marshall ID with zero.
|
||||
* @param[in] nVal The value to use for comparison (only 0 is allowed).
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the ID is not zero.
|
||||
*/
|
||||
bool operator!=(size_t nVal, const sdv::ps::TMarshallID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two marshall IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is smaller than the second ID.
|
||||
*/
|
||||
bool operator<(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two marshall IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is smaller or equal the than second ID.
|
||||
*/
|
||||
bool operator<=(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two marshall IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is larger than the second ID.
|
||||
*/
|
||||
bool operator>(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two marshall IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is larger or equal than the second ID.
|
||||
*/
|
||||
bool operator>=(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Check for validity of the marshall ID.
|
||||
* @param[in] rtID Reference to the ID.
|
||||
* @return Returns whether the ID is valid.
|
||||
*/
|
||||
bool operator!(const sdv::ps::TMarshallID& rtID);
|
||||
|
||||
#ifndef DOXYGEN_IGNORE
|
||||
/**
|
||||
* @brief Specialization of std::less for sdv::ps::TMarshallID.
|
||||
*/
|
||||
template <>
|
||||
struct std::less<sdv::ps::TMarshallID>
|
||||
{
|
||||
/// The result type
|
||||
using result_type = bool;
|
||||
|
||||
/// The first argument type.
|
||||
using first_argument_type = sdv::ps::TMarshallID;
|
||||
|
||||
/// The second argument type.
|
||||
using second_argument_type = sdv::ps::TMarshallID;
|
||||
|
||||
/**
|
||||
* @brief Compare ID1 < ID2.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Result of the comparison.
|
||||
*/
|
||||
bool operator()(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2) const { return ::operator<(rtID1, rtID2); }
|
||||
};
|
||||
#endif // !defined DOXYGEN_IGNORE
|
||||
|
||||
/**
|
||||
* @brief Compare two connection IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is identical to the second ID.
|
||||
*/
|
||||
bool operator==(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare the connection ID with zero.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] nVal The value to use for comparison (only 0 is allowed).
|
||||
* @return Returns whether the ID is zero.
|
||||
*/
|
||||
bool operator==(const sdv::com::TConnectionID& rtID1, size_t nVal);
|
||||
|
||||
/**
|
||||
* @brief Compare the connection ID with zero.
|
||||
* @param[in] nVal The value to use for comparison (only 0 is allowed).
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the ID is zero.
|
||||
*/
|
||||
bool operator==(size_t nVal, const sdv::com::TConnectionID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two connection IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is different from the second ID.
|
||||
*/
|
||||
bool operator!=(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare the connection ID with zero.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] nVal The value to use for comparison (only 0 is allowed).
|
||||
* @return Returns whether the ID is not zero.
|
||||
*/
|
||||
bool operator!=(const sdv::com::TConnectionID& rtID1, size_t nVal);
|
||||
|
||||
/**
|
||||
* @brief Compare the connection ID with zero.
|
||||
* @param[in] nVal The value to use for comparison (only 0 is allowed).
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the ID is not zero.
|
||||
*/
|
||||
bool operator!=(size_t nVal, const sdv::com::TConnectionID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two connection IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is smaller than the second ID.
|
||||
*/
|
||||
bool operator<(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two connection IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is smaller or equal the than second ID.
|
||||
*/
|
||||
bool operator<=(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two connection IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is larger than the second ID.
|
||||
*/
|
||||
bool operator>(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Compare two connection IDs.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Returns whether the first ID is larger or equal than the second ID.
|
||||
*/
|
||||
bool operator>=(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2);
|
||||
|
||||
/**
|
||||
* @brief Check for validity of the connection ID.
|
||||
* @param[in] rtID Reference to the ID.
|
||||
* @return Returns whether the ID is valid.
|
||||
*/
|
||||
bool operator!(const sdv::com::TConnectionID& rtID);
|
||||
|
||||
#ifndef DOXYGEN_IGNORE
|
||||
/**
|
||||
* @brief Specialization of std::less for sdv::com::TConnectionID.
|
||||
*/
|
||||
template <>
|
||||
struct std::less<sdv::com::TConnectionID>
|
||||
{
|
||||
/// The result type
|
||||
using result_type = bool;
|
||||
|
||||
/// The first argument type.
|
||||
using first_argument_type = sdv::com::TConnectionID;
|
||||
|
||||
/// The second argument type.
|
||||
using second_argument_type = sdv::com::TConnectionID;
|
||||
|
||||
/**
|
||||
* @brief Compare ID1 < ID2.
|
||||
* @param[in] rtID1 Reference to the first ID.
|
||||
* @param[in] rtID2 Reference to the second ID.
|
||||
* @return Result of the comparison.
|
||||
*/
|
||||
bool operator()(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2) const { return ::operator<(rtID1, rtID2); }
|
||||
};
|
||||
#endif // !defined DOXYGEN_IGNORE
|
||||
|
||||
#include "sequence.h"
|
||||
#include "pointer.h"
|
||||
#include "crc.h"
|
||||
#include "component_impl.h"
|
||||
#include <cassert>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
namespace ps
|
||||
{
|
||||
/**
|
||||
* Local SMarshall structure to handle specific CRC calculations
|
||||
*/
|
||||
struct SMarshallLocal : SMarshall
|
||||
{};
|
||||
|
||||
/**
|
||||
* @brief Bypass class available during a function call. This class uses thread local storage to allow the storage of
|
||||
* raw data bypassing the serialization.
|
||||
*/
|
||||
class CRawDataBypass
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
CRawDataBypass();
|
||||
|
||||
/**
|
||||
* @brief Add raw data to the raw data queue.
|
||||
* @param[in] rptrData Reference to the smart pointer holding the data.
|
||||
*/
|
||||
void push(const pointer<uint8_t>& rptrData);
|
||||
|
||||
/**
|
||||
* @brief Prop the data from the raw data queue.
|
||||
* @return The data to pop.
|
||||
*/
|
||||
pointer<uint8_t> pop();
|
||||
|
||||
/**
|
||||
* @brief Is the raw data queue empty?
|
||||
* @return Returns whether the queue is empty.
|
||||
*/
|
||||
bool empty() const;
|
||||
|
||||
/**
|
||||
* @brief Clear the raw data queue.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::queue<pointer<uint8_t>> m_queueBypassData; ///< Additional buffers not being serialized.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Global access function for the raw data bypass.
|
||||
* @return Reference to the bypass.
|
||||
*/
|
||||
CRawDataBypass& GetRawDataBypass();
|
||||
|
||||
/**
|
||||
* @brief Result enumeration of the call function.
|
||||
*/
|
||||
enum class ECallResult : uint32_t
|
||||
{
|
||||
result_ok = 0, ///< Normal processing. The return buffer contains the return values.
|
||||
result_exception = 1, ///< Exception occurred. The return buffer contains the serialized exception.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Proxy class managing the function calls and incoming calls containing the response.
|
||||
* @tparam TInterface The interface the deriving class is deriving from as well.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
class CProxyHandler : public sdv::CSdvObject, public IMarshallObjectIdent, public IMarshallLink
|
||||
{
|
||||
public:
|
||||
// Ensure that the EEndian structure is 8 bits (to prevent byte swapping during detection).
|
||||
static_assert(sizeof(EEndian) == 1);
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
CProxyHandler();
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
virtual ~CProxyHandler() override;
|
||||
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_CHAIN_BASE(sdv::CSdvObject)
|
||||
SDV_INTERFACE_ENTRY(IMarshallObjectIdent)
|
||||
SDV_INTERFACE_ENTRY(IMarshallLink)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
// Object class type
|
||||
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Proxy)
|
||||
|
||||
/**
|
||||
* @brief Set the identification. Overload of IMarshallObjectIdent::SetIdentification.
|
||||
* @param[in] tMarshallID Reference to the marshall object ID. For a proxy object, this is the proxy ID. For a stub object
|
||||
* this is a stub ID.
|
||||
*/
|
||||
virtual void SetIdentification(/*in*/ const TMarshallID& tMarshallID) override;
|
||||
|
||||
/**
|
||||
* @brief Link the communication interface to the object. Overload of IMarshallLink::Link.
|
||||
* @remarks Only one link can exists at the time.
|
||||
* @param[in] pMarshall Interface to be linked.
|
||||
*/
|
||||
virtual void Link(/*in*/ IMarshall* pMarshall) override;
|
||||
|
||||
/**
|
||||
* @brief Unlink the linked interface. Overload of IMarshallLink::Unlink.
|
||||
*/
|
||||
virtual void Unlink() override;
|
||||
|
||||
/**
|
||||
* @brief Schedule a call.
|
||||
* @param[in] uiFuncIndex Operation/attribute index.
|
||||
* @param[in] rserInput Serializer containing the input parameters.
|
||||
* @param[in] rdesOutput Deserializer containing the return value and output parameters or the exception.
|
||||
* @return The call result value.
|
||||
*/
|
||||
ECallResult DoCall(uint32_t uiFuncIndex, const serializer<GetPlatformEndianess()>& rserInput,
|
||||
deserializer<GetPlatformEndianess()>& rdesOutput);
|
||||
|
||||
private:
|
||||
IMarshall* m_pRequest = nullptr; ///< Marshall interface for call requests.
|
||||
TMarshallID m_tProxyID = {}; ///< Proxy handler ID.
|
||||
TMarshallID m_tStubID = {}; ///< Stub handler ID.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Stub class managing incoming calls containing the request and dispatching them to the functions.
|
||||
* @tparam TInterface The interface this stub is dispatching to.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
class CStubHandler : public sdv::CSdvObject, public IMarshallObjectIdent, public IMarshall
|
||||
{
|
||||
// Ensure that the EEndian structure is 8 bits (to prevent byte swapping during detection).
|
||||
static_assert(sizeof(EEndian) == 1);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
CStubHandler();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CStubHandler() override;
|
||||
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_CHAIN_BASE(sdv::CSdvObject)
|
||||
SDV_INTERFACE_ENTRY(IMarshallObjectIdent)
|
||||
SDV_INTERFACE_ENTRY(IMarshall)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
// Object class type
|
||||
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Stub)
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Dispatch function type. Function arguments are endianness, input parameters and output
|
||||
* parameters/return value/exception information. Function returns the dispact result.
|
||||
*/
|
||||
typedef std::function<ECallResult(EEndian, const pointer<uint8_t>&, pointer<uint8_t>&)> FNDispatch;
|
||||
|
||||
/**
|
||||
* @brief Register dispatch function.
|
||||
* @remarks This dispatch functions must be registered in the correct order.
|
||||
* @attention Registering dispatch functions should happen during construction. No protection of the vector is
|
||||
* available during data dispatching.
|
||||
* @param[in] fnDispatch Dispatch function to call for this interface.
|
||||
*/
|
||||
void RegisterDispatchFunc(FNDispatch fnDispatch);
|
||||
|
||||
/**
|
||||
* @brief Serialize exception helper function.
|
||||
* @tparam TExcept The exception type to serialize.
|
||||
* @param[in] eEndian The endianness of the serialization.
|
||||
* @param[in] rexcept Reference to the exception.
|
||||
* @return The serialized exception.
|
||||
*/
|
||||
template <typename TExcept>
|
||||
pointer<uint8_t> SerializeException(EEndian eEndian, const TExcept& rexcept);
|
||||
|
||||
/**
|
||||
* @brief Set the identification. Overload of IMarshallObjectIdent::SetIdentification.
|
||||
* @param[in] tMarshallID Reference to The marshall object ID. For a proxy object, this is the proxy ID. For a stub object
|
||||
* this is a stub ID.
|
||||
*/
|
||||
virtual void SetIdentification(/*in*/ const TMarshallID& tMarshallID) override;
|
||||
|
||||
/**
|
||||
* @brief Marshall a function call. Overload of IMarshall::Call.
|
||||
* @remarks This function call is synchronous and does not return until the call has been finalized or a timeout
|
||||
* exception has occurred.
|
||||
* @remarks The sequence contains all data to make the call. It is important that the data in the sequence is
|
||||
* complete and in the correct order.
|
||||
* @param[inout] seqInputData Reference to sequence of input data pointers. The first data pointer contains the
|
||||
* marshalling header. The second contains the parameters (if available) and the others contain raw data pointers
|
||||
* (if available). The call is allowed to change the sequence to be able to add additional information during the
|
||||
* communication without having to copy the existing data.
|
||||
* @return Sequence of output data pointers. The first data pointer contains the marshalling header. The second
|
||||
* contains the return value and parameters (if available) and the others contain raw data pointers (if available).
|
||||
*/
|
||||
virtual sequence<pointer<uint8_t>> Call(/*inout*/ sequence<pointer<uint8_t>>& seqInputData) override;
|
||||
|
||||
private:
|
||||
std::vector<FNDispatch> m_vecDispatch; ///< Vector containing the dispatch functions.
|
||||
TMarshallID m_tStubID{}; ///< Stub handler ID.
|
||||
};
|
||||
} // namespace ps
|
||||
} // namespace sdv
|
||||
|
||||
#include "pssup.inl"
|
||||
|
||||
#endif // !defined(SDV_PS_SUPPORT_H)
|
||||
999
export/support/pssup.inl
Normal file
999
export/support/pssup.inl
Normal file
@@ -0,0 +1,999 @@
|
||||
#ifndef SDV_PS_SUPPORT_INL
|
||||
#define SDV_PS_SUPPORT_INL
|
||||
|
||||
#ifndef SDV_PS_SUPPORT_H
|
||||
#error Do not include "pssup.inl" directly. Include "pssup.h" instead!
|
||||
#endif //!defined SDV_PS_SUPPORT_H
|
||||
|
||||
#include "../interfaces/core_ps.h"
|
||||
#include "../interfaces/serdes/core_ps_serdes.h"
|
||||
#include "../interfaces/serdes/core_types_serdes.h"
|
||||
#include "sequence.h"
|
||||
#include "pointer.h"
|
||||
#include "crc.h"
|
||||
#include "component_impl.h"
|
||||
#include <cassert>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
|
||||
namespace serdes
|
||||
{
|
||||
/**
|
||||
* @brief Specialization of serializer/deserializer class for sdv::interface_t.
|
||||
*/
|
||||
template <>
|
||||
class CSerdes<sdv::interface_t>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Calculate the size of the value in serialized form.
|
||||
* @remarks Dependable on the size value, padding is added to align data.
|
||||
* @param[in] rifc Reference to the interface variable.
|
||||
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
||||
*/
|
||||
static void CalcSize(const sdv::interface_t& rifc, size_t& rnSize)
|
||||
{
|
||||
sdv::ser_size(rifc.id(), rnSize);
|
||||
sdv::ser_size(sdv::ps::TMarshallID(), rnSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the variable into the serializer.
|
||||
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @param[in] rSerializer Reference to the serializer.
|
||||
* @param[in] rifc Reference to the variable.
|
||||
* @return Reference to the serializer.
|
||||
*/
|
||||
template <sdv::EEndian eTargetEndianess>
|
||||
static sdv::serializer<eTargetEndianess>& Serialize(sdv::serializer<eTargetEndianess>& rSerializer,
|
||||
const sdv::interface_t& rifc)
|
||||
{
|
||||
// Get interface to the component isolation service.
|
||||
auto ptrComControl = sdv::core::GetObject("CommunicationControl");
|
||||
if (!ptrComControl) throw sdv::ps::XMarshallNotInitialized{};
|
||||
sdv::ps::IMarshallAccess* pMarshallAccess = ptrComControl.GetInterface<sdv::ps::IMarshallAccess>();
|
||||
if (!pMarshallAccess) throw sdv::ps::XMarshallNotInitialized{};
|
||||
|
||||
// Serialize the interface ID first
|
||||
rSerializer << rifc.id();
|
||||
|
||||
// Create and serialize a stub object for the interface.
|
||||
sdv::ps::TMarshallID tStubID = pMarshallAccess->GetStub(rifc);
|
||||
rSerializer << tStubID;
|
||||
|
||||
return rSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream a variable from the deserializer.
|
||||
* @tparam eSourceEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @param[in] rDeserializer Reference to the deserializer.
|
||||
* @param[out] rifc Reference to the variable to be filled.
|
||||
* @return Reference to the deserializer.
|
||||
*/
|
||||
template <sdv::EEndian eSourceEndianess>
|
||||
static sdv::deserializer<eSourceEndianess>& Deserialize(sdv::deserializer<eSourceEndianess>& rDeserializer,
|
||||
sdv::interface_t& rifc)
|
||||
{
|
||||
// Get interface to the component isolation service.
|
||||
auto ptrComControl = sdv::core::GetObject("CommunicationControl");
|
||||
if (!ptrComControl) throw sdv::ps::XMarshallNotInitialized{};
|
||||
sdv::ps::IMarshallAccess* pMarshallAccess = ptrComControl.GetInterface<sdv::ps::IMarshallAccess>();
|
||||
if (!pMarshallAccess) throw sdv::ps::XMarshallNotInitialized{};
|
||||
|
||||
// Get the interface ID
|
||||
sdv::interface_id id = 0;
|
||||
rDeserializer >> id;
|
||||
|
||||
// Get the stub ID
|
||||
sdv::ps::TMarshallID tStubID{};
|
||||
rDeserializer >> tStubID;
|
||||
|
||||
// Create the proxy
|
||||
if (!tStubID && !id) // In case the ID is zero, an NULL interface was sent.
|
||||
rifc = {};
|
||||
else
|
||||
rifc = pMarshallAccess->GetProxy(tStubID, id);
|
||||
|
||||
return rDeserializer;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specialization of serializer/deserializer class for sdv::any_t.
|
||||
*/
|
||||
template <>
|
||||
class CSerdes<sdv::any_t>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Calculate the size of the value in serialized form.
|
||||
* @remarks Dependable on the size value, padding is added to align data.
|
||||
* @param[in] rany Reference to the variable.
|
||||
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
||||
*/
|
||||
static void CalcSize(const sdv::any_t& rany, size_t& rnSize)
|
||||
{
|
||||
// The size of the type
|
||||
sdv::ser_size(rany.eValType, rnSize);
|
||||
|
||||
// Added with the size of the variable.
|
||||
switch (rany.eValType)
|
||||
{
|
||||
case sdv::any_t::EValType::val_type_bool: sdv::ser_size(rany.bVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_int8: sdv::ser_size(rany.i8Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_uint8: sdv::ser_size(rany.ui8Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_int16: sdv::ser_size(rany.i16Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_uint16: sdv::ser_size(rany.ui16Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_int32: sdv::ser_size(rany.i32Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_uint32: sdv::ser_size(rany.ui32Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_int64: sdv::ser_size(rany.i64Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_uint64: sdv::ser_size(rany.ui64Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_char: sdv::ser_size(rany.cVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_char16: sdv::ser_size(rany.c16Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_char32: sdv::ser_size(rany.c32Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_wchar: sdv::ser_size(rany.cwVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_float: sdv::ser_size(rany.fVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_double: sdv::ser_size(rany.dVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_long_double: sdv::ser_size(rany.ldVal, rnSize); break;
|
||||
//case sdv::any_t::EValType::val_type_fixed: sdv::ser_size(rany.fixVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_string: sdv::ser_size(rany.ssVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_u8string: sdv::ser_size(rany.ss8Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_u16string: sdv::ser_size(rany.ss16Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_u32string: sdv::ser_size(rany.ss32Val, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_wstring: sdv::ser_size(rany.sswVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_interface: sdv::ser_size(rany.ifcVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_interface_id: sdv::ser_size(rany.idIfcVal, rnSize); break;
|
||||
case sdv::any_t::EValType::val_type_exception_id: sdv::ser_size(rany.idExceptVal, rnSize); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the variable into the serializer.
|
||||
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @param[in] rSerializer Reference to the serializer.
|
||||
* @param[in] rany Reference to the variable.
|
||||
* @return Reference to the serializer.
|
||||
*/
|
||||
template <sdv::EEndian eTargetEndianess>
|
||||
static sdv::serializer<eTargetEndianess>& Serialize(sdv::serializer<eTargetEndianess>& rSerializer, const sdv::any_t& rany)
|
||||
{
|
||||
// Serialize the type first
|
||||
rSerializer << rany.eValType;
|
||||
|
||||
// Serialize the data
|
||||
switch (rany.eValType)
|
||||
{
|
||||
case sdv::any_t::EValType::val_type_bool: rSerializer << rany.bVal; break;
|
||||
case sdv::any_t::EValType::val_type_int8: rSerializer << rany.i8Val; break;
|
||||
case sdv::any_t::EValType::val_type_uint8: rSerializer << rany.ui8Val; break;
|
||||
case sdv::any_t::EValType::val_type_int16: rSerializer << rany.i16Val; break;
|
||||
case sdv::any_t::EValType::val_type_uint16: rSerializer << rany.ui16Val; break;
|
||||
case sdv::any_t::EValType::val_type_int32: rSerializer << rany.i32Val; break;
|
||||
case sdv::any_t::EValType::val_type_uint32: rSerializer << rany.ui32Val; break;
|
||||
case sdv::any_t::EValType::val_type_int64: rSerializer << rany.i64Val; break;
|
||||
case sdv::any_t::EValType::val_type_uint64: rSerializer << rany.ui64Val; break;
|
||||
case sdv::any_t::EValType::val_type_char: rSerializer << rany.cVal; break;
|
||||
case sdv::any_t::EValType::val_type_char16: rSerializer << rany.c16Val; break;
|
||||
case sdv::any_t::EValType::val_type_char32: rSerializer << rany.c32Val; break;
|
||||
case sdv::any_t::EValType::val_type_wchar: rSerializer << rany.cwVal; break;
|
||||
case sdv::any_t::EValType::val_type_float: rSerializer << rany.fVal; break;
|
||||
case sdv::any_t::EValType::val_type_double: rSerializer << rany.dVal; break;
|
||||
case sdv::any_t::EValType::val_type_long_double: rSerializer << rany.ldVal; break;
|
||||
//case sdv::any_t::EValType::val_type_fixed: rSerializer << rany.fixVal; break;
|
||||
case sdv::any_t::EValType::val_type_string: rSerializer << rany.ssVal; break;
|
||||
case sdv::any_t::EValType::val_type_u8string: rSerializer << rany.ss8Val; break;
|
||||
case sdv::any_t::EValType::val_type_u16string: rSerializer << rany.ss16Val; break;
|
||||
case sdv::any_t::EValType::val_type_u32string: rSerializer << rany.ss32Val; break;
|
||||
case sdv::any_t::EValType::val_type_wstring: rSerializer << rany.sswVal; break;
|
||||
case sdv::any_t::EValType::val_type_interface: rSerializer << rany.ifcVal; break;
|
||||
case sdv::any_t::EValType::val_type_interface_id: rSerializer << rany.idIfcVal; break;
|
||||
case sdv::any_t::EValType::val_type_exception_id: rSerializer << rany.idExceptVal; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return rSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream a variable from the deserializer.
|
||||
* @tparam eSourceEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @param[in] rDeserializer Reference to the deserializer.
|
||||
* @param[out] rany Reference to the variable to be filled.
|
||||
* @return Reference to the deserializer.
|
||||
*/
|
||||
template <sdv::EEndian eSourceEndianess>
|
||||
static sdv::deserializer<eSourceEndianess>& Deserialize(sdv::deserializer<eSourceEndianess>& rDeserializer, sdv::any_t& rany)
|
||||
{
|
||||
rany.clear();
|
||||
|
||||
// Deserialize the type first
|
||||
rDeserializer >> rany.eValType;
|
||||
|
||||
// Serialize the data
|
||||
switch (rany.eValType)
|
||||
{
|
||||
case sdv::any_t::EValType::val_type_bool: rDeserializer >> rany.bVal; break;
|
||||
case sdv::any_t::EValType::val_type_int8: rDeserializer >> rany.i8Val; break;
|
||||
case sdv::any_t::EValType::val_type_uint8: rDeserializer >> rany.ui8Val; break;
|
||||
case sdv::any_t::EValType::val_type_int16: rDeserializer >> rany.i16Val; break;
|
||||
case sdv::any_t::EValType::val_type_uint16: rDeserializer >> rany.ui16Val; break;
|
||||
case sdv::any_t::EValType::val_type_int32: rDeserializer >> rany.i32Val; break;
|
||||
case sdv::any_t::EValType::val_type_uint32: rDeserializer >> rany.ui32Val; break;
|
||||
case sdv::any_t::EValType::val_type_int64: rDeserializer >> rany.i64Val; break;
|
||||
case sdv::any_t::EValType::val_type_uint64: rDeserializer >> rany.ui64Val; break;
|
||||
case sdv::any_t::EValType::val_type_char: rDeserializer >> rany.cVal; break;
|
||||
case sdv::any_t::EValType::val_type_char16: rDeserializer >> rany.c16Val; break;
|
||||
case sdv::any_t::EValType::val_type_char32: rDeserializer >> rany.c32Val; break;
|
||||
case sdv::any_t::EValType::val_type_wchar: rDeserializer >> rany.cwVal; break;
|
||||
case sdv::any_t::EValType::val_type_float: rDeserializer >> rany.fVal; break;
|
||||
case sdv::any_t::EValType::val_type_double: rDeserializer >> rany.dVal; break;
|
||||
case sdv::any_t::EValType::val_type_long_double: rDeserializer >> rany.ldVal; break;
|
||||
//case sdv::any_t::EValType::val_type_fixed: new (&rany.fixVal) sdv::fixed; rDeserializer >> rany.fixVal; break;
|
||||
case sdv::any_t::EValType::val_type_string: new (&rany.ssVal) sdv::string; rDeserializer >> rany.ssVal; break;
|
||||
case sdv::any_t::EValType::val_type_u8string: new (&rany.ss8Val) sdv::u8string; rDeserializer >> rany.ss8Val; break;
|
||||
case sdv::any_t::EValType::val_type_u16string: new (&rany.ss16Val) sdv::u16string; rDeserializer >> rany.ss16Val; break;
|
||||
case sdv::any_t::EValType::val_type_u32string: new (&rany.ss32Val) sdv::u32string; rDeserializer >> rany.ss32Val; break;
|
||||
case sdv::any_t::EValType::val_type_wstring: new (&rany.sswVal) sdv::wstring; rDeserializer >> rany.sswVal; break;
|
||||
case sdv::any_t::EValType::val_type_interface: new (&rany.ifcVal) sdv::interface_t; rDeserializer >> rany.ifcVal; break;
|
||||
case sdv::any_t::EValType::val_type_interface_id: rDeserializer >> rany.idIfcVal; break;
|
||||
case sdv::any_t::EValType::val_type_exception_id: rDeserializer >> rany.idExceptVal; break;
|
||||
default: rany.eValType = sdv::any_t::EValType::val_type_empty; break;
|
||||
}
|
||||
|
||||
return rDeserializer;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specialization of serializer/deserializer class for sdv::ps::SMarshallLocal.
|
||||
*/
|
||||
template <>
|
||||
class CSerdes<sdv::ps::SMarshallLocal>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Calculate the size of the value in serialized form.
|
||||
* @remarks Dependable on the size value, padding is added to align data.
|
||||
* @param[in] rsValue Reference to the variable.
|
||||
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
||||
*/
|
||||
static void CalcSize(const sdv::ps::SMarshallLocal& rsValue, size_t& rnSize)
|
||||
{
|
||||
sdv::ser_size(rsValue.eEndian, rnSize);
|
||||
sdv::ser_size(rsValue.uiVersion, rnSize);
|
||||
sdv::ser_size(rsValue.tIfcId, rnSize);
|
||||
sdv::ser_size(rsValue.uiFuncIndex, rnSize);
|
||||
sdv::ser_size(rsValue.uiFlags, rnSize);
|
||||
sdv::ser_size(rsValue.seqChecksums, rnSize);
|
||||
sdv::ser_size(rsValue.uiHdrChecksum, rnSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the variable into the serializer.
|
||||
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @param[in] rSerializer Reference to the serializer.
|
||||
* @param[in] rsValue Reference to the variable.
|
||||
* @return Reference to the serializer.
|
||||
*/
|
||||
template <sdv::EEndian eTargetEndianess>
|
||||
static sdv::serializer<eTargetEndianess>& Serialize(sdv::serializer<eTargetEndianess>& rSerializer,
|
||||
sdv::ps::SMarshallLocal& rsValue)
|
||||
{
|
||||
// Stream the initial parameters.
|
||||
rSerializer << rsValue.eEndian;
|
||||
rSerializer << rsValue.uiVersion;
|
||||
rSerializer << rsValue.tIfcId;
|
||||
rSerializer << rsValue.uiFuncIndex;
|
||||
rSerializer << rsValue.uiFlags;
|
||||
rSerializer << rsValue.seqChecksums;
|
||||
|
||||
// Get the currently calculated checksum and store the checksum.
|
||||
rsValue.uiHdrChecksum = rSerializer.checksum();
|
||||
|
||||
// Stream the checksum.
|
||||
rSerializer << rsValue.uiHdrChecksum;
|
||||
|
||||
return rSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream a variable from the deserializer.
|
||||
* @tparam eSourceEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @param[in] rDeserializer Reference to the deserializer.
|
||||
* @param[out] rsValue Reference to the variable to be filled.
|
||||
* @return Reference to the deserializer.
|
||||
*/
|
||||
template <sdv::EEndian eSourceEndianess>
|
||||
static sdv::deserializer<eSourceEndianess>& Deserialize(sdv::deserializer<eSourceEndianess>& rDeserializer,
|
||||
sdv::ps::SMarshallLocal& rsValue)
|
||||
{
|
||||
// Stream the initial parameters.
|
||||
rDeserializer >> rsValue.eEndian;
|
||||
rDeserializer >> rsValue.uiVersion;
|
||||
|
||||
// Continue only when the version is corresponding with the interface version (otherwise the order might be
|
||||
// mixed up).
|
||||
if (rsValue.uiVersion == SDVFrameworkInterfaceVersion)
|
||||
{
|
||||
rDeserializer >> rsValue.tIfcId;
|
||||
rDeserializer >> rsValue.uiFuncIndex;
|
||||
rDeserializer >> rsValue.uiFlags;
|
||||
rDeserializer >> rsValue.seqChecksums;
|
||||
rDeserializer >> rsValue.uiHdrChecksum;
|
||||
}
|
||||
|
||||
return rDeserializer;
|
||||
}
|
||||
};
|
||||
} // namespace serdes
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
namespace ps
|
||||
{
|
||||
inline CRawDataBypass::CRawDataBypass()
|
||||
{}
|
||||
|
||||
inline void CRawDataBypass::push(const pointer<uint8_t>& rptrData)
|
||||
{
|
||||
m_queueBypassData.push(rptrData);
|
||||
}
|
||||
|
||||
inline pointer<uint8_t> CRawDataBypass::pop()
|
||||
{
|
||||
pointer<uint8_t> ptrData = std::move(m_queueBypassData.front());
|
||||
m_queueBypassData.pop();
|
||||
return ptrData;
|
||||
}
|
||||
|
||||
inline bool CRawDataBypass::empty() const
|
||||
{
|
||||
return m_queueBypassData.empty();
|
||||
}
|
||||
|
||||
inline void CRawDataBypass::clear()
|
||||
{
|
||||
while (!m_queueBypassData.empty())
|
||||
m_queueBypassData.pop();
|
||||
}
|
||||
|
||||
inline CRawDataBypass& GetRawDataBypass()
|
||||
{
|
||||
thread_local static CRawDataBypass bypass;
|
||||
return bypass;
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline CProxyHandler<TInterface>::CProxyHandler()
|
||||
{}
|
||||
|
||||
template <typename TInterface>
|
||||
inline CProxyHandler<TInterface>::~CProxyHandler()
|
||||
{}
|
||||
|
||||
template <typename TInterface>
|
||||
inline void CProxyHandler<TInterface>::SetIdentification(/*in*/ const TMarshallID& tMarshallID)
|
||||
{
|
||||
m_tProxyID = tMarshallID;
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline void CProxyHandler<TInterface>::Link(/*in*/ IMarshall* pMarshall)
|
||||
{
|
||||
assert(pMarshall);
|
||||
m_pRequest = pMarshall;
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline void CProxyHandler<TInterface>::Unlink()
|
||||
{
|
||||
m_pRequest = nullptr;
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline ECallResult CProxyHandler<TInterface>::DoCall(uint32_t uiFuncIndex,
|
||||
const serializer<GetPlatformEndianess()>& rserInput, deserializer<GetPlatformEndianess()>& rdesOutput)
|
||||
{
|
||||
// Needs a valid request interface
|
||||
if (!m_pRequest) throw XMarshallNotInitialized{};
|
||||
|
||||
// The sequence holding the input data pointers
|
||||
sequence<pointer<uint8_t>> seqInputData;
|
||||
|
||||
// Fill the marshall packet
|
||||
SMarshallLocal sInputPacket{};
|
||||
sInputPacket.eEndian = GetPlatformEndianess();
|
||||
sInputPacket.uiVersion = SDVFrameworkInterfaceVersion;
|
||||
sInputPacket.tIfcId = TInterface::_id;
|
||||
sInputPacket.uiFuncIndex = uiFuncIndex;
|
||||
|
||||
// Are there any parameters?
|
||||
if (rserInput.buffer())
|
||||
{
|
||||
// Add the serialized parameters to the marshall sequence
|
||||
seqInputData.push_back(rserInput.buffer());
|
||||
sInputPacket.seqChecksums.push_back(rserInput.checksum());
|
||||
|
||||
// Add additional raw data
|
||||
while (!GetRawDataBypass().empty())
|
||||
{
|
||||
// Calculate the checksum
|
||||
crcCCITT_FALSE crc;
|
||||
pointer<uint8_t> ptrRawData = GetRawDataBypass().pop();
|
||||
crcCCITT_FALSE crcBypass;
|
||||
uint16_t uiChecksum = crcBypass.calc_checksum(ptrRawData.get(), ptrRawData.size());
|
||||
|
||||
// Add the raw data to the marshall sequence
|
||||
seqInputData.push_back(ptrRawData);
|
||||
sInputPacket.seqChecksums.push_back(uiChecksum);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an additional stream for the marshall struct.
|
||||
serializer serHdr;
|
||||
serdes::CSerdes<SMarshallLocal>::Serialize(serHdr, sInputPacket);
|
||||
|
||||
// Add the packet to the top of the pointer sequence.
|
||||
seqInputData.insert(seqInputData.begin(), serHdr.buffer());
|
||||
|
||||
// Call the request; this will update the sequence with result information
|
||||
sequence<pointer<uint8_t>> seqOutputData = m_pRequest->Call(seqInputData);
|
||||
if (seqOutputData.empty()) throw XMarshallMissingData{};
|
||||
|
||||
// The first data pointer in the sequence contains the marshall header
|
||||
pointer<uint8_t> ptrHeader = seqOutputData[0];
|
||||
if (!ptrHeader) throw ps::XMarshallMissingData{};
|
||||
|
||||
// And the first byte in the data pointer determines the endianess
|
||||
EEndian eSourceEndianess = static_cast<EEndian>(ptrHeader[0]);
|
||||
|
||||
// Deserialize the packet
|
||||
SMarshallLocal sOutputPacket{};
|
||||
if (eSourceEndianess == EEndian::big_endian)
|
||||
{
|
||||
deserializer<EEndian::big_endian> deserializer;
|
||||
deserializer.attach(ptrHeader, 0); // Do not check checksum...
|
||||
serdes::CSerdes<SMarshallLocal>::Deserialize(deserializer, sOutputPacket);
|
||||
} else
|
||||
{
|
||||
deserializer<EEndian::little_endian> deserializer;
|
||||
deserializer.attach(ptrHeader, 0); // Do not check checksum...
|
||||
serdes::CSerdes<SMarshallLocal>::Deserialize(deserializer, sOutputPacket);
|
||||
}
|
||||
|
||||
// Check the packet version... must fit, otherwise data misalignment might occur.
|
||||
if (sOutputPacket.uiVersion != SDVFrameworkInterfaceVersion) throw XMarshallVersion{};
|
||||
|
||||
// The checksum can be calculated by serializing the packet once more.
|
||||
uint16_t uiHdrChecksum = sOutputPacket.uiHdrChecksum;
|
||||
serializer serializer;
|
||||
serdes::CSerdes<SMarshallLocal>::Serialize(serializer, sOutputPacket);
|
||||
// Ignore cppcheck suppress warning is always false. The checksum is written into the packet again. If previously it
|
||||
// was different, this causes an integrity exception.
|
||||
// cppcheck-suppress knownConditionTrueFalse
|
||||
if (sOutputPacket.uiHdrChecksum != uiHdrChecksum)
|
||||
throw XMarshallIntegrity{};
|
||||
|
||||
// Check whether the result contains an exception
|
||||
if (sOutputPacket.uiFlags & static_cast<uint32_t>(sdv::ps::EMarshallFlags::exception_triggered))
|
||||
{
|
||||
// Check the checksum of the data
|
||||
if (seqOutputData.size() != 2) throw XMarshallIntegrity{};
|
||||
if (sOutputPacket.seqChecksums.size() != 1) throw XMarshallIntegrity{};
|
||||
crcCCITT_FALSE crc;
|
||||
if (crc.calc_checksum(seqOutputData[1].get(), seqOutputData[1].size()) != sOutputPacket.seqChecksums[0])
|
||||
throw XMarshallIntegrity{};
|
||||
|
||||
// Attach the data to the deserializer.
|
||||
rdesOutput.attach(seqOutputData[1]);
|
||||
|
||||
// Check for system and/or proxy-stub exceptions
|
||||
sdv::exception_id id = 0;
|
||||
rdesOutput.peek_front(id);
|
||||
switch(id)
|
||||
{
|
||||
case GetExceptionId<XNoInterface>():
|
||||
{
|
||||
XNoInterface exception;
|
||||
serdes::CSerdes<XNoInterface>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XIndexOutOfRange>():
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
serdes::CSerdes<XIndexOutOfRange>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XInvalidIterator>():
|
||||
{
|
||||
XInvalidIterator exception;
|
||||
serdes::CSerdes<XInvalidIterator>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XNullPointer>():
|
||||
{
|
||||
XNullPointer exception;
|
||||
serdes::CSerdes<XNullPointer>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XInvalidRefCount>():
|
||||
{
|
||||
XInvalidRefCount exception;
|
||||
serdes::CSerdes<XInvalidRefCount>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XBufferTooSmall>():
|
||||
{
|
||||
XBufferTooSmall exception;
|
||||
serdes::CSerdes<XBufferTooSmall>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XHashNotMatching>():
|
||||
{
|
||||
XHashNotMatching exception;
|
||||
serdes::CSerdes<XHashNotMatching>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XOffsetPastBufferSize>():
|
||||
{
|
||||
XOffsetPastBufferSize exception;
|
||||
serdes::CSerdes<XOffsetPastBufferSize>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XUnknownException>():
|
||||
{
|
||||
XUnknownException exception;
|
||||
serdes::CSerdes<XUnknownException>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XUnhandledException>():
|
||||
{
|
||||
XUnhandledException exception;
|
||||
serdes::CSerdes<XUnhandledException>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<core::XNoMemMgr>():
|
||||
{
|
||||
core::XNoMemMgr exception;
|
||||
serdes::CSerdes<core::XNoMemMgr>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<core::XAllocFailed>():
|
||||
{
|
||||
core::XAllocFailed exception;
|
||||
serdes::CSerdes<core::XAllocFailed>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XMarshallNotInitialized>():
|
||||
{
|
||||
XMarshallNotInitialized exception;
|
||||
serdes::CSerdes<XMarshallNotInitialized>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XMarshallTimeout>():
|
||||
{
|
||||
XMarshallTimeout exception;
|
||||
serdes::CSerdes<XMarshallTimeout>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XMarshallMissingData>():
|
||||
{
|
||||
XMarshallMissingData exception;
|
||||
serdes::CSerdes<XMarshallMissingData>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XMarshallVersion>():
|
||||
{
|
||||
XMarshallVersion exception;
|
||||
serdes::CSerdes<XMarshallVersion>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
case GetExceptionId<XMarshallIntegrity>():
|
||||
{
|
||||
XMarshallIntegrity exception;
|
||||
serdes::CSerdes<XMarshallIntegrity>::Deserialize(rdesOutput, exception);
|
||||
throw exception;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// No known exception, let the caller check whether it can handle the exception.
|
||||
return ECallResult::result_exception;
|
||||
}
|
||||
|
||||
// Check for packet integrity and add the raw data to the raw data bypass
|
||||
if (sOutputPacket.seqChecksums.size() != seqOutputData.size() - 1) throw XMarshallIntegrity{};
|
||||
size_t nChecksumIndex = 0;
|
||||
pointer<uint8_t> ptrParams;
|
||||
GetRawDataBypass().clear();
|
||||
for (auto itData = seqOutputData.begin() + 1; itData != seqOutputData.end(); itData++)
|
||||
{
|
||||
crcCCITT_FALSE crc;
|
||||
if (crc.calc_checksum(itData->get(), itData->size()) != sOutputPacket.seqChecksums[nChecksumIndex])
|
||||
throw XMarshallIntegrity{};
|
||||
if (nChecksumIndex)
|
||||
GetRawDataBypass().push(*itData);
|
||||
else
|
||||
ptrParams = *itData;
|
||||
nChecksumIndex++;
|
||||
}
|
||||
|
||||
// Return the deserialization object.
|
||||
if (ptrParams)
|
||||
rdesOutput.attach(ptrParams);
|
||||
return ECallResult::result_ok;
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline CStubHandler<TInterface>::CStubHandler()
|
||||
{}
|
||||
|
||||
template <typename TInterface>
|
||||
inline CStubHandler<TInterface>::~CStubHandler()
|
||||
{}
|
||||
|
||||
template <typename TInterface>
|
||||
inline void CStubHandler<TInterface>::RegisterDispatchFunc(FNDispatch fnDispatch)
|
||||
{
|
||||
m_vecDispatch.push_back(fnDispatch);
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
template <typename TExcept>
|
||||
inline pointer<uint8_t> CStubHandler<TInterface>::SerializeException(EEndian eEndian, const TExcept& rexcept)
|
||||
{
|
||||
GetRawDataBypass().clear(); // just in case
|
||||
if (eEndian == sdv::EEndian::big_endian)
|
||||
{
|
||||
sdv::serializer<sdv::EEndian::big_endian> serOutput;
|
||||
serdes::CSerdes<TExcept>::Serialize(serOutput, rexcept);
|
||||
return serOutput.buffer();
|
||||
} else
|
||||
{
|
||||
sdv::serializer<sdv::EEndian::little_endian> serOutput;
|
||||
serdes::CSerdes<TExcept>::Serialize(serOutput, rexcept);
|
||||
return serOutput.buffer();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline void CStubHandler<TInterface>::SetIdentification(/*in*/ const TMarshallID& tMarshallID)
|
||||
{
|
||||
m_tStubID = tMarshallID;
|
||||
}
|
||||
|
||||
template <typename TInterface>
|
||||
inline sequence<pointer<uint8_t>> CStubHandler<TInterface>::Call(/*inout*/ sequence<pointer<uint8_t>>& seqInputData)
|
||||
{
|
||||
if (seqInputData.empty()) throw XMarshallMissingData{};
|
||||
|
||||
// The first data pointer in the sequence contains the marshall header
|
||||
pointer<uint8_t> ptrHeader = seqInputData[0];
|
||||
if (!ptrHeader) throw ps::XMarshallMissingData{};
|
||||
|
||||
// And the first byte in the data pointer determines the endianess
|
||||
EEndian eSourceEndianess = static_cast<EEndian>(ptrHeader[0]);
|
||||
|
||||
// Deserialize the packet
|
||||
SMarshallLocal sInputPacket{};
|
||||
if (eSourceEndianess == EEndian::big_endian)
|
||||
{
|
||||
deserializer<EEndian::big_endian> desInput;
|
||||
desInput.attach(ptrHeader, 0); // Do not check checksum...
|
||||
serdes::CSerdes<SMarshallLocal>::Deserialize(desInput, sInputPacket);
|
||||
} else
|
||||
{
|
||||
deserializer<EEndian::little_endian> desInput;
|
||||
desInput.attach(ptrHeader, 0); // Do not check checksum...
|
||||
serdes::CSerdes<SMarshallLocal>::Deserialize(desInput, sInputPacket);
|
||||
}
|
||||
|
||||
// Check the packet version... must fit, otherwise data misalignment might occur.
|
||||
if (sInputPacket.uiVersion != SDVFrameworkInterfaceVersion) throw XMarshallVersion{};
|
||||
|
||||
// The checksum can be calculated by serializing the packet once more.
|
||||
uint16_t uiHdrChecksum = sInputPacket.uiHdrChecksum;
|
||||
serializer rserInput;
|
||||
serdes::CSerdes<SMarshallLocal>::Serialize(rserInput, sInputPacket);
|
||||
// Ignore cppcheck suppress warning is always false. The checksum is written into the packet again. If previously it
|
||||
// was different, this causes an integrity exception.
|
||||
// cppcheck-suppress knownConditionTrueFalse
|
||||
if (sInputPacket.uiHdrChecksum != uiHdrChecksum) throw XMarshallIntegrity{};
|
||||
|
||||
// Check for packet integrity and add the raw data to the raw data bypass
|
||||
if (sInputPacket.seqChecksums.size() != seqInputData.size() - 1) throw XMarshallIntegrity{};
|
||||
size_t nChecksumIndex = 0;
|
||||
pointer<uint8_t> ptrInputParams;
|
||||
GetRawDataBypass().clear();
|
||||
for (auto itData = seqInputData.begin() + 1; itData != seqInputData.end(); itData++)
|
||||
{
|
||||
crcCCITT_FALSE crc;
|
||||
if (crc.calc_checksum(itData->get(), itData->size()) != sInputPacket.seqChecksums[nChecksumIndex])
|
||||
throw XMarshallIntegrity{};
|
||||
if (nChecksumIndex)
|
||||
GetRawDataBypass().push(*itData);
|
||||
else
|
||||
ptrInputParams = *itData;
|
||||
nChecksumIndex++;
|
||||
}
|
||||
|
||||
// If any exception occured during the input processing, return the buffer without processing. This allows the
|
||||
// caller to receive the exception.
|
||||
if (sInputPacket.uiFlags & static_cast<uint32_t>(EMarshallFlags::exception_triggered))
|
||||
return seqInputData;
|
||||
|
||||
// Call dispatch function
|
||||
FNDispatch fnDispatch = m_vecDispatch[sInputPacket.uiFuncIndex];
|
||||
if (!fnDispatch) throw XMarshallNotInitialized{};
|
||||
pointer<uint8_t> ptrOutputParams;
|
||||
ECallResult eResult = ECallResult::result_ok;
|
||||
try
|
||||
{
|
||||
eResult = fnDispatch(eSourceEndianess, ptrInputParams, ptrOutputParams);
|
||||
} catch (const XNoInterface& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const XIndexOutOfRange& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const XInvalidIterator& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const XNullPointer& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const XInvalidRefCount& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const XBufferTooSmall& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const XHashNotMatching& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const XOffsetPastBufferSize& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const XUnknownException& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const XUnhandledException& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const core::XNoMemMgr& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (const core::XAllocFailed& rexcept)
|
||||
{
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, rexcept);
|
||||
eResult = ECallResult::result_exception;
|
||||
} catch (...)
|
||||
{
|
||||
XUnhandledException xUnhandled;
|
||||
ptrOutputParams = SerializeException(eSourceEndianess, xUnhandled);
|
||||
eResult = ECallResult::result_exception;
|
||||
}
|
||||
|
||||
// The sequence holding the output data pointers
|
||||
sequence<pointer<uint8_t>> seqOutputData;
|
||||
|
||||
// Fill the marshall packet
|
||||
SMarshallLocal sOutputPacket{};
|
||||
sOutputPacket.eEndian = eSourceEndianess;
|
||||
sOutputPacket.uiVersion = SDVFrameworkInterfaceVersion;
|
||||
sOutputPacket.tIfcId = TInterface::_id;
|
||||
sOutputPacket.uiFuncIndex = sInputPacket.uiFuncIndex;
|
||||
sOutputPacket.uiFlags = static_cast<uint32_t>(EMarshallFlags::direction_output);
|
||||
if (eResult == ECallResult::result_exception)
|
||||
sOutputPacket.uiFlags |= static_cast<uint32_t>(EMarshallFlags::exception_triggered);
|
||||
|
||||
// Are there any parameters?
|
||||
if (ptrOutputParams)
|
||||
{
|
||||
// Calculate the checksum
|
||||
crcCCITT_FALSE crc;
|
||||
uint16_t uiChecksum = crc.calc_checksum(ptrOutputParams.get(), ptrOutputParams.size());
|
||||
|
||||
// Add the serialized parameters to the marshall sequence
|
||||
seqOutputData.push_back(ptrOutputParams);
|
||||
sOutputPacket.seqChecksums.push_back(uiChecksum);
|
||||
|
||||
// Add additional raw data
|
||||
while (!GetRawDataBypass().empty())
|
||||
{
|
||||
// Calculate the checksum
|
||||
pointer<uint8_t> ptrRawData = GetRawDataBypass().pop();
|
||||
crcCCITT_FALSE crcBypass;
|
||||
uiChecksum = crcBypass.calc_checksum(ptrRawData.get(), ptrRawData.size());
|
||||
|
||||
// Add the raw data to the marshall sequence
|
||||
seqOutputData.push_back(ptrRawData);
|
||||
sOutputPacket.seqChecksums.push_back(uiChecksum);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an additional stream for the marshall struct.
|
||||
serializer serHdr;
|
||||
serdes::CSerdes<SMarshallLocal>::Serialize(serHdr, sOutputPacket);
|
||||
|
||||
// Add the packet to the top of the pointer sequence.
|
||||
seqOutputData.insert(seqOutputData.begin(), serHdr.buffer());
|
||||
|
||||
return seqOutputData;
|
||||
}
|
||||
} // namespace ps
|
||||
} // namespace sdv
|
||||
|
||||
inline bool operator==(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2)
|
||||
{
|
||||
if (rtID1.uiHostID != rtID2.uiHostID) return false;
|
||||
if (rtID1.tProcessID != rtID2.tProcessID) return false;
|
||||
if (rtID1.uiIdent != rtID2.uiIdent) return false;
|
||||
if (rtID1.uiControl != rtID2.uiControl) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator==(const sdv::ps::TMarshallID& rtID1, size_t nVal)
|
||||
{
|
||||
if (nVal) return false;
|
||||
return operator==(rtID1, sdv::ps::TMarshallID{});
|
||||
}
|
||||
|
||||
inline bool operator==(size_t nVal, const sdv::ps::TMarshallID& rtID2)
|
||||
{
|
||||
if (nVal) return false;
|
||||
return operator==(sdv::ps::TMarshallID{}, rtID2);
|
||||
}
|
||||
|
||||
inline bool operator!=(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2)
|
||||
{
|
||||
return !operator==(rtID1, rtID2);
|
||||
}
|
||||
|
||||
inline bool operator!=(const sdv::ps::TMarshallID& rtID1, size_t nVal)
|
||||
{
|
||||
if (nVal) return true;
|
||||
return !operator==(rtID1, sdv::ps::TMarshallID{});
|
||||
}
|
||||
|
||||
inline bool operator!=(size_t nVal, const sdv::ps::TMarshallID& rtID2)
|
||||
{
|
||||
if (nVal) return true;
|
||||
return !operator==(sdv::ps::TMarshallID{}, rtID2);
|
||||
}
|
||||
|
||||
inline bool operator<(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2)
|
||||
{
|
||||
if (rtID1.uiHostID < rtID2.uiHostID) return true;
|
||||
if (rtID1.uiHostID > rtID2.uiHostID) return false;
|
||||
if (rtID1.tProcessID < rtID2.tProcessID) return true;
|
||||
if (rtID1.tProcessID > rtID2.tProcessID) return false;
|
||||
if (rtID1.uiIdent < rtID2.uiIdent) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator<=(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2)
|
||||
{
|
||||
if (rtID1.uiHostID < rtID2.uiHostID) return true;
|
||||
if (rtID1.uiHostID > rtID2.uiHostID) return false;
|
||||
if (rtID1.tProcessID < rtID2.tProcessID) return true;
|
||||
if (rtID1.tProcessID > rtID2.tProcessID) return false;
|
||||
if (rtID1.uiIdent < rtID2.uiIdent) return true;
|
||||
if (rtID1.uiControl == rtID2.uiControl) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator>(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2)
|
||||
{
|
||||
if (rtID1.uiHostID > rtID2.uiHostID) return true;
|
||||
if (rtID1.uiHostID < rtID2.uiHostID) return false;
|
||||
if (rtID1.tProcessID > rtID2.tProcessID) return true;
|
||||
if (rtID1.tProcessID < rtID2.tProcessID) return false;
|
||||
if (rtID1.uiIdent > rtID2.uiIdent) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator>=(const sdv::ps::TMarshallID& rtID1, const sdv::ps::TMarshallID& rtID2)
|
||||
{
|
||||
if (rtID1.uiHostID > rtID2.uiHostID) return true;
|
||||
if (rtID1.uiHostID < rtID2.uiHostID) return false;
|
||||
if (rtID1.tProcessID > rtID2.tProcessID) return true;
|
||||
if (rtID1.tProcessID < rtID2.tProcessID) return false;
|
||||
if (rtID1.uiIdent > rtID2.uiIdent) return true;
|
||||
if (rtID1.uiControl == rtID2.uiControl) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator!(const sdv::ps::TMarshallID& rtID)
|
||||
{
|
||||
// The control ID is the onl ID which is not allowed to be zero.
|
||||
return rtID.uiControl ? false : true;
|
||||
}
|
||||
|
||||
inline bool operator==(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2)
|
||||
{
|
||||
if (rtID1.uiIdent != rtID2.uiIdent) return false;
|
||||
if (rtID1.uiControl != rtID2.uiControl) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator==(const sdv::com::TConnectionID& rtID1, size_t nVal)
|
||||
{
|
||||
if (nVal) return false;
|
||||
return operator==(rtID1, sdv::com::TConnectionID{});
|
||||
}
|
||||
|
||||
inline bool operator==(size_t nVal, const sdv::com::TConnectionID& rtID2)
|
||||
{
|
||||
if (nVal) return false;
|
||||
return operator==(sdv::com::TConnectionID{}, rtID2);
|
||||
}
|
||||
|
||||
inline bool operator!=(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2)
|
||||
{
|
||||
return !operator==(rtID1, rtID2);
|
||||
}
|
||||
|
||||
inline bool operator!=(const sdv::com::TConnectionID& rtID1, size_t nVal)
|
||||
{
|
||||
if (nVal) return true;
|
||||
return !operator==(rtID1, sdv::com::TConnectionID{});
|
||||
}
|
||||
|
||||
inline bool operator!=(size_t nVal, const sdv::com::TConnectionID& rtID2)
|
||||
{
|
||||
if (nVal) return true;
|
||||
return !operator==(sdv::com::TConnectionID{}, rtID2);
|
||||
}
|
||||
|
||||
inline bool operator<(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2)
|
||||
{
|
||||
if (rtID1.uiIdent < rtID2.uiIdent) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator<=(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2)
|
||||
{
|
||||
if (rtID1.uiIdent < rtID2.uiIdent) return true;
|
||||
if (rtID1.uiControl == rtID2.uiControl) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator>(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2)
|
||||
{
|
||||
if (rtID1.uiIdent > rtID2.uiIdent) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator>=(const sdv::com::TConnectionID& rtID1, const sdv::com::TConnectionID& rtID2)
|
||||
{
|
||||
if (rtID1.uiIdent > rtID2.uiIdent) return true;
|
||||
if (rtID1.uiControl == rtID2.uiControl) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator!(const sdv::com::TConnectionID& rtID)
|
||||
{
|
||||
// The control ID is the onl ID which is not allowed to be zero.
|
||||
return rtID.uiControl ? false : true;
|
||||
}
|
||||
|
||||
#endif // !defined(SDV_PS_SUPPORT_INL)
|
||||
300
export/support/sdv_core.h
Normal file
300
export/support/sdv_core.h
Normal file
@@ -0,0 +1,300 @@
|
||||
#ifndef SDV_CORE_H
|
||||
#define SDV_CORE_H
|
||||
|
||||
#ifndef DONT_LOAD_CORE_TYPES
|
||||
#include "../interfaces/core.h"
|
||||
#include "../interfaces/module.h"
|
||||
#endif
|
||||
#include "interface_ptr.h"
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
#include <stdlib.h>
|
||||
#include <functional>
|
||||
|
||||
#ifdef _WIN32
|
||||
// Resolve conflict
|
||||
#pragma push_macro("interface")
|
||||
#pragma push_macro("GetObject")
|
||||
#undef interface
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#include <objbase.h>
|
||||
|
||||
// Resolve conflict
|
||||
#pragma pop_macro("interface")
|
||||
#pragma pop_macro("GetObject")
|
||||
#ifdef GetClassInfo
|
||||
#undef GetClassInfo
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
#endif
|
||||
#elif defined __unix__
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* @brief The SDV core loader
|
||||
*/
|
||||
class CSDVCoreLoader
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
* @remarks The constructor doesn't load the library, since this could cause a deadlock during the initialization
|
||||
* phase. Loading is done through the Load function.
|
||||
*/
|
||||
CSDVCoreLoader() = default;
|
||||
|
||||
/**
|
||||
* @brief Destructor unloading the core
|
||||
*/
|
||||
~CSDVCoreLoader()
|
||||
{
|
||||
// Free the library
|
||||
if (m_tModule)
|
||||
#ifdef _WIN32
|
||||
FreeLibrary(reinterpret_cast<HMODULE>(m_tModule));
|
||||
#elif defined __unix__
|
||||
dlclose(reinterpret_cast<void*>(m_tModule));
|
||||
#else
|
||||
#error OS not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load the SDV core library.
|
||||
* @details The function searches for the library core_services in different locations:
|
||||
* First it searches in the directory of the executable for the library.
|
||||
* Then it searches in the directory of the executable for a configuration file with the library location.
|
||||
* The configuration file is called sdv_core_reloc.toml and should contain a section at least the line:
|
||||
* directory=[path] whereas [path] represents the path to the core library. Other information in the file is
|
||||
* ignored. Then it searches in the environment variable SDV_FRAMEWORK_RUNTIME for the location of the library.
|
||||
* Last it searches in the path for the location of the library.
|
||||
*/
|
||||
void Load()
|
||||
{
|
||||
if (m_bInit) return; // Prevent trying to load again.
|
||||
m_bInit = true;
|
||||
|
||||
// Check for the executable directory
|
||||
std::filesystem::path pathCoreLib;
|
||||
if (std::filesystem::exists(GetExecDirectory() / "core_services.sdv"))
|
||||
pathCoreLib = GetExecDirectory() / "core_services.sdv";
|
||||
// Check for the local config file
|
||||
if (pathCoreLib.empty() && std::filesystem::exists(GetExecDirectory() / "sdv_core_reloc.toml"))
|
||||
{
|
||||
std::ifstream fstream(GetExecDirectory() / "sdv_core_reloc.toml");
|
||||
std::string ssLine;
|
||||
while (std::getline(fstream, ssLine))
|
||||
{
|
||||
size_t nPos = 0;
|
||||
auto fnSkipWhitespace = [&]() { while (std::isspace(ssLine[nPos])) nPos++; };
|
||||
fnSkipWhitespace();
|
||||
if (ssLine[nPos] == '#') continue; // Rest of the line is comments
|
||||
if (ssLine.substr(nPos, 9) != "directory") continue; // not the keq of interest: skip line
|
||||
nPos += 9;
|
||||
fnSkipWhitespace();
|
||||
if (ssLine[nPos] != '=')
|
||||
{
|
||||
std::cout << "Error in \"sdv_core_reloc.toml\": expecting assignment character '=' following"
|
||||
" keyword 'directory'." << std::endl;
|
||||
break;
|
||||
}
|
||||
nPos++;
|
||||
fnSkipWhitespace();
|
||||
if (ssLine[nPos] != '\"')
|
||||
{
|
||||
std::cout << "Error in \"sdv_core_reloc.toml\": expecting double quote character '\"' indicating"
|
||||
" a string begin'." << std::endl;
|
||||
break;
|
||||
}
|
||||
nPos++;
|
||||
size_t nStart = nPos;
|
||||
while (nPos < ssLine.length() && ssLine[nPos] != '\"')
|
||||
{
|
||||
// Check for escape character
|
||||
if (ssLine[nPos] == '\\') nPos++;
|
||||
|
||||
// Skip character
|
||||
nPos++;
|
||||
}
|
||||
if (nPos >= ssLine.length() || ssLine[nPos] != '\"')
|
||||
{
|
||||
std::cout << "Error in \"sdv_core_reloc.toml\": expecting double quote character '\"' indicating"
|
||||
" a string end'." << std::endl;
|
||||
break;
|
||||
}
|
||||
std::string ssDirectory = ssLine.substr(nStart, nPos - nStart);
|
||||
while (ssDirectory.empty())
|
||||
{
|
||||
std::cout << "Error in \"sdv_core_reloc.toml\": expecting a valid value following the assignment"
|
||||
" of the 'directory' key." << std::endl;
|
||||
break;
|
||||
}
|
||||
pathCoreLib = std::filesystem::path(ssDirectory) / "core_services.sdv";
|
||||
if (pathCoreLib.is_relative())
|
||||
pathCoreLib = (GetExecDirectory() / pathCoreLib).lexically_normal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Check for the environment variable
|
||||
#ifdef _WIN32
|
||||
std::wstring ssPathCoreTemp(32768, '\0');
|
||||
GetEnvironmentVariable(L"SDV_FRAMEWORK_RUNTIME", ssPathCoreTemp.data(), static_cast<DWORD>(ssPathCoreTemp.size()));
|
||||
ssPathCoreTemp.resize(wcsnlen(ssPathCoreTemp.c_str(), ssPathCoreTemp.size()));
|
||||
if (pathCoreLib.empty() && !ssPathCoreTemp.empty())
|
||||
{
|
||||
pathCoreLib = std::filesystem::path(ssPathCoreTemp) / "core_services.sdv";
|
||||
#else
|
||||
if (pathCoreLib.empty() && getenv("SDV_FRAMEWORK_RUNTIME"))
|
||||
{
|
||||
pathCoreLib = std::filesystem::path(getenv("SDV_FRAMEWORK_RUNTIME")) / "core_services.sdv";
|
||||
#endif
|
||||
if (pathCoreLib.is_relative())
|
||||
pathCoreLib = (GetExecDirectory() / pathCoreLib).lexically_normal();
|
||||
}
|
||||
|
||||
// Depend on system path to find the library
|
||||
if (pathCoreLib.empty())
|
||||
pathCoreLib = "core_services.sdv";
|
||||
|
||||
// Open the library
|
||||
#ifdef _WIN32
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
m_tModule = reinterpret_cast<core::TModuleID>(LoadLibraryW(pathCoreLib.native().c_str()));
|
||||
#elif defined __unix__
|
||||
m_tModule = reinterpret_cast<core::TModuleID>(dlopen(pathCoreLib.native().c_str(), RTLD_LAZY));
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
if (!m_tModule)
|
||||
{
|
||||
std::string ssError;
|
||||
#ifdef _WIN32
|
||||
ssError.resize(1024);
|
||||
ssError.resize(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
|
||||
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &ssError.front(), 1024, NULL));
|
||||
while (!ssError.empty() && std::isspace(ssError.back())) ssError.pop_back();
|
||||
#elif defined __unix__
|
||||
const char* szError = dlerror();
|
||||
if (szError) ssError = szError;
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
std::cerr << "Could not load \"core_services.sdv\" library";
|
||||
if (!ssError.empty()) std::cerr << ": " << ssError;
|
||||
std::cerr << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the SDVCore function pointer
|
||||
using TFNSDVCore = IInterfaceAccess*();
|
||||
#ifdef _WIN32
|
||||
std::function<TFNSDVCore> fnSDVCore =
|
||||
reinterpret_cast<TFNSDVCore*>(GetProcAddress(reinterpret_cast<HMODULE>(m_tModule), "SDVCore"));
|
||||
#elif defined __unix__
|
||||
std::function<TFNSDVCore> fnSDVCore =
|
||||
reinterpret_cast<TFNSDVCore*>(dlsym(reinterpret_cast<void*>(m_tModule), "SDVCore"));
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
if (!fnSDVCore)
|
||||
{
|
||||
std::cerr << "The library \"core_services.sdv\" doesn't expose the SDVCore function." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Add version check!
|
||||
|
||||
// Get the core interface
|
||||
m_pCore = fnSDVCore();
|
||||
if (!m_pCore)
|
||||
{
|
||||
std::cerr << "The library \"core_services.sdv\" doesn't provide a valid interface." << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the core interface
|
||||
*/
|
||||
operator TInterfaceAccessPtr() const { return m_pCore; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Get the directory of the executable.
|
||||
* @return Path to the directory.
|
||||
*/
|
||||
static std::filesystem::path GetExecDirectory()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Windows specific
|
||||
std::wstring ssPath(32768, '\0');
|
||||
GetModuleFileNameW(NULL, ssPath.data(), static_cast<DWORD>(ssPath.size() - 1));
|
||||
#elif defined __linux__
|
||||
// Linux specific
|
||||
std::string ssPath(PATH_MAX + 1, '\0');
|
||||
const ssize_t nCount = readlink("/proc/self/exe", ssPath.data(), PATH_MAX);
|
||||
if (nCount < 0 || nCount >= PATH_MAX)
|
||||
return {}; // some error
|
||||
ssPath.at(nCount) = '\0';
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
return std::filesystem::path{ssPath.c_str()}.parent_path() / ""; // To finish the folder path with (back)slash
|
||||
}
|
||||
|
||||
bool m_bInit = false; ///< Is the loader initialized?
|
||||
core::TModuleID m_tModule = 0; ///< Module ID
|
||||
IInterfaceAccess* m_pCore = nullptr; ///< Pointer to the core services.
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
#ifndef NO_SDV_CORE_FUNC
|
||||
/**
|
||||
* @brief Access to the core.
|
||||
* @return Smart pointer to the core services interface.
|
||||
*/
|
||||
inline TInterfaceAccessPtr GetCore()
|
||||
{
|
||||
static internal::CSDVCoreLoader core;
|
||||
core.Load();
|
||||
return core;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access to specific interface of the core.
|
||||
* @tparam TInterface Type of interface to return.
|
||||
* @return Pointer to the interface or NULL when the interface was not exposed.
|
||||
*/
|
||||
template <typename TInterface>
|
||||
inline TInterface* GetCore()
|
||||
{
|
||||
return GetCore().GetInterface<TInterface>();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // !define SDV_CORE_H
|
||||
250
export/support/sdv_test_macro.h
Normal file
250
export/support/sdv_test_macro.h
Normal file
@@ -0,0 +1,250 @@
|
||||
#ifndef SDV_TEST_MACRO_H
|
||||
#define SDV_TEST_MACRO_H
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief Namespace TEST
|
||||
*/
|
||||
namespace TEST
|
||||
{
|
||||
/**
|
||||
* @brief Enum for warning levels.
|
||||
*/
|
||||
enum WarningLevel
|
||||
{
|
||||
WARNING_ENABLED, //<! With this level Failed tests are reported as error as it is in GTEST normally.
|
||||
WARNING_REDUCED, //<! With this level Failed tests are reported as warning.
|
||||
WARNING_DISABLED //<! With this level no action is implemented at this moment.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Function to report a warning when the expected condition is not met.
|
||||
* @param[in] condition The condition that is being checked (should be true if valid).
|
||||
* @param[in] warningLevel The level of warning to display.
|
||||
* @param[in] message The warning message to display.
|
||||
* @param[in] file The name of the file where the warning occurred.
|
||||
* @param[in] line The line number where the warning occurred.
|
||||
*/
|
||||
inline void ReportWarning(bool condition, WarningLevel warningLevel, const std::string& message, const char* file, int line)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
switch (warningLevel)
|
||||
{
|
||||
case WARNING_ENABLED:
|
||||
FAIL() << "[ FAILED ]: " << message << " in file " << file << " on line " << line << std::endl;
|
||||
break;
|
||||
case WARNING_DISABLED:
|
||||
// No action
|
||||
break;
|
||||
case WARNING_REDUCED:
|
||||
std::clog << "[[ WARNING ]] TEST FAILURE NOT EVALUATED: " << message << " in file " << file << " on line " << line << std::endl;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to detect whether tests are running with CMAKE build or locally manually.
|
||||
* @return Returns true if it is running with CMAKE build, otherwise false.
|
||||
*/
|
||||
inline bool IsRunningTestsWithCmakeBuild()
|
||||
{
|
||||
auto envVar = std::getenv("TEST_EXECUTION_MODE");
|
||||
|
||||
if (envVar && std::string(envVar) == "CMake") return true;
|
||||
else return false;
|
||||
}
|
||||
} // namespace TEST
|
||||
} // namespace sdv
|
||||
|
||||
/**
|
||||
* @brief Macro for checking whether tests are running with CMAKE build or locally manually.
|
||||
* Returns true if it is running with CMAKE build, otherwise false.
|
||||
*/
|
||||
#define SDV_IS_RUNNING_TESTS_WITH_CMAKE_BUILD sdv::TEST::IsRunningTestsWithCmakeBuild()
|
||||
|
||||
/**
|
||||
* @brief Helper macro to handle warning levels.
|
||||
* @param[in] level The warning level.
|
||||
* @param[in] statement The statement to execute.
|
||||
* @param[in] val1 The first value for comparison.
|
||||
* @param[in] val2 The second value for comparison.
|
||||
* @param[in] condition The condition to check.
|
||||
*/
|
||||
#define HANDLE_WARNING_LEVEL(level, statement, val1, val2, condition) \
|
||||
do \
|
||||
{ \
|
||||
switch (level) \
|
||||
{ \
|
||||
case sdv::TEST::WarningLevel::WARNING_ENABLED: \
|
||||
statement; \
|
||||
break; \
|
||||
case sdv::TEST::WarningLevel::WARNING_REDUCED: \
|
||||
if (val1 condition val2) statement; \
|
||||
else \
|
||||
{ \
|
||||
std::ostringstream oss; \
|
||||
oss << "[[ WARNING ]] TEST FAILURE NOT EVALUATED: Condition did not match for [" \
|
||||
<< #val1 "] and [" #val2 << "] in file " << __FILE__ << " on line " << __LINE__; \
|
||||
std::clog << oss.str() << std::endl; \
|
||||
} \
|
||||
break; \
|
||||
case sdv::TEST::WarningLevel::WARNING_DISABLED: /* No action */ \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Redefine GTEST macros with warning level.
|
||||
* @param[in] val1 The first value.
|
||||
* @param[in] val2 The second value.
|
||||
* @param[in] level The warning level.
|
||||
*/
|
||||
#define SDV_EXPECT_EQ(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_EQ(val1, val2), val1, val2, ==)
|
||||
|
||||
#define SDV_ASSERT_EQ(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_EQ(val1, val2), val1, val2, ==)
|
||||
|
||||
#define SDV_EXPECT_NE(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_NE(val1, val2), val1, val2, !=)
|
||||
|
||||
#define SDV_ASSERT_NE(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_NE(val1, val2), val1, val2, !=)
|
||||
|
||||
#define SDV_EXPECT_TRUE(condition, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_TRUE(condition), condition, true, ==)
|
||||
|
||||
#define SDV_ASSERT_TRUE(condition, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_TRUE(condition), condition, true, ==)
|
||||
|
||||
#define SDV_EXPECT_FALSE(condition, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_FALSE(condition), condition, false, ==)
|
||||
|
||||
#define SDV_ASSERT_FALSE(condition, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_FALSE(condition), condition, false, ==)
|
||||
|
||||
#define SDV_EXPECT_LT(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_LT(val1, val2), val1, val2, <)
|
||||
|
||||
#define SDV_ASSERT_LT(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_LT(val1, val2), val1, val2, <)
|
||||
|
||||
#define SDV_EXPECT_LE(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_LE(val1, val2), val1, val2, <=)
|
||||
|
||||
#define SDV_ASSERT_LE(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_LE(val1, val2), val1, val2, <=)
|
||||
|
||||
#define SDV_EXPECT_GT(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_GT(val1, val2), val1, val2, >)
|
||||
|
||||
#define SDV_ASSERT_GT(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_GT(val1, val2), val1, val2, >)
|
||||
|
||||
#define SDV_EXPECT_GE(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_GE(val1, val2), val1, val2, >=)
|
||||
|
||||
#define SDV_ASSERT_GE(val1, val2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_GE(val1, val2), val1, val2, >=)
|
||||
|
||||
#define SDV_EXPECT_STREQ(str1, str2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_STREQ((str1).c_str(), (str2).c_str()), str1, str2, ==)
|
||||
|
||||
#define SDV_ASSERT_STREQ(str1, str2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_STREQ((str1).c_str(), (str2).c_str()), str1, str2, ==)
|
||||
|
||||
#define SDV_EXPECT_STRNE(str1, str2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_STRNE(str1.c_str(), str2.c_str()), str1, str2, !=)
|
||||
|
||||
#define SDV_ASSERT_STRNE(str1, str2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_STRNE(str1.c_str(), str2.c_str()), str1, str2, !=)
|
||||
|
||||
#define SDV_EXPECT_STRCASEEQ(str1, str2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_STRCASEEQ((str1).c_str(), (str2).c_str()), str1, str2, ==)
|
||||
|
||||
#define SDV_ASSERT_STRCASEEQ(str1, str2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_STRCASEEQ((str1).c_str(), (str2).c_str()), str1, str2, ==)
|
||||
|
||||
#define SDV_EXPECT_STRCASENE(str1, str2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, EXPECT_STRCASENE((str1).c_str(), (str2).c_str()), str1, str2, !=)
|
||||
|
||||
#define SDV_ASSERT_STRCASENE(str1, str2, level) \
|
||||
HANDLE_WARNING_LEVEL(level, ASSERT_STRCASENE((str1).c_str(), (str2).c_str()), str1, str2, !=)
|
||||
|
||||
/**
|
||||
* @brief Macro for equality check (==) with warning reporting for time critical tests.
|
||||
* @param[in] val1 The first value.
|
||||
* @param[in] val2 The second value.
|
||||
* @param[in] warningLevel The level of warning to display.
|
||||
*/
|
||||
#define SDV_TIMING_EXPECT_EQ(val1, val2, warningLevel) \
|
||||
sdv::TEST::ReportWarning((val1) == (val2), warningLevel, \
|
||||
"Expected " #val1 " == " #val2 " (" #val1 "=" + std::to_string(val1) + ", " #val2 "=" + std::to_string(val2) + ")", \
|
||||
__FILE__, __LINE__)
|
||||
|
||||
/**
|
||||
* @brief Macro for inequality check (!=) with warning reporting for time critical tests.
|
||||
* @param[in] val1 The first value.
|
||||
* @param[in] val2 The second value.
|
||||
* @param[in] warningLevel The level of warning to display.
|
||||
*/
|
||||
#define SDV_TIMING_EXPECT_NE(val1, val2, warningLevel) \
|
||||
sdv::TEST::ReportWarning((val1) != (val2), warningLevel, \
|
||||
"Expected " #val1 " != " #val2 " (" #val1 "=" + std::to_string(val1) + ", " #val2 "=" + std::to_string(val2) + ")", \
|
||||
__FILE__, __LINE__)
|
||||
|
||||
/**
|
||||
* @brief Macro for greater-than check (>) with warning reporting for time critical tests.
|
||||
* @param[in] val1 The first value.
|
||||
* @param[in] val2 The second value.
|
||||
* @param[in] warningLevel The level of warning to display.
|
||||
*/
|
||||
#define SDV_TIMING_EXPECT_GT(val1, val2, warningLevel) \
|
||||
sdv::TEST::ReportWarning((val1) > (val2), warningLevel, \
|
||||
"Expected " #val1 " > " #val2 " (" #val1 "=" + std::to_string(val1) + ", " #val2 "=" + std::to_string(val2) + ")", \
|
||||
__FILE__, __LINE__)
|
||||
|
||||
/**
|
||||
* @brief Macro for less-than check (<) with warning reporting for time critical tests.
|
||||
* @param[in] val1 The first value.
|
||||
* @param[in] val2 The second value.
|
||||
* @param[in] warningLevel The level of warning to display.
|
||||
*/
|
||||
#define SDV_TIMING_EXPECT_LT(val1, val2, warningLevel) \
|
||||
sdv::TEST::ReportWarning((val1) < (val2), warningLevel, \
|
||||
"Expected " #val1 " < " #val2 " (" #val1 "=" + std::to_string(val1) + ", " #val2 "=" + std::to_string(val2) + ")", \
|
||||
__FILE__, __LINE__)
|
||||
|
||||
/**
|
||||
* @brief Macro for greater-than-or-equal-to check (>=) with warning reporting for time critical tests.
|
||||
* @param[in] val1 The first value.
|
||||
* @param[in] val2 The second value.
|
||||
* @param[in] warningLevel The level of warning to display.
|
||||
*/
|
||||
#define SDV_TIMING_EXPECT_GE(val1, val2, warningLevel) \
|
||||
sdv::TEST::ReportWarning((val1) >= (val2), warningLevel, \
|
||||
"Expected " #val1 " >= " #val2 " (" #val1 "=" + std::to_string(val1) + ", " #val2 "=" + std::to_string(val2) + ")", \
|
||||
__FILE__, __LINE__)
|
||||
|
||||
/**
|
||||
* @brief Macro for less-than-or-equal-to check (<=) with warning reporting for time critical tests.
|
||||
* @param[in] val1 The first value.
|
||||
* @param[in] val2 The second value.
|
||||
* @param[in] warningLevel The level of warning to display.
|
||||
*/
|
||||
#define SDV_TIMING_EXPECT_LE(val1, val2, warningLevel) \
|
||||
sdv::TEST::ReportWarning((val1) <= (val2), warningLevel, \
|
||||
"Expected " #val1 " <= " #val2 " (" #val1 "=" + std::to_string(val1) + ", " #val2 "=" + std::to_string(val2) + ")", \
|
||||
__FILE__, __LINE__)
|
||||
|
||||
#endif // SDV_TEST_MACRO_H
|
||||
596
export/support/sequence.h
Normal file
596
export/support/sequence.h
Normal file
@@ -0,0 +1,596 @@
|
||||
#ifndef SDV_SEQUENCE_H
|
||||
#define SDV_SEQUENCE_H
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include "iterator.h"
|
||||
#include "pointer.h"
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief Managed sequence class.
|
||||
* @details Sequence management class. A sequence provides a dynamic vector based on a buffer implementation of the ptr-class.
|
||||
* There are two versions of buffer management, fixed buffer management (nFixedSize template parameter larger than 0) and
|
||||
* dynamic buffer management (nFixedSize template parameter is 0). The functions of this class are similar to the functions of
|
||||
* the std::vector class.
|
||||
* @tparam T Type to use for the buffer allocation.
|
||||
* @tparam nFixedSize Size of the fixed size buffer or 0 for a dynamic sized buffer.
|
||||
*/
|
||||
|
||||
template <class T, size_t nFixedSize = 0>
|
||||
class sequence
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Value type for this sequence class.
|
||||
*/
|
||||
using value_type = T;
|
||||
|
||||
/**
|
||||
* @brief Forward iterator class used by this sequence class.
|
||||
*/
|
||||
using iterator = internal::index_iterator<sequence<T, nFixedSize>, false, false>;
|
||||
|
||||
/**
|
||||
* @brief Backward iterator class used by this sequence class.
|
||||
*/
|
||||
using reverse_iterator = internal::index_iterator<sequence<T, nFixedSize>, false, true>;
|
||||
|
||||
/**
|
||||
* @brief Const forward iterator class used by this sequence class.
|
||||
*/
|
||||
using const_iterator = internal::index_iterator<sequence<T, nFixedSize>, true, false>;
|
||||
|
||||
/**
|
||||
* @brief Const backward iterator class used by this sequence class.
|
||||
*/
|
||||
using const_reverse_iterator = internal::index_iterator<sequence<T, nFixedSize>, true, true>;
|
||||
|
||||
/**
|
||||
* @brief Reference type of the element.
|
||||
*/
|
||||
using reference = T&;
|
||||
|
||||
/**
|
||||
* @brief Const reference type of the element.
|
||||
*/
|
||||
using const_reference = const T&;
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
sequence() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~sequence();
|
||||
|
||||
/**
|
||||
* @brief Construct a sequence with a certain amount of values.
|
||||
* @param[in] nCount The amount of values to create.
|
||||
* @param[in] rtValue Reference to the value to use for the initialization.
|
||||
*/
|
||||
sequence(size_t nCount, const T& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Construct a sequence with a certain amount of values.
|
||||
* @param[in] nCount The amount of values to create.
|
||||
*/
|
||||
explicit sequence(size_t nCount);
|
||||
|
||||
/**
|
||||
* @brief Construct a sequence from a range of values accessible through iterators.
|
||||
* @tparam TIterator Type of iterator.
|
||||
* @param[in] itFirst The iterator pointing to the itFirst value.
|
||||
* @param[in] itLast The iterator pointing to the value past the itLast value.
|
||||
*/
|
||||
template <class TIterator>
|
||||
sequence(TIterator itFirst, TIterator itLast);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor of same sequence type.
|
||||
* @param[in] rseq Reference to the sequence containing the values to copy.
|
||||
*/
|
||||
sequence(const sequence& rseq);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor of other sequence types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided sequence.
|
||||
* @param[in] rseq Reference to the sequence containing the values to copy.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
sequence(const sequence<T, nFixedSize2>& rseq);
|
||||
|
||||
/**
|
||||
* @brief Move constructor of same sequence type.
|
||||
* @param[in] rseq Reference to the sequence to move the values from.
|
||||
*/
|
||||
sequence(sequence&& rseq) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Move constructor of other sequence types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided sequence.
|
||||
* @param[in] rseq Reference to the sequence to move the values from.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
sequence(sequence<T, nFixedSize2>&& rseq) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Construct a sequence from a vector.
|
||||
* @param[in] rvec Reference to the sequence.
|
||||
*/
|
||||
sequence(std::vector<T>& rvec);
|
||||
|
||||
/**
|
||||
* @brief Construct a sequence from an initializer list.
|
||||
* @param[in] ilist Initializer list.
|
||||
*/
|
||||
sequence(std::initializer_list<T> ilist);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator of same sequence type.
|
||||
* @param[in] rseq Reference to the sequence.
|
||||
* @return Reference to this sequence.
|
||||
*/
|
||||
sequence& operator=(const sequence& rseq);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator of other sequence types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided sequence.
|
||||
* @param[in] rseq Reference to the sequence.
|
||||
* @return Reference to this sequence.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
sequence& operator=(const sequence<T, nFixedSize2>& rseq);
|
||||
|
||||
/**
|
||||
* @brief Move operator of same sequence type.
|
||||
* @param[in] rseq Reference to the sequence.
|
||||
* @return Reference to this sequence.
|
||||
*/
|
||||
sequence& operator=(sequence&& rseq) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Move operator of other sequence types.
|
||||
* @tparam nFixedSize2 The fixed size of the provided sequence.
|
||||
* @param[in] rseq Reference to the sequence.
|
||||
* @return Reference to this sequence.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
sequence& operator=(sequence<T, nFixedSize2>&& rseq) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Assignment operator for vector.
|
||||
* @param[in] rvec Reference to the vector.
|
||||
* @return Reference to this sequence.
|
||||
*/
|
||||
sequence& operator=(const std::vector<T>& rvec);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator for initializer list.
|
||||
* @param[in] ilist Initializer list.
|
||||
* @return Reference to this sequence.
|
||||
*/
|
||||
sequence& operator=(std::initializer_list<T> ilist);
|
||||
|
||||
/**
|
||||
* @brief Assign an amount of values to the sequence replacing the values existing before.
|
||||
* @param[in] nCount Amount of values to assign.
|
||||
* @param[in] rtValue Reference to the value to assign.
|
||||
*/
|
||||
void assign(size_t nCount, const T& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Assign an amount of values pointed to by itFirst and itLast iterators replacing the values existing before.
|
||||
* @tparam TIterator Type of iterator.
|
||||
* @param[in] itFirst The iterator pointing to the itFirst value.
|
||||
* @param[in] itLast The iterator pointing to the value past the itLast value.
|
||||
*/
|
||||
template <class TIterator>
|
||||
void assign(TIterator itFirst, TIterator itLast);
|
||||
|
||||
/**
|
||||
* @brief Assign the values from an initializer list.
|
||||
* @param[in] ilist Initializer list.
|
||||
*/
|
||||
void assign(std::initializer_list<T> ilist);
|
||||
|
||||
/**
|
||||
* @brief Return a reference to the value at the specified position.
|
||||
* @param[in] nPos The specified position.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
reference at(size_t nPos);
|
||||
|
||||
/**
|
||||
* @brief Return a reference to the value at the specified position.
|
||||
* @param[in] nPos The specified position.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
const_reference at(size_t nPos) const;
|
||||
|
||||
/**
|
||||
* @brief Return a reference to the value at the specified position.
|
||||
* @param[in] nPos The specified position.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
reference operator[](size_t nPos);
|
||||
|
||||
/**
|
||||
* @brief Return a reference to the value at the specified position.
|
||||
* @param[in] nPos The specified position.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
const_reference operator[](size_t nPos) const;
|
||||
|
||||
/**
|
||||
* @brief Return a reference to the itFirst value.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
T& front();
|
||||
|
||||
/**
|
||||
* @brief Return a reference to the itFirst value.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
const T& front() const;
|
||||
|
||||
/**
|
||||
* @brief Return a reference to the itLast value.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
T& back();
|
||||
|
||||
/**
|
||||
* @brief Return a reference to the itLast value.
|
||||
* @return Reference to the value.
|
||||
*/
|
||||
const T& back() const;
|
||||
|
||||
/**
|
||||
* @brief Cast operator for C++ vector
|
||||
* @return Returns a C++ vector object containing a copy of the sequence.
|
||||
*/
|
||||
operator std::vector<T>() const;
|
||||
|
||||
/**
|
||||
* @brief Access to the underlying data.
|
||||
* @return Pointer to the data.
|
||||
*/
|
||||
const T* data() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Access to the buffer.
|
||||
* @return Return a reference to the internal buffer.
|
||||
*/
|
||||
pointer<T, nFixedSize>& buffer() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return an iterator to the itFirst value of the sequence.
|
||||
* @return Iterator to the itFirst value of te sequence.
|
||||
*/
|
||||
iterator begin() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return an iterator to the itFirst value of the sequence.
|
||||
* @return Iterator to the itFirst value of te sequence.
|
||||
*/
|
||||
const_iterator begin() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return a const iterator to the itFirst value of the sequence.
|
||||
* @return Const iterator to the itFirst value of te sequence.
|
||||
*/
|
||||
const_iterator cbegin() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return a reverse-iterator to the itLast value of the sequence.
|
||||
* @return Reverse iterator to the itLast value of te sequence.
|
||||
*/
|
||||
reverse_iterator rbegin() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return a reverse-iterator to the itLast value of the sequence.
|
||||
* @return Reverse iterator to the itLast value of te sequence.
|
||||
*/
|
||||
const_reverse_iterator rbegin() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return a const reverse iterator to the itLast value of the sequence.
|
||||
* @return Const reverse iterator to the itLast value of te sequence.
|
||||
*/
|
||||
const_reverse_iterator crbegin() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return an iterator beyond the itLast value of the sequence.
|
||||
* @return Iterator beyond the itLast value of te sequence.
|
||||
*/
|
||||
iterator end() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return an iterator beyond the itLast value of the sequence.
|
||||
* @return Iterator beyond the itLast value of te sequence.
|
||||
*/
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return a const beyond the itLast value of the sequence.
|
||||
* @return Const iterator beyond the itLast value of te sequence.
|
||||
*/
|
||||
const_iterator cend() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator before the itFirst value of the sequence.
|
||||
* @return Reverse iterator before the itLast value of te sequence.
|
||||
*/
|
||||
reverse_iterator rend() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator before the itFirst value of the sequence.
|
||||
* @return Reverse iterator before the itLast value of te sequence.
|
||||
*/
|
||||
const_reverse_iterator rend() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return a const reverse iterator before the itFirst value of the sequence.
|
||||
* @return Const reverse iterator before the itLast value of te sequence.
|
||||
*/
|
||||
const_reverse_iterator crend() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Is the sequence empty?
|
||||
* @return Returns 'true' when the sequence is empty; 'false' when not.
|
||||
*/
|
||||
bool empty() const;
|
||||
|
||||
/**
|
||||
* @brief Get the size of the sequence.
|
||||
* @remarks The length and the size for the sequence are equal.
|
||||
* @return The size of the sequence buffer.
|
||||
*/
|
||||
size_t size() const;
|
||||
|
||||
/**
|
||||
* @brief Get the length of the sequence.
|
||||
* @remarks The length and the size for the sequence are equal.
|
||||
* @return The length of the sequence.
|
||||
*/
|
||||
size_t length() const;
|
||||
|
||||
/**
|
||||
* @brief Reserve capacity for the sequence buffer. Additional buffer will be filled with zeros.
|
||||
* @remarks Reducing the capacity will have no effect.
|
||||
* @param[in] nNewCap The new capacity.
|
||||
*/
|
||||
void reserve(size_t nNewCap = 0);
|
||||
|
||||
/**
|
||||
* @brief Get the current sequence capacity.
|
||||
* @remarks This will be the same as the length and size of the sequence.
|
||||
* @return The capacity of the current sequence.
|
||||
*/
|
||||
size_t capacity() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Reduce the buffer to fit the sequence.
|
||||
* @remarks This function will have no effect.
|
||||
*/
|
||||
void shrink_to_fit();
|
||||
|
||||
/**
|
||||
* @brief Clear the sequence.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* @brief Insert a value rtValue at the position itPos.
|
||||
* @param[in] itPos Iterator pointing to the position to insert the value.
|
||||
* @param[in] rtValue Reference to the value to insert.
|
||||
* @return The iterator pointing to the inserted value.
|
||||
*/
|
||||
iterator insert(const_iterator itPos, const T& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Insert a value rtValue at the position itPos.
|
||||
* @param[in] itPos Iterator pointing to the position to insert the value.
|
||||
* @param[in] rtValue Reference to the value to insert.
|
||||
* @return The iterator pointing to the inserted value.
|
||||
*/
|
||||
iterator insert(const_iterator itPos, T&& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Insert an amount of values rtValue at the position itPos.
|
||||
* @param[in] itPos Iterator pointing to the position to insert the value.
|
||||
* @param[in] nCount The amount of values to insert.
|
||||
* @param[in] rtValue Reference to the value to insert.
|
||||
* @return The iterator pointing to the itFirst inserted value.
|
||||
*/
|
||||
iterator insert(const_iterator itPos, size_t nCount, const T& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Insert a range of vvalues identified by the supplied iterators.
|
||||
* @tparam TIterator Iterator type to use.
|
||||
* @param[in] itPos Iterator pointing to the position to insert the value.
|
||||
* @param[in] itFirst The iterator pointing to the itFirst value.
|
||||
* @param[in] itLast The iterator pointing to the value past the itLast value.
|
||||
* @return The iterator pointing to the itFirst inserted value.
|
||||
*/
|
||||
template <class TIterator>
|
||||
iterator insert(const_iterator itPos, TIterator itFirst, TIterator itLast);
|
||||
|
||||
/**
|
||||
* @brief Insert an initializer list at the position itPos.
|
||||
* @param[in] itPos Iterator pointing to the position to insert the value.
|
||||
* @param[in] ilist Initializer list.
|
||||
* @return The iterator pointing to the itFirst inserted value.
|
||||
*/
|
||||
iterator insert(const_iterator itPos, std::initializer_list<T> ilist);
|
||||
|
||||
/**
|
||||
* @brief Remove a value at the provided position.
|
||||
* @remarks The iterator must point to this sequence.
|
||||
* @param[in] itPos Iterator pointing to the position to erase the value from.
|
||||
* @return Iterator to the value following the erase value or end() when no more values are available.
|
||||
*/
|
||||
iterator erase(iterator itPos);
|
||||
|
||||
/**
|
||||
* @brief Remove a value at the provided position.
|
||||
* @remarks The iterator must point to this sequence.
|
||||
* @param[in] itPos Iterator pointing to the position to erase the value from.
|
||||
* @return Iterator to the value following the erase value or end() when no more values are available.
|
||||
*/
|
||||
iterator erase(const_iterator itPos);
|
||||
|
||||
/**
|
||||
* @brief Remove al values starting at itFirst until but not including itLast.
|
||||
* @remarks Both iterators must point to this sequence.
|
||||
* @param[in] itFirst The iterator pointing to the itFirst value.
|
||||
* @param[in] itLast The iterator pointing to the value past the itLast value.
|
||||
* @return Iterator to the value following the erased values or end() when no more values are available.
|
||||
*/
|
||||
iterator erase(iterator itFirst, iterator itLast);
|
||||
|
||||
/**
|
||||
* @brief Remove al values starting at itFirst until but not including itLast.
|
||||
* @remarks Both iterators must point to this sequence.
|
||||
* @param[in] itFirst The iterator pointing to the itFirst value.
|
||||
* @param[in] itLast The iterator pointing to the value past the itLast value.
|
||||
* @return Iterator to the value following the erased values or end() when no more values are available.
|
||||
*/
|
||||
iterator erase(const_iterator itFirst, const_iterator itLast);
|
||||
|
||||
/**
|
||||
* @brief Appends the given value to the end of the sequence.
|
||||
* @param[in] rtValue Reference to the value to append.
|
||||
*/
|
||||
void push_back(const T& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Appends the given value to the end of the sequence.
|
||||
* @param[in] rtValue Reference to the value to append.
|
||||
*/
|
||||
void push_back(T&& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Removes the itLast value from the sequence.
|
||||
*/
|
||||
void pop_back();
|
||||
|
||||
/**
|
||||
* @brief Set the new size of the sequence.
|
||||
* @param[in] nCount The size of the sequence buffer.
|
||||
*/
|
||||
void resize(size_t nCount);
|
||||
|
||||
/**
|
||||
* @brief Set the new size of the sequence. Additional values will be filled with rtValue.
|
||||
* @param[in] nCount The size of the sequence buffer.
|
||||
* @param[in] rtValue Reference to the value to use for initialization.
|
||||
*/
|
||||
void resize(size_t nCount, const value_type& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Exchange the content of provided sequence with this sequence.
|
||||
* @tparam nFixedSize2 The fixed size of the provided sequence.
|
||||
* @param[in] rseq Reference to the sequence to swap with.
|
||||
*/
|
||||
template <size_t nFixedSize2>
|
||||
void swap(sequence<T, nFixedSize2>& rseq) noexcept;
|
||||
|
||||
private:
|
||||
pointer<T, nFixedSize> m_ptrData; ///< Smart pointer to the data.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Swap two sequences.
|
||||
* @tparam T Type to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left sequence.
|
||||
* @tparam nFixedSizeRight The fixed size of the right sequence.
|
||||
* @param[in] rseqLeft Reference to the first sequence.
|
||||
* @param[in] rseqRight Reference to the second sequence.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
void swap(sequence<T, nFixedSizeLeft>& rseqLeft, sequence<T, nFixedSizeRight>& rseqRight) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Compare whether the content of both sequences is identical.
|
||||
* @tparam T Type to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left sequence.
|
||||
* @tparam nFixedSizeRight The fixed size of the right sequence.
|
||||
* @param[in] rseqLeft Reference to the first sequence.
|
||||
* @param[in] rseqRight Reference to the second sequence.
|
||||
* @return Returns whether the comparison was successful.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator==(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight);
|
||||
|
||||
/**
|
||||
* @brief Compare whether the content of both sequences is not identical.
|
||||
* @tparam T Type to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left sequence.
|
||||
* @tparam nFixedSizeRight The fixed size of the right sequence.
|
||||
* @param[in] rseqLeft Reference to the first sequence.
|
||||
* @param[in] rseqRight Reference to the second sequence.
|
||||
* @return Returns whether the comparison was successful.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator!=(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight);
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left sequence has a lower content than the right sequence or if equal, has a smaller size.
|
||||
* @tparam T Type to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left sequence.
|
||||
* @tparam nFixedSizeRight The fixed size of the right sequence.
|
||||
* @param[in] rseqLeft Reference to the left sequence.
|
||||
* @param[in] rseqRight Reference to the right sequence.
|
||||
* @return Returns whether the comparison was successful.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator<(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight);
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left sequence has a lower or equal content than the right sequence or if equal, has a smaller
|
||||
* or equal size.
|
||||
* @tparam T Type to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left sequence.
|
||||
* @tparam nFixedSizeRight The fixed size of the right sequence.
|
||||
* @param[in] rseqLeft Reference to the left sequence.
|
||||
* @param[in] rseqRight Reference to the right sequence.
|
||||
* @return Returns whether the comparison was successful.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator<=(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight);
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left sequence has a higher content than the right sequence or if equal, has a larger size.
|
||||
* @tparam T Type to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left sequence.
|
||||
* @tparam nFixedSizeRight The fixed size of the right sequence.
|
||||
* @param[in] rseqLeft Reference to the left sequence.
|
||||
* @param[in] rseqRight Reference to the right sequence.
|
||||
* @return Returns whether the comparison was successful.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator>(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight);
|
||||
|
||||
/**
|
||||
* @brief Compare whether the left sequence has a higher or equal content than the right sequence or if equal, has a larger
|
||||
* or equal size.
|
||||
* @tparam T Type to use as a base.
|
||||
* @tparam nFixedSizeLeft The fixed size of the left sequence.
|
||||
* @tparam nFixedSizeRight The fixed size of the right sequence.
|
||||
* @param[in] rseqLeft Reference to the left sequence.
|
||||
* @param[in] rseqRight Reference to the right sequence.
|
||||
* @return Returns whether the comparison was successful.
|
||||
*/
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
bool operator>=(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight);
|
||||
} // namespace sdv
|
||||
|
||||
#include "sequence.inl"
|
||||
|
||||
#endif // !defined SDV_SEQUENCE_H
|
||||
713
export/support/sequence.inl
Normal file
713
export/support/sequence.inl
Normal file
@@ -0,0 +1,713 @@
|
||||
#ifndef SDV_SEQUENCE_INL
|
||||
#define SDV_SEQUENCE_INL
|
||||
|
||||
#ifndef SDV_SEQUENCE_H
|
||||
#error Do not include "sequence.inl" directly. Include "sequence.h" instead!
|
||||
#endif //!defined SDV_SEQUENCE_H
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>::sequence() noexcept
|
||||
{}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
sequence<T, nFixedSize>::~sequence()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>::sequence(size_t nCount, const T& rtValue) : sequence()
|
||||
{
|
||||
insert(begin(), nCount, rtValue);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>::sequence(size_t nCount) : sequence()
|
||||
{
|
||||
T t{};
|
||||
insert(begin(), nCount, t);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
template <class TIterator>
|
||||
inline sequence<T, nFixedSize>::sequence(TIterator itFirst, TIterator itLast) : sequence()
|
||||
{
|
||||
insert(begin(), itFirst, itLast);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>::sequence(const sequence& rseq) : sequence()
|
||||
{
|
||||
if (!rseq.empty())
|
||||
{
|
||||
resize(rseq.size());
|
||||
if (m_ptrData)
|
||||
std::copy_n(rseq.data(), std::min(rseq.size(), size()), m_ptrData.get());
|
||||
}
|
||||
}
|
||||
|
||||
/// @cond DOXYGEN_IGNORE
|
||||
template <class T, size_t nFixedSize>
|
||||
template <size_t nFixedSize2>
|
||||
inline sequence<T, nFixedSize>::sequence(const sequence<T, nFixedSize2>& rseq) : sequence()
|
||||
{
|
||||
if (!rseq.empty())
|
||||
{
|
||||
resize(rseq.size());
|
||||
if (m_ptrData)
|
||||
std::copy_n(rseq.data(), std::min(rseq.size(), size()), m_ptrData.get());
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>::sequence(sequence&& rseq) noexcept : sequence()
|
||||
{
|
||||
m_ptrData = std::move(rseq.m_ptrData);
|
||||
}
|
||||
|
||||
/// @cond DOXYGEN_IGNORE
|
||||
template <class T, size_t nFixedSize>
|
||||
template <size_t nFixedSize2>
|
||||
inline sequence<T, nFixedSize>::sequence(sequence<T, nFixedSize2>&& rseq) noexcept : sequence()
|
||||
{
|
||||
m_ptrData = std::move(rseq.buffer());
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>::sequence(std::vector<T>& rvec) : sequence()
|
||||
{
|
||||
if (!rvec.empty())
|
||||
{
|
||||
resize(rvec.size());
|
||||
if (m_ptrData)
|
||||
std::copy_n(rvec.data(), std::min(rvec.size(), size()), m_ptrData.get());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>::sequence(std::initializer_list<T> ilist) : sequence()
|
||||
{
|
||||
insert(begin(), ilist);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>& sequence<T, nFixedSize>::operator=(const sequence& rseq)
|
||||
{
|
||||
clear();
|
||||
if (!rseq.empty())
|
||||
{
|
||||
resize(rseq.size());
|
||||
if (m_ptrData)
|
||||
std::copy_n(rseq.data(), std::min(rseq.size(), size()), m_ptrData.get());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @cond DOXYGEN_IGNORE
|
||||
template <class T, size_t nFixedSize>
|
||||
template <size_t nFixedSize2>
|
||||
inline sequence<T, nFixedSize>& sequence<T, nFixedSize>::operator=(const sequence<T, nFixedSize2>& rseq)
|
||||
{
|
||||
clear();
|
||||
if (!rseq.empty())
|
||||
{
|
||||
resize(rseq.size());
|
||||
if (m_ptrData)
|
||||
std::copy_n(rseq.data(), std::min(rseq.size(), size()), m_ptrData.get());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/// @cond DOXYGEN_IGNORE
|
||||
template <class T, size_t nFixedSize>
|
||||
template <size_t nFixedSize2>
|
||||
inline sequence<T, nFixedSize>& sequence<T, nFixedSize>::operator=(sequence<T, nFixedSize2>&& rseq) noexcept
|
||||
{
|
||||
clear();
|
||||
m_ptrData = std::move(rseq.buffer());
|
||||
return *this;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>& sequence<T, nFixedSize>::operator=(sequence&& rseq) noexcept
|
||||
{
|
||||
clear();
|
||||
m_ptrData = std::move(rseq.m_ptrData);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>& sequence<T, nFixedSize>::operator=(const std::vector<T>& rvec)
|
||||
{
|
||||
clear();
|
||||
if (!rvec.empty())
|
||||
{
|
||||
resize(rvec.size());
|
||||
if (m_ptrData)
|
||||
std::copy_n(rvec.data(), std::min(rvec.size(), size()), m_ptrData.get());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>& sequence<T, nFixedSize>::operator=(std::initializer_list<T> ilist)
|
||||
{
|
||||
clear();
|
||||
insert(begin(), ilist);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::assign(size_t nCount, const T& rtValue)
|
||||
{
|
||||
clear();
|
||||
insert(begin(), nCount, rtValue);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
template <class TIterator>
|
||||
inline void sequence<T, nFixedSize>::assign(TIterator itFirst, TIterator itLast)
|
||||
{
|
||||
clear();
|
||||
insert(begin(), itFirst, itLast);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::assign(std::initializer_list<T> ilist)
|
||||
{
|
||||
clear();
|
||||
insert(begin(), ilist);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::reference sequence<T, nFixedSize>::at(size_t nPos)
|
||||
{
|
||||
if (nPos >= size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(nPos);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return m_ptrData[nPos];
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_reference sequence<T, nFixedSize>::at(size_t nPos) const
|
||||
{
|
||||
if (nPos >= size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(nPos);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return m_ptrData[nPos];
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::reference sequence<T, nFixedSize>::operator[](size_t nPos)
|
||||
{
|
||||
if (nPos >= size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(nPos);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return m_ptrData[nPos];
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_reference sequence<T, nFixedSize>::operator[](size_t nPos) const
|
||||
{
|
||||
if (nPos >= size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(nPos);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return m_ptrData[nPos];
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline T& sequence<T, nFixedSize>::front()
|
||||
{
|
||||
if (!size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(0);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return m_ptrData[0];
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline const T& sequence<T, nFixedSize>::front() const
|
||||
{
|
||||
if (!size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(0);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return m_ptrData[0];
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline T& sequence<T, nFixedSize>::back()
|
||||
{
|
||||
if (!size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(0);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return m_ptrData[size() - 1];
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline const T& sequence<T, nFixedSize>::back() const
|
||||
{
|
||||
if (!size())
|
||||
{
|
||||
XIndexOutOfRange exception;
|
||||
exception.uiIndex = static_cast<uint32_t>(0);
|
||||
exception.uiSize = static_cast<uint32_t>(size());
|
||||
throw exception;
|
||||
}
|
||||
return m_ptrData[size() - 1];
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline sequence<T, nFixedSize>::operator std::vector<T>() const
|
||||
{
|
||||
std::vector<T> vec;
|
||||
if (size())
|
||||
{
|
||||
try
|
||||
{
|
||||
vec.resize(size());
|
||||
}
|
||||
catch (const std::bad_alloc&)
|
||||
{
|
||||
core::XAllocFailed exception;
|
||||
exception.uiSize = static_cast<uint32_t>(size() * sizeof(T));
|
||||
throw exception;
|
||||
}
|
||||
std::copy_n(data(), std::min(size(), vec.size()), &vec.front());
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline const T* sequence<T, nFixedSize>::data() const noexcept
|
||||
{
|
||||
return m_ptrData.get();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline pointer<T, nFixedSize>& sequence<T, nFixedSize>::buffer() noexcept
|
||||
{
|
||||
return m_ptrData;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::begin() noexcept
|
||||
{
|
||||
return iterator(this);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_iterator sequence<T, nFixedSize>::begin() const noexcept
|
||||
{
|
||||
return iterator(this);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_iterator sequence<T, nFixedSize>::cbegin() const noexcept
|
||||
{
|
||||
return const_iterator(this);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::reverse_iterator sequence<T, nFixedSize>::rbegin() noexcept
|
||||
{
|
||||
return reverse_iterator(this);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_reverse_iterator sequence<T, nFixedSize>::rbegin() const noexcept
|
||||
{
|
||||
return reverse_iterator(this);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_reverse_iterator sequence<T, nFixedSize>::crbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(this);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::end() noexcept
|
||||
{
|
||||
iterator it(this);
|
||||
it += std::numeric_limits<size_t>::max();
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_iterator sequence<T, nFixedSize>::end() const noexcept
|
||||
{
|
||||
iterator it(this);
|
||||
it += std::numeric_limits<size_t>::max();
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_iterator sequence<T, nFixedSize>::cend() const noexcept
|
||||
{
|
||||
const_iterator it(this);
|
||||
it += std::numeric_limits<size_t>::max();
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::reverse_iterator sequence<T, nFixedSize>::rend() noexcept
|
||||
{
|
||||
reverse_iterator it(this);
|
||||
it += std::numeric_limits<size_t>::max();
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_reverse_iterator sequence<T, nFixedSize>::rend() const noexcept
|
||||
{
|
||||
reverse_iterator it(this);
|
||||
it += std::numeric_limits<size_t>::max();
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::const_reverse_iterator sequence<T, nFixedSize>::crend() const noexcept
|
||||
{
|
||||
const_reverse_iterator it(this);
|
||||
it += std::numeric_limits<size_t>::max();
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline bool sequence<T, nFixedSize>::empty() const
|
||||
{
|
||||
return !size();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline size_t sequence<T, nFixedSize>::size() const
|
||||
{
|
||||
return m_ptrData.size();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline size_t sequence<T, nFixedSize>::length() const
|
||||
{
|
||||
return m_ptrData.size();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::reserve(size_t nNewCap /*= 0*/)
|
||||
{
|
||||
if (nNewCap > size())
|
||||
resize(nNewCap);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline size_t sequence<T, nFixedSize>::capacity() const noexcept
|
||||
{
|
||||
return m_ptrData.capacity();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::shrink_to_fit()
|
||||
{
|
||||
// Do nothing...
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::clear()
|
||||
{
|
||||
m_ptrData.reset();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::insert(const_iterator itPos, const T& rtValue)
|
||||
{
|
||||
return insert(itPos, static_cast<size_t>(1), rtValue);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::insert(const_iterator itPos, T&& rtValue)
|
||||
{
|
||||
T t{};
|
||||
insert(itPos, static_cast<size_t>(1), t);
|
||||
iterator it = itPos;
|
||||
*it = std::move(rtValue);
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::insert(const_iterator itPos, size_t nCount, const T& rtValue)
|
||||
{
|
||||
if (!itPos.is_valid(*this)) throw XInvalidIterator();
|
||||
|
||||
// Determine location
|
||||
size_t nIndex = 0;
|
||||
if (itPos == cend())
|
||||
nIndex = size();
|
||||
else if (!empty())
|
||||
nIndex = &itPos[0] - data();
|
||||
|
||||
// Calculate count
|
||||
size_t nCountTemp = nCount;
|
||||
size_t nCurrentLen = size();
|
||||
if (nFixedSize && nCurrentLen + nCountTemp > nFixedSize)
|
||||
nCountTemp = nFixedSize - nCurrentLen;
|
||||
if (!nCountTemp) return iterator(itPos);;
|
||||
|
||||
// Allocate space for a new sequence.
|
||||
m_ptrData.resize(nCurrentLen + nCountTemp);
|
||||
|
||||
// Copy the part following the index.
|
||||
if (nIndex < nCurrentLen)
|
||||
std::copy_backward(data() + nIndex, data() + nCurrentLen, m_ptrData.get() + nCurrentLen + nCountTemp);
|
||||
|
||||
// Insert the values
|
||||
if (nCountTemp) std::fill_n(m_ptrData.get() + std::min(nIndex, nCurrentLen), nCountTemp, rtValue);
|
||||
|
||||
return iterator(itPos);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
template <class TIterator>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::insert(const_iterator itPos, TIterator itFirst, TIterator itLast)
|
||||
{
|
||||
if (!itPos.is_valid(*this)) throw XInvalidIterator();
|
||||
|
||||
// Count the amount of entries to insert
|
||||
size_t nCount = 0;
|
||||
for (TIterator itIndex = itFirst; itIndex != itLast; itIndex++)
|
||||
nCount++;
|
||||
|
||||
// Determine location
|
||||
size_t nIndex = 0;
|
||||
if (itPos == cend())
|
||||
nIndex = size();
|
||||
else if (!empty())
|
||||
nIndex = &itPos[0] - data();
|
||||
|
||||
// Calculate count
|
||||
size_t nCountTemp = nCount;
|
||||
size_t nCurrentLen = size();
|
||||
if (nFixedSize && nCurrentLen + nCountTemp > nFixedSize)
|
||||
nCountTemp = nFixedSize - nCurrentLen;
|
||||
if (!nCountTemp) return iterator(itPos);;
|
||||
|
||||
// Allocate space for a new sequence.
|
||||
m_ptrData.resize(nCurrentLen + nCountTemp);
|
||||
|
||||
// Copy the part following the index.
|
||||
if (nIndex < nCurrentLen)
|
||||
std::copy_backward(data() + nIndex, data() + nCurrentLen, m_ptrData.get() + nCurrentLen + nCountTemp);
|
||||
|
||||
// Copy the data
|
||||
for (TIterator itIndex = itFirst; itIndex != itLast; itIndex++)
|
||||
at(nIndex++) = *itIndex;
|
||||
|
||||
return iterator(itPos);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::insert(const_iterator itPos, std::initializer_list<T> ilist)
|
||||
{
|
||||
if (!itPos.is_valid(*this)) throw XInvalidIterator();
|
||||
return insert(itPos, ilist.begin(), ilist.end());
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::erase(iterator itPos)
|
||||
{
|
||||
erase(itPos, itPos + 1);
|
||||
return itPos;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::erase(const_iterator itPos)
|
||||
{
|
||||
erase(itPos, itPos + 1);
|
||||
return itPos;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::erase(iterator itFirst, iterator itLast)
|
||||
{
|
||||
erase(const_iterator(itFirst), const_iterator(itLast));
|
||||
return itFirst;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline typename sequence<T, nFixedSize>::iterator sequence<T, nFixedSize>::erase(const_iterator itFirst, const_iterator itLast)
|
||||
{
|
||||
if (!itFirst.is_valid(*this)) throw XInvalidIterator();
|
||||
if (!itLast.is_valid(*this)) throw XInvalidIterator();
|
||||
if (empty()) return cbegin(); // Nothing to do
|
||||
if (itFirst == cend()) return cbegin(); // Nothing to do
|
||||
if (itFirst == itLast) return itFirst; // Nothing to do
|
||||
|
||||
// Determine location
|
||||
size_t nIndex = &itFirst[0] - data();
|
||||
size_t nCount = itLast == cend() ? (size() - nIndex) : (&itLast[0] - &itFirst[0]);
|
||||
|
||||
// Copy any leftover characters
|
||||
if (nCount < size() && nIndex + nCount < size())
|
||||
{
|
||||
std::copy_n(m_ptrData.get() + nIndex + nCount, size() - nIndex - nCount, m_ptrData.get() + nIndex);
|
||||
resize(size() - nCount);
|
||||
}
|
||||
else
|
||||
resize(nIndex);
|
||||
|
||||
return itFirst;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::push_back(const T& rtValue)
|
||||
{
|
||||
insert(end(), rtValue);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::push_back(T&& rtValue)
|
||||
{
|
||||
insert(end(), std::move(rtValue));
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::pop_back()
|
||||
{
|
||||
if (empty()) return; // Nothing to do
|
||||
erase(cend() - 1);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::resize(size_t nCount)
|
||||
{
|
||||
T t{};
|
||||
resize(nCount, t);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSize>
|
||||
inline void sequence<T, nFixedSize>::resize(size_t nCount, const value_type& rtValue)
|
||||
{
|
||||
if (!nCount)
|
||||
clear();
|
||||
else
|
||||
{
|
||||
size_t nCurrentLen = size();
|
||||
m_ptrData.resize(nCount);
|
||||
// False positive of CppCheck - condition is not always true. Suppress warning.
|
||||
// cppcheck-suppress knownConditionTrueFalse
|
||||
if (size() > nCurrentLen)
|
||||
std::fill_n(m_ptrData.get() + nCurrentLen, size() - nCurrentLen, rtValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// @cond DOXYGEN_IGNORE
|
||||
template <class T, size_t nFixedSize>
|
||||
template <size_t nFixedSize2>
|
||||
inline void sequence<T, nFixedSize>::swap(sequence<T, nFixedSize2>& rseq) noexcept
|
||||
{
|
||||
sequence seqTemp = std::move(rseq);
|
||||
rseq = std::move(*this);
|
||||
operator=(std::move(seqTemp));
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline void swap(sequence<T, nFixedSizeLeft>& rseqLeft, sequence<T, nFixedSizeRight>& rseqRight) noexcept
|
||||
{
|
||||
rseqLeft.swap(rseqRight);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator==(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight)
|
||||
{
|
||||
if (rseqLeft.size() != rseqRight.size()) return false;
|
||||
for (size_t nIndex = 0; nIndex < rseqLeft.size(); nIndex++)
|
||||
if (rseqLeft[nIndex] != rseqRight[nIndex]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator!=(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight)
|
||||
{
|
||||
return !operator==(rseqLeft, rseqRight);
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator<(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight)
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < std::min(rseqLeft.size(), rseqRight.size()); nIndex++)
|
||||
{
|
||||
if (rseqLeft[nIndex] < rseqRight[nIndex]) return true;
|
||||
if (rseqLeft[nIndex] > rseqRight[nIndex]) return false;
|
||||
}
|
||||
return rseqLeft.size() < rseqRight.size();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator<=(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight)
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < std::min(rseqLeft.size(), rseqRight.size()); nIndex++)
|
||||
{
|
||||
if (rseqLeft[nIndex] < rseqRight[nIndex]) return true;
|
||||
if (rseqLeft[nIndex] > rseqRight[nIndex]) return false;
|
||||
}
|
||||
return rseqLeft.size() <= rseqRight.size();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator>(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight)
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < std::min(rseqLeft.size(), rseqRight.size()); nIndex++)
|
||||
{
|
||||
if (rseqLeft[nIndex] < rseqRight[nIndex]) return false;
|
||||
if (rseqLeft[nIndex] > rseqRight[nIndex]) return true;
|
||||
}
|
||||
return rseqLeft.size() > rseqRight.size();
|
||||
}
|
||||
|
||||
template <class T, size_t nFixedSizeLeft, size_t nFixedSizeRight>
|
||||
inline bool operator>=(const sequence<T, nFixedSizeLeft>& rseqLeft, const sequence<T, nFixedSizeRight>& rseqRight)
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < std::min(rseqLeft.size(), rseqRight.size()); nIndex++)
|
||||
{
|
||||
if (rseqLeft[nIndex] < rseqRight[nIndex]) return false;
|
||||
if (rseqLeft[nIndex] > rseqRight[nIndex]) return true;
|
||||
}
|
||||
return rseqLeft.size() >= rseqRight.size();
|
||||
}
|
||||
|
||||
} // namespace sdv
|
||||
|
||||
|
||||
#endif // !defined SDV_SEQUENCE_INL
|
||||
297
export/support/serdes.h
Normal file
297
export/support/serdes.h
Normal file
@@ -0,0 +1,297 @@
|
||||
#ifndef SDV_SERDES_H
|
||||
#define SDV_SERDES_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "pointer.h"
|
||||
#include "sequence.h"
|
||||
#include "string.h"
|
||||
#include "any.h"
|
||||
#include "crc.h"
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Return the endianness for this platform.
|
||||
* @return The platform endianness enum value.
|
||||
*/
|
||||
inline constexpr EEndian GetPlatformEndianess()
|
||||
{
|
||||
// Since C++11 there is no programmatic way to test for endianness in a constexpr function. During runtime this is possible
|
||||
// using a union or a casting pointers. C++20 adds platform endian support and the implementation is likely done using
|
||||
// compiler constants.
|
||||
#if defined _MSC_VER
|
||||
return EEndian::little_endian;
|
||||
#elif defined __GNUC__
|
||||
return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? EEndian::big_endian : EEndian::little_endian;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Serializer class implementing the serialization of basic types and memory management.
|
||||
* @details The serialization into the buffer is aligned to the size of the value to store. For example, bytes can be stored at
|
||||
* any position. 16-bit words can be stored at 2 bytes boundary. 32-bits can be stored at 4 bytes boundary and 64-bits can be
|
||||
* stored at 8 bytes boundary.
|
||||
* The buffer allocation occurs in 1024 bytes at the time. The buffer is readjusted to the correct size just before detaching
|
||||
* the buffer.
|
||||
* @tparam eTargetEndianess The targeendiannessss determines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
*/
|
||||
template <sdv::EEndian eTargetEndianess = GetPlatformEndianess(), typename TCRC = crcCCITT_FALSE>
|
||||
class serializer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
serializer() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Push value into the serializer.
|
||||
* @tparam T Type of the value. Only arithmic and boolean types can be added. All other types need to be decomposed before
|
||||
* they can be added.
|
||||
* @param[in] tValue The value to add.
|
||||
*/
|
||||
template <typename T>
|
||||
void push_back(T tValue);
|
||||
|
||||
/**
|
||||
* @brief Attach a buffer to serialize into.
|
||||
* @param[in] rptrBuffer Reference to the buffer.
|
||||
* @param[in] nOffset Offset to start serializing.
|
||||
* @param[in] uiChecksum Current checksum value to continue with in the CRC calculation.
|
||||
*/
|
||||
void attach(pointer<uint8_t>&& rptrBuffer, size_t nOffset = 0, typename TCRC::TCRCType uiChecksum = 0u);
|
||||
|
||||
/**
|
||||
* @brief Detach the internal buffer and assign this buffer to the supplied pointer.
|
||||
* @param[out] rptrBuffer Reference to the pointer to assign this buffer to.
|
||||
*/
|
||||
void detach(pointer<uint8_t>& rptrBuffer);
|
||||
|
||||
/**
|
||||
* @brief Reserve space for a large amount of data.
|
||||
* @details Reserving space for data is done automatically, but only in small chunks. If large data is serialized, it is
|
||||
* more efficient to reserve the space at once before the serialization process takes place. This will prevent many smaller
|
||||
* reallocations taking place.
|
||||
* @param[in] nSize The size of new data to reserve space for.
|
||||
*/
|
||||
void reserve(size_t nSize);
|
||||
|
||||
/**
|
||||
* @brief Get a copy of the buffer pointer.
|
||||
* @return Smart pointer to the contained buffer.
|
||||
*/
|
||||
pointer<uint8_t> buffer() const;
|
||||
|
||||
/**
|
||||
* @brief Return the calculated checksum value of the serialized data.
|
||||
* @return Checksum value.
|
||||
*/
|
||||
typename TCRC::TCRCType checksum() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return the current offset.
|
||||
* @return The offset from the start of the stream.
|
||||
*/
|
||||
size_t offset() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Extend the buffer and align to the size of the variable.
|
||||
* @tparam T The type of the variable to use the size from.
|
||||
*/
|
||||
template <typename T>
|
||||
void extend_and_align();
|
||||
|
||||
pointer<uint8_t> m_ptrBuffer; ///< Buffer smart pointer.
|
||||
size_t m_nOffset = 0; ///< Current offset in the buffer.
|
||||
TCRC m_crcChecksum; ///< Calculated checksum value.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Deserializer class implementing the deserialization of basic types.
|
||||
* @details The deserialization from the buffer is aligned to the size of the value that was stored. For example, bytes are
|
||||
* stored at any position. 16-bit words are stored at 2 bytes aligned. 32-bits can be stored at 4 bytes aligned and 64-bits are
|
||||
* stored at 8 bytes aligned.
|
||||
* @tparam eSourceEndianess The source endianness determines whether to swap the bytes after retrieving them from the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
*/
|
||||
template <sdv::EEndian eSourceEndianess = GetPlatformEndianess(), typename TCRC = crcCCITT_FALSE>
|
||||
class deserializer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
deserializer();
|
||||
|
||||
/**
|
||||
* @brief Pull the value from the deserializer.
|
||||
* @tparam T Type of the value. Only arithmic and boolean types can be deserialized. All other types need to be composed
|
||||
* by deserialized arithmic and boolean types.
|
||||
* @param[out] rtValue Reference to the value to get.
|
||||
*/
|
||||
template <typename T>
|
||||
void pop_front(T& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Peek for the value from the deserializer without popping the value from the deserializer.
|
||||
* @tparam T Type of the value. Only arithmic and boolean types can be deserialized.
|
||||
* @param[out] rtValue Reference to the value to get.
|
||||
*/
|
||||
template <typename T>
|
||||
void peek_front(T& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Assign a buffer.
|
||||
* @param[in] pData Pointer to the data.
|
||||
* @param[in] nSize Data size;
|
||||
* @param[in] uiChecksum The checksum value that was calculated or 0 when no checksum checking should occur before
|
||||
* deserialization.
|
||||
*/
|
||||
void assign(const uint8_t* pData, size_t nSize, typename TCRC::TCRCType uiChecksum = 0);
|
||||
|
||||
/**
|
||||
* @brief Attach a buffer.
|
||||
* @remarks Providing the checksum will result a check through the data in the supplied buffer for the fitting checksum.
|
||||
* @param[in] rptrData Reference to the data pointer.
|
||||
* @param[in] uiChecksum The checksum value that was calculated or 0 when no checksum checking should occur.
|
||||
*/
|
||||
void attach(const pointer<uint8_t>& rptrData, typename TCRC::TCRCType uiChecksum = 0);
|
||||
|
||||
/**
|
||||
* @brief Return the calculated checksum value of the deserialized data.
|
||||
* @return Checksum value.
|
||||
*/
|
||||
typename TCRC::TCRCType checksum() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return the size of the contained buffer.
|
||||
* @return The size of the buffer.
|
||||
*/
|
||||
size_t size() const;
|
||||
|
||||
/**
|
||||
* @brief Return the current offset.
|
||||
* @return The offset from the start of the stream.
|
||||
*/
|
||||
size_t offset() const;
|
||||
|
||||
/**
|
||||
* @brief Return the leftover space within the buffer (size - offset).
|
||||
* @return The leftover space of the buffer.
|
||||
*/
|
||||
size_t remaining() const;
|
||||
|
||||
/**
|
||||
* @brief Skip to the supplied offset and start calculating the rest of the checksum with the supplied checksum.
|
||||
* @details This function allows navigating through the buffer or chunkwise deserialization. By supplying an offset, the
|
||||
* deserialization can start from the supplied offset using the supplied checksum to check any further. It is also possible
|
||||
* to do chunkwise deserialization, providing a small buffer covering only part of the large serialized package. Jumping to
|
||||
* the beginning of the buffer (offset 0), but explicitly setting the checksum, allows processing the package as if part of
|
||||
* a larger buffer.
|
||||
* @param[in] nOffset New offset to start processing from. Must be smaller than the buffer size.
|
||||
* @param[in] uiChecksum Checksum to start calculating the checksum value over the following data with.
|
||||
*/
|
||||
void jump(size_t nOffset, typename TCRC::TCRCType uiChecksum = 0);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Align the offset to the size of the variable.
|
||||
* @tparam T The type of the variable to use the size from.
|
||||
*/
|
||||
template <typename T>
|
||||
void align();
|
||||
|
||||
pointer<uint8_t> m_ptrBuffer; ///< Buffer smart pointer (might not be used).
|
||||
const uint8_t* m_pData = nullptr; ///< Pointer to the data.
|
||||
size_t m_nSize = 0; ///< Current buffer length.
|
||||
size_t m_nOffset = 0; ///< Current offset in the buffer.
|
||||
TCRC m_crcChecksum; ///< Calculated checksum value.
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Return the size of type T in serialized form.
|
||||
* @remarks Dependable on the size value, padding is added to align data.
|
||||
* @tparam T Type of the variable.
|
||||
* @param[in] rtValue Reference to the variable.
|
||||
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
||||
*/
|
||||
template <typename T>
|
||||
void ser_size(const T& rtValue, size_t& rnSize);
|
||||
} // namespace sdv
|
||||
|
||||
/**
|
||||
* @brief Serializer/deserializer namespace.
|
||||
*/
|
||||
namespace serdes
|
||||
{
|
||||
/**
|
||||
* @brief Serializer/deserializer class.
|
||||
* @tparam T Type of the variable.
|
||||
*/
|
||||
template <typename T>
|
||||
class CSerdes
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Calculate the size of the value in serialized form.
|
||||
* @remarks Dependable on the size value, padding is added to align data.
|
||||
* @param[in] rtValue Reference to the variable.
|
||||
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
||||
*/
|
||||
static void CalcSize(const T& rtValue, size_t& rnSize);
|
||||
|
||||
/**
|
||||
* @brief Stream the variable into the serializer.
|
||||
* @tparam eTargetEndianess The target endianness determines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rSerializer Reference to the serializer.
|
||||
* @param[in] rtValue Reference to the variable.
|
||||
* @return Reference to the serializer.
|
||||
*/
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
static sdv::serializer<eTargetEndianess, TCRC>& Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const T& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Stream a variable from the deserializer.
|
||||
* @tparam eSourceEndianess The target endianness determines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rDeserializer Reference to the deserializer.
|
||||
* @param[out] rtValue Reference to the variable to be filled.
|
||||
* @return Reference to the deserializer.
|
||||
*/
|
||||
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
||||
static sdv::deserializer<eSourceEndianess, TCRC>& Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, T& rtValue);
|
||||
};
|
||||
} // namespace serdes
|
||||
|
||||
/**
|
||||
* @brief Stream the variable into the serializer.
|
||||
* @tparam T Type of the variable.
|
||||
* @tparam eTargetEndianess The target endianness determines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rSerializer Reference to the serializer.
|
||||
* @param[in] rtValue Reference to the variable.
|
||||
* @return Reference to the serializer.
|
||||
*/
|
||||
template <typename T, sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
sdv::serializer<eTargetEndianess, TCRC>& operator<<(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const T& rtValue);
|
||||
|
||||
/**
|
||||
* @brief Stream a variable from the deserializer.
|
||||
* @tparam T Type of the variable.
|
||||
* @tparam eSourceEndianess The target endianness determines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rDeserializer Reference to the deserializer.
|
||||
* @param[out] rtValue Reference to the variable to be filled.
|
||||
* @return Reference to the deserializer.
|
||||
*/
|
||||
template <typename T, sdv::EEndian eSourceEndianess, typename TCRC>
|
||||
sdv::deserializer<eSourceEndianess, TCRC>& operator>>(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, T& rtValue);
|
||||
|
||||
#include "serdes.inl"
|
||||
|
||||
#endif // !defined SDV_SERDES_H
|
||||
651
export/support/serdes.inl
Normal file
651
export/support/serdes.inl
Normal file
@@ -0,0 +1,651 @@
|
||||
#ifndef SDV_SERDES_INL
|
||||
#define SDV_SERDES_INL
|
||||
|
||||
#ifndef SDV_SERDES_H
|
||||
#error Do not include "serdes.inl" directly. Include "serdes.h" instead!
|
||||
#endif //!defined SDV_SERDES_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
inline serializer<eTargetEndianess, TCRC>::serializer() noexcept
|
||||
{}
|
||||
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
template <typename T>
|
||||
inline void serializer<eTargetEndianess, TCRC>::push_back(T tValue)
|
||||
{
|
||||
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, bool> || std::is_enum_v<T>);
|
||||
|
||||
// Make certain the data fits and align to the proper address.
|
||||
extend_and_align<T>();
|
||||
|
||||
// Without buffer there is no serialization.
|
||||
if (!m_ptrBuffer) return;
|
||||
|
||||
if constexpr (eTargetEndianess == GetPlatformEndianess()) // No swapping
|
||||
*reinterpret_cast<T*>(m_ptrBuffer.get() + m_nOffset) = tValue;
|
||||
else // Swap bytes
|
||||
{
|
||||
uint8_t* pData = m_ptrBuffer.get() + m_nOffset;
|
||||
for (size_t nIndex = 0; nIndex < sizeof(T); nIndex++)
|
||||
pData[nIndex] = reinterpret_cast<uint8_t*>(&tValue)[sizeof(T) - nIndex - 1];
|
||||
}
|
||||
|
||||
// Calculate CRC
|
||||
for (size_t nIndex = m_nOffset; nIndex < m_nOffset + sizeof(T); nIndex++)
|
||||
m_crcChecksum.add(m_ptrBuffer[nIndex]);
|
||||
|
||||
// Increase offset
|
||||
m_nOffset += sizeof(T);
|
||||
}
|
||||
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
inline void serializer<eTargetEndianess, TCRC>::attach(pointer<uint8_t>&& rptrBuffer, size_t nOffset /*= 0*/, typename TCRC::TCRCType uiChecksum /*= 0u*/)
|
||||
{
|
||||
if (nOffset > rptrBuffer.size())
|
||||
{
|
||||
XOffsetPastBufferSize exception;
|
||||
exception.uiOffset = static_cast<uint32_t>(nOffset);
|
||||
exception.uiSize = static_cast<uint32_t>(rptrBuffer.size());
|
||||
throw exception;
|
||||
}
|
||||
|
||||
m_ptrBuffer = std::move(rptrBuffer);
|
||||
m_nOffset = nOffset;
|
||||
m_crcChecksum.set_checksum(uiChecksum);
|
||||
}
|
||||
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
inline void serializer<eTargetEndianess, TCRC>::detach(pointer<uint8_t>& rptrBuffer)
|
||||
{
|
||||
// Reduce the buffer to the currently calculated offset.
|
||||
if (m_ptrBuffer)
|
||||
m_ptrBuffer.resize(m_nOffset);
|
||||
|
||||
// Assign the buffer
|
||||
rptrBuffer = std::move(m_ptrBuffer);
|
||||
|
||||
// Clear the offset
|
||||
m_nOffset = 0;
|
||||
}
|
||||
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
inline void serializer<eTargetEndianess, TCRC>::reserve(size_t nSize)
|
||||
{
|
||||
// Check whether reservation is required.
|
||||
if (m_ptrBuffer.size() < m_nOffset + nSize)
|
||||
m_ptrBuffer.resize(m_ptrBuffer.size() + nSize);
|
||||
}
|
||||
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
inline pointer<uint8_t> serializer<eTargetEndianess, TCRC>::buffer() const
|
||||
{
|
||||
pointer<uint8_t> ptrLocal = m_ptrBuffer;
|
||||
|
||||
// Reduce the buffer to the currently calculated offset.
|
||||
if (ptrLocal)
|
||||
ptrLocal.resize(m_nOffset);
|
||||
|
||||
// Return a copy of the smart pointer to the internal buffer.
|
||||
return ptrLocal;
|
||||
}
|
||||
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
inline typename TCRC::TCRCType serializer<eTargetEndianess, TCRC>::checksum() const noexcept
|
||||
{
|
||||
return m_crcChecksum.get_checksum();
|
||||
}
|
||||
|
||||
template <EEndian eTargetEndianess, typename TCRC>
|
||||
inline size_t serializer<eTargetEndianess, TCRC>::offset() const
|
||||
{
|
||||
return m_nOffset;
|
||||
}
|
||||
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
template <typename T>
|
||||
inline void serializer<eTargetEndianess, TCRC>::extend_and_align()
|
||||
{
|
||||
// Align the offset position dependable on the size of the variable to add.
|
||||
size_t nOffsetNew = m_nOffset;
|
||||
if ((nOffsetNew & (sizeof(T) - 1)) != 0)
|
||||
nOffsetNew = (nOffsetNew | (sizeof(T) - 1)) + 1;
|
||||
|
||||
// Check if the buffer size is large enough to hold the alignment and the type.
|
||||
// If not, extend with 1024 bytes.
|
||||
if ((nOffsetNew + sizeof(T)) > m_ptrBuffer.size())
|
||||
m_ptrBuffer.resize(m_ptrBuffer.size() + 1024);
|
||||
|
||||
// Fill the buffer with padding and add the padding to the checksum value calculation.
|
||||
for (size_t nIndex = m_nOffset; nIndex != nOffsetNew; nIndex++)
|
||||
{
|
||||
m_ptrBuffer[m_nOffset] = 0x00;
|
||||
m_crcChecksum.add(static_cast<uint8_t>(0x00));
|
||||
}
|
||||
|
||||
// Set the new offset
|
||||
m_nOffset = nOffsetNew;
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
inline deserializer<eSourceEndianess, TCRC>::deserializer()
|
||||
{}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
template <typename T>
|
||||
inline void deserializer<eSourceEndianess, TCRC>::pop_front(T& rtValue)
|
||||
{
|
||||
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, bool> || std::is_enum_v<T>);
|
||||
|
||||
// Without buffer there is no deserialization.
|
||||
if (!m_ptrBuffer) return;
|
||||
|
||||
// Align to the proper address.
|
||||
align<T>();
|
||||
|
||||
// Check whether the buffer contains the data requested
|
||||
if (m_ptrBuffer.size() < m_nOffset + sizeof(T))
|
||||
{
|
||||
sdv::XBufferTooSmall exception;
|
||||
exception.uiSize = m_nOffset + sizeof(T);
|
||||
exception.uiCapacity = m_ptrBuffer.size();
|
||||
throw exception;
|
||||
}
|
||||
|
||||
// Calculate CRC
|
||||
for (size_t nIndex = m_nOffset; nIndex < m_nOffset + sizeof(T); nIndex++)
|
||||
m_crcChecksum.add(m_ptrBuffer[nIndex]);
|
||||
|
||||
// Copy data
|
||||
if constexpr (eSourceEndianess == GetPlatformEndianess()) // No swapping
|
||||
rtValue = *reinterpret_cast<T*>(m_ptrBuffer.get() + m_nOffset);
|
||||
else // Swap bytes
|
||||
{
|
||||
const uint8_t* pData = m_ptrBuffer.get() + m_nOffset;
|
||||
for (size_t nIndex = 0; nIndex < sizeof(T); nIndex++)
|
||||
reinterpret_cast<uint8_t*>(&rtValue)[nIndex] = pData[sizeof(T) - nIndex - 1];
|
||||
}
|
||||
|
||||
// Increase offset
|
||||
m_nOffset += sizeof(T);
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
template <typename T>
|
||||
inline void deserializer<eSourceEndianess, TCRC>::peek_front(T& rtValue)
|
||||
{
|
||||
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, bool> || std::is_enum_v<T>);
|
||||
|
||||
// Without buffer there is no deserialization.
|
||||
if (!m_ptrBuffer) return;
|
||||
|
||||
// Store the offset and checksum
|
||||
size_t nOffsetTemp = m_nOffset;
|
||||
auto nChecksum = m_crcChecksum.get_checksum();
|
||||
|
||||
// Make certain the data fits and align to the proper address.
|
||||
align<T>();
|
||||
|
||||
// Check whether the buffer contains the data requested
|
||||
if (m_ptrBuffer.size() < m_nOffset + sizeof(T))
|
||||
{
|
||||
sdv::XBufferTooSmall exception;
|
||||
exception.uiSize = m_nOffset + sizeof(T);
|
||||
exception.uiCapacity = m_ptrBuffer.size();
|
||||
throw exception;
|
||||
}
|
||||
|
||||
// Copy data
|
||||
if constexpr (eSourceEndianess == GetPlatformEndianess()) // No swapping
|
||||
rtValue = *reinterpret_cast<T*>(m_ptrBuffer.get() + m_nOffset);
|
||||
else // Swap bytes
|
||||
{
|
||||
const uint8_t* pData = m_ptrBuffer.get() + m_nOffset;
|
||||
for (size_t nIndex = 0; nIndex < sizeof(T); nIndex++)
|
||||
reinterpret_cast<uint8_t*>(&rtValue)[nIndex] = pData[sizeof(T) - nIndex - 1];
|
||||
}
|
||||
|
||||
// Reset the offset and checksum
|
||||
m_nOffset = nOffsetTemp;
|
||||
m_crcChecksum.set_checksum(nChecksum);
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
inline void deserializer<eSourceEndianess, TCRC>::assign(const uint8_t* pData, size_t nSize, typename TCRC::TCRCType uiChecksum /*= 0*/)
|
||||
{
|
||||
if (!pData) throw XNullPointer();
|
||||
|
||||
// Check the checksum value
|
||||
if (uiChecksum)
|
||||
{
|
||||
crcCCITT_FALSE crcChecksum;
|
||||
for (size_t nIndex = 0; nIndex < nSize; nIndex++)
|
||||
crcChecksum.add(pData[nIndex]);
|
||||
if (crcChecksum.get_checksum() != uiChecksum)
|
||||
{
|
||||
XHashNotMatching exception;
|
||||
exception.uiCalculated = crcChecksum.get_checksum();
|
||||
exception.uiProvided = uiChecksum;
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
m_pData = pData;
|
||||
m_nSize = nSize;
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
inline void deserializer<eSourceEndianess, TCRC>::attach(const pointer<uint8_t>& rptrData, typename TCRC::TCRCType uiChecksum /*= 0*/)
|
||||
{
|
||||
m_ptrBuffer = rptrData;
|
||||
assign(rptrData.get(), rptrData.size(), uiChecksum);
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
inline typename TCRC::TCRCType deserializer<eSourceEndianess, TCRC>::checksum() const noexcept
|
||||
{
|
||||
return m_crcChecksum.get_checksum();
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
template <typename T>
|
||||
inline void deserializer<eSourceEndianess, TCRC>::align()
|
||||
{
|
||||
// Align the offset position dependable on the size of the variable to get.
|
||||
if ((m_nOffset & (sizeof(T) - 1)) != 0)
|
||||
{
|
||||
size_t nOffsetNew = (m_nOffset | (sizeof(T) - 1)) + 1;
|
||||
|
||||
// Add the padding to the checksum value calculation.
|
||||
for (size_t nIndex = m_nOffset; nIndex != nOffsetNew; nIndex++)
|
||||
m_crcChecksum.add(m_ptrBuffer[nIndex]);
|
||||
|
||||
m_nOffset = nOffsetNew;
|
||||
}
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
inline size_t deserializer<eSourceEndianess, TCRC>::size() const
|
||||
{
|
||||
return m_nSize;
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
inline size_t deserializer<eSourceEndianess, TCRC>::offset() const
|
||||
{
|
||||
return m_nOffset;
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
inline size_t deserializer<eSourceEndianess, TCRC>::remaining() const
|
||||
{
|
||||
return m_nSize - std::min(m_nOffset, m_nSize);
|
||||
}
|
||||
|
||||
template <EEndian eSourceEndianess, typename TCRC>
|
||||
void deserializer<eSourceEndianess, TCRC>::jump(size_t nOffset, typename TCRC::TCRCType uiChecksum /*= 0*/)
|
||||
{
|
||||
if (nOffset > m_ptrBuffer.size())
|
||||
{
|
||||
XOffsetPastBufferSize exception;
|
||||
exception.uiOffset = static_cast<uint32_t>(nOffset);
|
||||
exception.uiSize = static_cast<uint32_t>(m_ptrBuffer.size());
|
||||
throw exception;
|
||||
}
|
||||
|
||||
m_nOffset = nOffset;
|
||||
m_crcChecksum.set_checksum(uiChecksum);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void ser_size(const T& rtValue, size_t& rnSize)
|
||||
{
|
||||
serdes::CSerdes<T>::CalcSize(rtValue, rnSize);
|
||||
}
|
||||
} // namespace sdv
|
||||
|
||||
namespace serdes
|
||||
{
|
||||
template <typename T>
|
||||
inline void CSerdes<T>::CalcSize([[maybe_unused]] const T& rtValue, size_t& rnSize)
|
||||
{
|
||||
static_assert(std::is_fundamental_v<T> || std::is_enum_v<T>);
|
||||
|
||||
// Add alignment if necessary
|
||||
size_t nBytes = rnSize % sizeof(T);
|
||||
if (nBytes) rnSize += sizeof(T) - nBytes;
|
||||
|
||||
// Increase the size
|
||||
rnSize += sizeof(T);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
inline sdv::serializer<eTargetEndianess, TCRC>& CSerdes<T>::Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const T& rtValue)
|
||||
{
|
||||
rSerializer.push_back(rtValue);
|
||||
return rSerializer;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
||||
inline sdv::deserializer<eSourceEndianess, TCRC>& CSerdes<T>::Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, T& rtValue)
|
||||
{
|
||||
rDeserializer.pop_front(rtValue);
|
||||
return rDeserializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialization of serializer/deserializer class.
|
||||
* @tparam T Type of the variable.
|
||||
* @tparam nSize The size of the provided array.
|
||||
*/
|
||||
template <typename T, size_t nSize>
|
||||
class CSerdes<T[nSize]>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Calculate the size of the value in serialized form.
|
||||
* @remarks Dependable on the size value, padding is added to align data.
|
||||
* @param[in] rrgtValue Reference to an array with variables.
|
||||
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
||||
*/
|
||||
static void CalcSize([[maybe_unused]] const T(&rrgtValue)[nSize], size_t& rnSize)
|
||||
{
|
||||
for (const T& rtValue : rrgtValue)
|
||||
sdv::ser_size(rtValue, rnSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the variable into the serializer.
|
||||
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rSerializer Reference to the serializer.
|
||||
* @param[in] rrgtValue Reference to an array with variables.
|
||||
* @return Reference to the serializer.
|
||||
*/
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
static sdv::serializer<eTargetEndianess, TCRC>& Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const T(&rrgtValue)[nSize])
|
||||
{
|
||||
// Reserve the space in the serializer (this speeds up the serialization process).
|
||||
rSerializer.reserve(nSize * sizeof(T));
|
||||
|
||||
// Serialize all entries
|
||||
for (const T& rtValue : rrgtValue)
|
||||
CSerdes<T>::Serialize(rSerializer, rtValue);
|
||||
return rSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream a variable from the deserializer.
|
||||
* @tparam eSourceEndianess The source endianess detemines whether to swap the bytes after retrieving them from the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rDeserializer Reference to the deserializer.
|
||||
* @param[out] rrgtValue Reference to an array with variables to be filled.
|
||||
* @return Reference to the deserializer.
|
||||
*/
|
||||
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
||||
static sdv::deserializer<eSourceEndianess, TCRC>& Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, T(&rrgtValue)[nSize])
|
||||
{
|
||||
for (T& rtValue : rrgtValue)
|
||||
CSerdes<T>::Deserialize(rDeserializer, rtValue);
|
||||
return rDeserializer;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specialization of serializer/deserializer class.
|
||||
* @tparam T Type of the variable.
|
||||
* @tparam nFixedSize The fixed size of the pointer or 0 when the pointer is dynamic.
|
||||
*/
|
||||
template <typename T, size_t nFixedSize>
|
||||
class CSerdes<sdv::pointer<T, nFixedSize>>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Calculate the size of the value in serialized form.
|
||||
* @remarks Dependable on the size value, padding is added to align data.
|
||||
* @param[in] rptrValue Reference to the pointer.
|
||||
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
||||
*/
|
||||
static void CalcSize(const sdv::pointer<T, nFixedSize>& rptrValue, size_t& rnSize)
|
||||
{
|
||||
sdv::ser_size(static_cast<uint64_t>(rptrValue.size()), rnSize);
|
||||
if constexpr (std::is_fundamental_v<T>)
|
||||
rnSize += rptrValue.size() * sizeof(T);
|
||||
else
|
||||
{
|
||||
for (size_t n = 0; n < rptrValue.size(); n++)
|
||||
sdv::ser_size(rptrValue.get()[n], rnSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the pointer variable into the serializer.
|
||||
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rSerializer Reference to the serializer.
|
||||
* @param[in] rptrValue Reference to the pointer.
|
||||
* @return Reference to the serializer.
|
||||
*/
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
static sdv::serializer<eTargetEndianess, TCRC>& Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const sdv::pointer<T, nFixedSize>& rptrValue)
|
||||
{
|
||||
rSerializer << static_cast<uint64_t>(rptrValue.size());
|
||||
if (rptrValue)
|
||||
{
|
||||
// Reserve the space in the serializer (this speeds up the serialization process).
|
||||
rSerializer.reserve(rptrValue.size() * sizeof(T));
|
||||
|
||||
// Serialize all entries
|
||||
const T* ptValue = rptrValue.get();
|
||||
for (size_t nIndex = 0; nIndex < rptrValue.size(); nIndex++)
|
||||
CSerdes<T>::Serialize(rSerializer, ptValue[nIndex]);
|
||||
}
|
||||
return rSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the pointer variable from the deserializer.
|
||||
* @tparam eSourceEndianess The source endianess detemines whether to swap the bytes after retrieving them from the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rDeserializer Reference to the deserializer.
|
||||
* @param[in] rptrValue Reference to the pointer.
|
||||
* @return Reference to the deserializer.
|
||||
*/
|
||||
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
||||
static sdv::deserializer<eSourceEndianess, TCRC>& Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, sdv::pointer<T, nFixedSize>& rptrValue)
|
||||
{
|
||||
uint64_t nSize = 0;
|
||||
rDeserializer >> nSize;
|
||||
if (nSize * sizeof(T) > rDeserializer.remaining())
|
||||
{
|
||||
sdv::XOffsetPastBufferSize exception;
|
||||
exception.uiSize = rDeserializer.size();
|
||||
exception.uiOffset = rDeserializer.offset() + nSize * sizeof(T);
|
||||
throw exception;
|
||||
}
|
||||
rptrValue.resize(nSize);
|
||||
if (nSize && rptrValue)
|
||||
{
|
||||
T* ptValue = rptrValue.get();
|
||||
for (size_t nIndex = 0; nIndex < nSize; nIndex++)
|
||||
CSerdes<T>::Deserialize(rDeserializer, ptValue[nIndex]);
|
||||
}
|
||||
return rDeserializer;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @brief Specialization of serializer/deserializer class.
|
||||
* @tparam T Type of the variable.
|
||||
* @tparam nFixedSize The fixed size of the sequence or 0 when the sequence is dynamic.
|
||||
*/
|
||||
template <typename T, size_t nFixedSize>
|
||||
class CSerdes<sdv::sequence<T, nFixedSize>>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Calculate the size of the value in serialized form.
|
||||
* @remarks Dependable on the size value, padding is added to align data.
|
||||
* @param[in] rseqValue Reference to the sequence.
|
||||
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
||||
*/
|
||||
static void CalcSize(const sdv::sequence<T, nFixedSize>& rseqValue, size_t& rnSize)
|
||||
{
|
||||
sdv::ser_size(static_cast<uint64_t>(rseqValue.size()), rnSize);
|
||||
if constexpr (std::is_fundamental_v<T>)
|
||||
rnSize += rseqValue.size() * sizeof(T);
|
||||
else
|
||||
{
|
||||
for (const T& rValue: rseqValue)
|
||||
sdv::ser_size(rValue, rnSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the sequence variable into the serializer.
|
||||
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rSerializer Reference to the serializer.
|
||||
* @param[in] rseqValue Reference to the sequence.
|
||||
* @return Reference to the serializer.
|
||||
*/
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
static sdv::serializer<eTargetEndianess, TCRC>& Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const sdv::sequence<T, nFixedSize>& rseqValue)
|
||||
{
|
||||
rSerializer << static_cast<uint64_t>(rseqValue.size());
|
||||
|
||||
// Reserve the space in the serializer (this speeds up the serialization process).
|
||||
rSerializer.reserve(rseqValue.size() * sizeof(T));
|
||||
|
||||
// Serialize all entries
|
||||
for (const T& rtValue : rseqValue)
|
||||
CSerdes<T>::Serialize(rSerializer, rtValue);
|
||||
return rSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the sequence variable from the deserializer.
|
||||
* @tparam eSourceEndianess The source endianess detemines whether to swap the bytes after retrieving them from the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rDeserializer Reference to the deserializer.
|
||||
* @param[in] rseqValue Reference to the sequence.
|
||||
* @return Reference to the deserializer.
|
||||
*/
|
||||
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
||||
static sdv::deserializer<eSourceEndianess, TCRC>& Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, sdv::sequence<T, nFixedSize>& rseqValue)
|
||||
{
|
||||
uint64_t nSize = 0;
|
||||
rDeserializer >> nSize;
|
||||
if (nSize * sizeof(T) > rDeserializer.remaining())
|
||||
{
|
||||
sdv::XOffsetPastBufferSize exception;
|
||||
exception.uiSize = rDeserializer.size();
|
||||
exception.uiOffset = rDeserializer.offset() + nSize * sizeof(T);
|
||||
throw exception;
|
||||
}
|
||||
rseqValue.resize(nSize);
|
||||
if (nSize)
|
||||
{
|
||||
for (T& rtValue : rseqValue)
|
||||
CSerdes<T>::Deserialize(rDeserializer, rtValue);
|
||||
}
|
||||
return rDeserializer;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specialization of serializer/deserializer class.
|
||||
* @tparam TCharType Type of the string.
|
||||
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @tparam bUnicode When set, the string is a unicode string.
|
||||
* @tparam nFixedSize The fixed size of the string or 0 when the string is dynamic.
|
||||
*/
|
||||
template <typename TCharType, bool bUnicode, size_t nFixedSize>
|
||||
class CSerdes<sdv::string_base<TCharType, bUnicode, nFixedSize>>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Calculate the size of the value in serialized form.
|
||||
* @remarks Dependable on the size value, padding is added to align data.
|
||||
* @param[in] rssValue Reference to the string.
|
||||
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
||||
*/
|
||||
static void CalcSize(const sdv::string_base<TCharType, bUnicode, nFixedSize>& rssValue, size_t& rnSize)
|
||||
{
|
||||
sdv::ser_size(static_cast<uint64_t>(rssValue.size()), rnSize);
|
||||
rnSize += rssValue.size() * sizeof(TCharType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the string variable into the serializer.
|
||||
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rSerializer Reference to the serializer.
|
||||
* @param[in] rssValue Reference to the string.
|
||||
* @return Reference to the serializer.
|
||||
*/
|
||||
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
static sdv::serializer<eTargetEndianess, TCRC>& Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const sdv::string_base<TCharType, bUnicode, nFixedSize>& rssValue)
|
||||
{
|
||||
rSerializer << static_cast<uint64_t>(rssValue.size());
|
||||
|
||||
// Reserve the space in the serializer (this speeds up the serialization process).
|
||||
rSerializer.reserve(rssValue.size() * sizeof(TCharType));
|
||||
|
||||
// Serialize all entries
|
||||
for (TCharType tValue : rssValue)
|
||||
CSerdes<TCharType>::Serialize(rSerializer, tValue);
|
||||
return rSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stream the string variable from the deserializer.
|
||||
* @tparam eSourceEndianess The source endianess detemines whether to swap the bytes after retrieving them from the buffer.
|
||||
* @tparam TCRC The CRC type to use for the checksum calculation.
|
||||
* @param[in] rDeserializer Reference to the deserializer.
|
||||
* @param[in] rssValue Reference to the string.
|
||||
* @return Reference to the deserializer.
|
||||
*/
|
||||
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
||||
static sdv::deserializer<eSourceEndianess, TCRC>& Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, sdv::string_base<TCharType, bUnicode, nFixedSize>& rssValue)
|
||||
{
|
||||
uint64_t nSize = 0;
|
||||
rDeserializer >> nSize;
|
||||
if (nSize * sizeof(TCharType) > rDeserializer.remaining())
|
||||
{
|
||||
sdv::XOffsetPastBufferSize exception;
|
||||
exception.uiSize = rDeserializer.size();
|
||||
exception.uiOffset = rDeserializer.offset() + nSize * sizeof(TCharType);
|
||||
throw exception;
|
||||
}
|
||||
rssValue.resize(nSize);
|
||||
if (nSize)
|
||||
{
|
||||
for (TCharType& rtValue : rssValue)
|
||||
CSerdes<TCharType>::Deserialize(rDeserializer, rtValue);
|
||||
}
|
||||
return rDeserializer;
|
||||
}
|
||||
};
|
||||
} // namespace serdes
|
||||
|
||||
template <typename T, sdv::EEndian eTargetEndianess, typename TCRC>
|
||||
inline sdv::serializer<eTargetEndianess, TCRC>& operator<<(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const T& rtValue)
|
||||
{
|
||||
serdes::CSerdes<T>::Serialize(rSerializer, rtValue);
|
||||
return rSerializer;
|
||||
}
|
||||
|
||||
template <typename T, sdv::EEndian eSourceEndianess, typename TCRC>
|
||||
inline sdv::deserializer<eSourceEndianess, TCRC>& operator>>(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, T& rtValue)
|
||||
{
|
||||
serdes::CSerdes<T>::Deserialize(rDeserializer, rtValue);
|
||||
return rDeserializer;
|
||||
}
|
||||
|
||||
#endif // !defined SDV_SERDES_INL
|
||||
832
export/support/signal_support.h
Normal file
832
export/support/signal_support.h
Normal file
@@ -0,0 +1,832 @@
|
||||
/**
|
||||
*
|
||||
* @file signal_support.h
|
||||
* @brief This file provides base-implementations and helpers for signals and signal handling.
|
||||
* @version 0.1
|
||||
* @date 2022.11.14
|
||||
* @author Thomas.pfleiderer@zf.com
|
||||
* @copyright Copyright ZF Friedrichshaven AG (c) 2022
|
||||
*
|
||||
*/
|
||||
#ifndef SIGNAL_SUPPORT_H
|
||||
#define SIGNAL_SUPPORT_H
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "../interfaces/dispatch.h"
|
||||
#include "local_service_access.h"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
namespace core
|
||||
{
|
||||
// Forward declaration
|
||||
class CSignal;
|
||||
class CTrigger;
|
||||
class CTransaction;
|
||||
|
||||
/**
|
||||
* @brief Dispatch service convenience class.
|
||||
*/
|
||||
class CDispatchService
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor. The constructor will automatically try to connect to the Data Dispatch Service.
|
||||
*/
|
||||
CDispatchService();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CDispatchService();
|
||||
|
||||
/**
|
||||
* @brief Register a signal for sending over the network; reading from the dispatch service. Data is provided by the
|
||||
* signal publisher and dependable on the requested behavior stored until it is sent.
|
||||
* @param[in] rssSignalName Reference to the name of the signal. To guarantee uniqueness, it is preferred to add the group
|
||||
* hierarchy to the signal name separated by a dot. E.g. with CAN: MAB.BcmChas1Fr03.SteerReCtrlReqAgReq
|
||||
* @param[in] tDefVal The default value of the signal.
|
||||
* @return Returns the initialized signal class or an empty signal when the signal already existed or the dispatch
|
||||
* service could not be reached.
|
||||
*/
|
||||
template <typename TType>
|
||||
CSignal RegisterTxSignal(const u8string& rssSignalName, TType tDefVal);
|
||||
|
||||
/**
|
||||
* @brief Register a signal for reception over the network; providing to the dispatch service.
|
||||
* @param[in] rssSignalName Name of the signal. To guarantee uniqueness, it is preferred to add the group hierarchy to
|
||||
* the signal name separated by a dot. E.g. with CAN: MAB.BcmChas1Fr03.SteerReCtrlReqAgReq
|
||||
* @return Returns the initialized signal class or an empty signal when the signal already existed or the dispatch
|
||||
* service could not be reached.
|
||||
*/
|
||||
CSignal RegisterRxSignal(const u8string& rssSignalName);
|
||||
|
||||
/**
|
||||
* @brief Add a publisher of signal data.
|
||||
* @param[in] rssSignalName Reference to the name of the signal to publish data for.
|
||||
* @return Returns the initialized signal class or an empty signal when the signal was nor registered before or the
|
||||
* dispatch service could not be reached.
|
||||
*/
|
||||
CSignal AddPublisher(const u8string& rssSignalName);
|
||||
|
||||
/**
|
||||
* @brief Subscribe to a signal event.
|
||||
* @param[in] rssSignalName Reference to the name of the signal to publish data for.
|
||||
* @param[in] func Function to call when data is received.
|
||||
* @return Returns the initialized signal class or an empty signal when the signal was nor registered before or the
|
||||
* dispatch service could not be reached.
|
||||
*/
|
||||
CSignal Subscribe(const u8string& rssSignalName, std::function<void(any_t)> func);
|
||||
|
||||
/**
|
||||
* @brief Subscribe to a signal event and allow updating the signal value automatically.
|
||||
* @tparam TType Type of the signal data.
|
||||
* @param[in] rssSignalName Reference to the name of the signal to publish data for.
|
||||
* @param[in] rtVal Reference to the value to be filled automatically.
|
||||
* @return Returns the initialized signal class or an empty signal when the signal was nor registered before or the
|
||||
* dispatch service could not be reached.
|
||||
*/
|
||||
template <typename TType>
|
||||
CSignal Subscribe(const u8string& rssSignalName, std::atomic<TType>& rtVal);
|
||||
|
||||
/**
|
||||
* @brief Get a list of registered signals.
|
||||
* @return List of registration functions.
|
||||
*/
|
||||
sequence<SSignalRegistration> GetRegisteredSignals() const;
|
||||
|
||||
/**
|
||||
* @brief Create a transaction.
|
||||
* @return Returns the transaction object. Returns an empty transaction object when the limit of transactions has been
|
||||
* exhausted.
|
||||
*/
|
||||
CTransaction CreateTransaction();
|
||||
|
||||
/**
|
||||
* @brief Finish a transaction.
|
||||
* @param[in] rTransaction Reference to the transaction to finish.
|
||||
*/
|
||||
void FinishTransaction(CTransaction& rTransaction);
|
||||
|
||||
/**
|
||||
* @brief Create a trigger object for the TX interface.
|
||||
* @param[in] fnExecute Callback function that is triggered.
|
||||
* @param[in] bSpontaneous When set, will be triggered on signal changes.
|
||||
* @param[in] uiDelayTime The minimal time between two triggers.
|
||||
* @param[in] uiPeriod When not 0, triggers periodically (time in ms).
|
||||
* @param[in] bOnlyWhenActive When set, periodic trigger will only occur once if the signal value equals the default
|
||||
* value.
|
||||
* @return If successful, returns the initialized trigger object or an empty trigger object when not successful.
|
||||
*/
|
||||
CTrigger CreateTxTrigger(std::function<void()> fnExecute, bool bSpontaneous = true, uint32_t uiDelayTime = 0,
|
||||
uint32_t uiPeriod = 0ul, bool bOnlyWhenActive = false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Transaction wrapping class
|
||||
*/
|
||||
class CTransaction
|
||||
{
|
||||
/// Dispatch service friend class.
|
||||
friend CDispatchService;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CTransaction() = default;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor for transaction.
|
||||
* @param[in] rDispatch Reference to the dispatch class.
|
||||
* @param[in] pTransaction Pointer to the interface of the transaction object.
|
||||
*/
|
||||
CTransaction(CDispatchService& rDispatch, IInterfaceAccess* pTransaction) :
|
||||
m_pDispatch(&rDispatch), m_pTransaction(pTransaction)
|
||||
{}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Copy constructor (deleted)
|
||||
* @param[in] rTransaction Reference to the transaction to copy from.
|
||||
*/
|
||||
CTransaction(const CTransaction& rTransaction) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
* @param[in] rTransaction Reference to the transaction to move from.
|
||||
*/
|
||||
CTransaction(CTransaction&& rTransaction) :
|
||||
m_pDispatch(rTransaction.m_pDispatch), m_pTransaction(rTransaction.m_pTransaction)
|
||||
{
|
||||
rTransaction.m_pDispatch = nullptr;
|
||||
rTransaction.m_pTransaction = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CTransaction()
|
||||
{
|
||||
Finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator (deleted)
|
||||
* @param[in] rTransaction Reference to the transaction to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CTransaction& operator=(const CTransaction& rTransaction) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move operator
|
||||
* @param[in] rTransaction Reference to the transaction to move from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CTransaction& operator=(CTransaction&& rTransaction)
|
||||
{
|
||||
Finish();
|
||||
m_pDispatch = rTransaction.m_pDispatch;
|
||||
m_pTransaction = rTransaction.m_pTransaction;
|
||||
rTransaction.m_pDispatch = nullptr;
|
||||
rTransaction.m_pTransaction = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Valid transaction?
|
||||
*/
|
||||
operator bool() const { return m_pTransaction ? true : false; }
|
||||
|
||||
/**
|
||||
* @brief Finish the transaction.
|
||||
*/
|
||||
void Finish()
|
||||
{
|
||||
if (m_pDispatch && m_pTransaction)
|
||||
{
|
||||
IObjectDestroy* pDestroy = m_pTransaction->GetInterface<IObjectDestroy>();
|
||||
pDestroy->DestroyObject();
|
||||
}
|
||||
|
||||
m_pDispatch = nullptr;
|
||||
m_pTransaction = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the transaction interface.
|
||||
* @return The transaction interface that was used for this transaction or nullptr when the transaction was started yet
|
||||
* or had finished before.
|
||||
*/
|
||||
IInterfaceAccess* GetTransaction() const
|
||||
{
|
||||
return m_pTransaction;
|
||||
}
|
||||
|
||||
private:
|
||||
CDispatchService* m_pDispatch = nullptr; ///< Pointer to the dispatch class.
|
||||
IInterfaceAccess* m_pTransaction = nullptr; ///< Transaction object
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Signal class wrapping the signal access functions.
|
||||
*/
|
||||
class CSignal
|
||||
{
|
||||
friend CDispatchService;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CSignal() = default;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor for signal interface received by a call to RegisterTxSignal, RegisterRxSignal or
|
||||
* RequestSignalPublisher.
|
||||
* @param[in] rDispatch Reference to the dispatch class.
|
||||
* @param[in] rssName Reference to the string holding the name of the signal.
|
||||
* @param[in] pSignal The signal interface access allowing access to the ISignalWrite interface.
|
||||
* @param[in] bRegistering Boolean indicating that the signal was created using a registration function rather than an
|
||||
* access function.
|
||||
*/
|
||||
CSignal(CDispatchService& rDispatch, const u8string& rssName, IInterfaceAccess* pSignal, bool bRegistering) :
|
||||
m_pDispatch(&rDispatch), m_ssName(rssName), m_pSignal(pSignal), m_bRegistering(bRegistering)
|
||||
{
|
||||
if (pSignal)
|
||||
{
|
||||
m_pSignalWrite = pSignal->GetInterface<ISignalWrite>();
|
||||
m_pSignalRead = pSignal->GetInterface<ISignalRead>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor for signal receiving callback.
|
||||
* @param[in] rDispatch Reference to the dispatch class.
|
||||
* @param[in] rssName Reference to the string holding the name of the signal.
|
||||
* @param[in] func Callback function being called on receiving data.
|
||||
*/
|
||||
CSignal(CDispatchService& rDispatch, const u8string& rssName, std::function<void(any_t)> func) :
|
||||
m_pDispatch(&rDispatch), m_ssName(rssName),
|
||||
m_ptrSubscriptionHandler(std::make_unique<CReceiveEventHandler>(rDispatch, func))
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Constructor for signal receiving callback.
|
||||
* @tparam TType Type of the variable to update automatically on an event call.
|
||||
* @param[in] rDispatch Reference to the dispatch class.
|
||||
* @param[in] rssName Reference to the string holding the name of the signal.
|
||||
* @param[in] rtVal Reference to the variable to update automatically on an event call.
|
||||
*/
|
||||
template <typename TType>
|
||||
CSignal(CDispatchService& rDispatch, const u8string& rssName, std::atomic<TType>& rtVal) :
|
||||
m_pDispatch(&rDispatch), m_ssName(rssName),
|
||||
m_ptrSubscriptionHandler(std::make_unique<CReceiveEventHandler>(rDispatch, rtVal))
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Get the subscription event handler, if existing.
|
||||
* @return Interface to the subscription handler or NULL when no handler is available.
|
||||
*/
|
||||
IInterfaceAccess* GetSubscriptionEventHandler()
|
||||
{
|
||||
return m_ptrSubscriptionHandler.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign subscription object returned by the dispatch service.
|
||||
* @param[in] pSubscription The interface to the subscription object.
|
||||
*/
|
||||
void Assign(IInterfaceAccess* pSubscription)
|
||||
{
|
||||
// The subscription object is managed through the signal int
|
||||
if (m_ptrSubscriptionHandler && !m_pSignal) m_pSignal = pSubscription;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Copy constructor (not available).
|
||||
* @param[in] rSignal Reference to the signal class to copy from.
|
||||
*/
|
||||
CSignal(const CSignal& rSignal) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @param[in] rSignal Reference to the signal class to move from.
|
||||
*/
|
||||
CSignal(CSignal&& rSignal) : m_pDispatch(rSignal.m_pDispatch), m_ssName(std::move(rSignal.m_ssName)),
|
||||
m_pSignal(rSignal.m_pSignal), m_pSignalWrite(rSignal.m_pSignalWrite), m_pSignalRead(rSignal.m_pSignalRead),
|
||||
m_ptrSubscriptionHandler(std::move(rSignal.m_ptrSubscriptionHandler)), m_bRegistering(rSignal.m_bRegistering)
|
||||
{
|
||||
rSignal.m_pSignal = nullptr;
|
||||
rSignal.m_pSignalWrite = nullptr;
|
||||
rSignal.m_pSignalRead = nullptr;
|
||||
rSignal.m_bRegistering = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator (not available).
|
||||
* @param[in] rSignal Reference to the signal class to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CSignal& operator=(const CSignal& rSignal) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move operator
|
||||
* @param[in] rSignal Reference to the signal class to move from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CSignal& operator=(CSignal&& rSignal)
|
||||
{
|
||||
Reset();
|
||||
m_pDispatch = rSignal.m_pDispatch;
|
||||
m_ssName = std::move(rSignal.m_ssName);
|
||||
m_pSignal = rSignal.m_pSignal;
|
||||
m_pSignalWrite = rSignal.m_pSignalWrite;
|
||||
m_pSignalRead = rSignal.m_pSignalRead;
|
||||
m_ptrSubscriptionHandler = std::move(rSignal.m_ptrSubscriptionHandler);
|
||||
m_bRegistering = rSignal.m_bRegistering;
|
||||
rSignal.m_pSignal = nullptr;
|
||||
rSignal.m_pSignalWrite = nullptr;
|
||||
rSignal.m_pSignalRead = nullptr;
|
||||
rSignal.m_bRegistering = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~CSignal()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the signal
|
||||
*/
|
||||
void Reset()
|
||||
{
|
||||
// First destroy the signal object. This will also prevent events to arrive.
|
||||
if (m_pSignal)
|
||||
{
|
||||
IObjectDestroy* pDestroy = m_pSignal->GetInterface<IObjectDestroy>();
|
||||
if (pDestroy) pDestroy->DestroyObject();
|
||||
}
|
||||
m_ptrSubscriptionHandler.reset();
|
||||
m_bRegistering = false;
|
||||
m_ssName.clear();
|
||||
m_pSignal = nullptr;
|
||||
m_pSignalWrite = nullptr;
|
||||
m_pSignalRead = nullptr;
|
||||
m_pDispatch = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator testing for validity of this class.
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return m_pSignal ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the signal value. This function is available for Rx signals (receiving data from the network) and for
|
||||
* services of publishing signals.
|
||||
* @param[in] tVal The value to update the signal with.
|
||||
* @param[in] rTransaction Reference to the transaction to use for reading.
|
||||
*/
|
||||
template <typename TType>
|
||||
void Write(TType tVal, const CTransaction& rTransaction = CTransaction())
|
||||
{
|
||||
if (m_pSignalWrite) m_pSignalWrite->Write(any_t(tVal), rTransaction.GetTransaction());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the signal value. This function is available for Tx signals (sending data over the network).
|
||||
* @param[in] rTransaction Reference to the transaction to use for reading.
|
||||
* @return The signal value or empty when no value or interface is available.
|
||||
*/
|
||||
any_t Read(const CTransaction& rTransaction = CTransaction()) const
|
||||
{
|
||||
any_t anyVal;
|
||||
if (m_pSignalRead) anyVal = m_pSignalRead->Read(rTransaction.GetTransaction());
|
||||
return anyVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Was this signal class used for registration of the signal.
|
||||
* @return Set when this signal is used for registration.
|
||||
*/
|
||||
bool UsedForRegistration() const { return m_bRegistering; }
|
||||
|
||||
/**
|
||||
* @brief Get the name of the signal.
|
||||
* @return String containing the name of the string.
|
||||
*/
|
||||
u8string GetName() const { return m_ssName; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Receive event handler
|
||||
*/
|
||||
class CReceiveEventHandler : public IInterfaceAccess, public ISignalReceiveEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for attaching a function.
|
||||
* @param[in] rDispatch Reference to the dispatch class.
|
||||
* @param[in] funcSignalReceive Callback function being called on receiving data.
|
||||
*/
|
||||
CReceiveEventHandler(CDispatchService& rDispatch, std::function<void(any_t)> funcSignalReceive) :
|
||||
m_rDispatch(rDispatch), m_funcSignalReceive(funcSignalReceive)
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Constructor for attaching a variable
|
||||
* @tparam TType Type of the variable to update automatically on an event call.
|
||||
* @param[in] rDispatch Reference to the dispatch class.
|
||||
* @param[in] rtVal Reference to the variable to update automatically on an event call.
|
||||
*/
|
||||
template <typename TType>
|
||||
CReceiveEventHandler(CDispatchService& rDispatch, std::atomic<TType>& rtVal) :
|
||||
m_rDispatch(rDispatch), m_ptrValue(std::make_unique<CValueAssignmentHelperT<TType>>(rtVal))
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CReceiveEventHandler()
|
||||
{
|
||||
if (m_pSubscription)
|
||||
{
|
||||
IObjectDestroy* pDestroy = m_pSubscription->GetInterface<IObjectDestroy>();
|
||||
if (pDestroy) pDestroy->DestroyObject();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper class for the value assignment.
|
||||
*/
|
||||
class CValueAssignmentHelper : public ISignalReceiveEvent
|
||||
{
|
||||
public:
|
||||
virtual ~CValueAssignmentHelper() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Type specific helper for the value assignment.
|
||||
* @tparam TType The type of the value.
|
||||
*/
|
||||
template <typename TType>
|
||||
class CValueAssignmentHelperT : public CValueAssignmentHelper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] rtVal Reference to the value to update at every receive event.
|
||||
*/
|
||||
CValueAssignmentHelperT(std::atomic<TType>& rtVal) : m_rtVal(rtVal)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~CValueAssignmentHelperT() = default;
|
||||
|
||||
/**
|
||||
* @brief A signal value was received. Overload function of ISignalReceiveEvent::Receive.
|
||||
* @param[in] anyVal The signal value.
|
||||
*/
|
||||
virtual void Receive(any_t anyVal) override
|
||||
{
|
||||
m_rtVal = static_cast<TType>(anyVal);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<TType>& m_rtVal;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Set the subscriber cookie. This allows automatically subscription removal.
|
||||
* @param[in] pSubscription Subscription interface.
|
||||
*/
|
||||
void Assign(IInterfaceAccess* pSubscription)
|
||||
{
|
||||
m_pSubscription = pSubscription;
|
||||
}
|
||||
|
||||
private:
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(IInterfaceAccess)
|
||||
SDV_INTERFACE_ENTRY(ISignalReceiveEvent)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief A signal value was received. Overload function of ISignalReceiveEvent::Receive.
|
||||
* @param[in] anyVal The signal value.
|
||||
*/
|
||||
virtual void Receive(any_t anyVal) override
|
||||
{
|
||||
if (m_funcSignalReceive) m_funcSignalReceive(anyVal);
|
||||
if (m_ptrValue) m_ptrValue->Receive(anyVal);
|
||||
}
|
||||
|
||||
CDispatchService& m_rDispatch; ///< Reference to the dispatch service.
|
||||
std::function<void(any_t)> m_funcSignalReceive; ///< Receive signal data - callback function.
|
||||
IInterfaceAccess* m_pSubscription = nullptr; ///< Cookie received by adding an receive subscription.
|
||||
std::unique_ptr<CValueAssignmentHelper> m_ptrValue; ///< Value to update instead of a callback function.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Receive event handler smart pointer.
|
||||
*/
|
||||
using CReceiveEventHandlerPtr = std::unique_ptr<CReceiveEventHandler>;
|
||||
|
||||
CDispatchService* m_pDispatch = nullptr; ///< Pointer to the dispatch service.
|
||||
u8string m_ssName; ///< Signal name.
|
||||
IInterfaceAccess* m_pSignal = nullptr; ///< The signal interface.
|
||||
ISignalWrite* m_pSignalWrite = nullptr; ///< Write signal data interface.
|
||||
ISignalRead* m_pSignalRead = nullptr; ///< Write signal data interface.
|
||||
CReceiveEventHandlerPtr m_ptrSubscriptionHandler; ///< Receive event handler smart pointer.
|
||||
bool m_bRegistering = false; ///< When set, the signal was created using the
|
||||
///< registration function.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Trigger class wrapping the trigger functionality.
|
||||
*/
|
||||
class CTrigger
|
||||
{
|
||||
friend CDispatchService;
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
CTrigger() = default;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor for trigger.
|
||||
* @param[in] rDispatch Reference to the dispatch class.
|
||||
* @param[in] fnExecute Function to the callback.
|
||||
*/
|
||||
CTrigger(CDispatchService& rDispatch, std::function<void()> fnExecute) :
|
||||
m_pDispatch(&rDispatch), m_ptrCallback(std::make_unique<STriggerCallback>(fnExecute))
|
||||
{}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Copy constructor (deleted)
|
||||
* @param[in] rTrigger Reference to the trigger to copy from.
|
||||
*/
|
||||
CTrigger(const CTrigger& rTrigger) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
* @param[in] rTrigger Reference to the trigger to move from.
|
||||
*/
|
||||
CTrigger(CTrigger&& rTrigger) :
|
||||
m_pDispatch(rTrigger.m_pDispatch), m_pTrigger(rTrigger.m_pTrigger),
|
||||
m_ptrCallback(std::move(rTrigger.m_ptrCallback))
|
||||
{
|
||||
rTrigger.m_pDispatch = nullptr;
|
||||
rTrigger.m_pTrigger = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CTrigger()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator (deleted)
|
||||
* @param[in] rTrigger Reference to the trigger to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CTrigger& operator=(const CTrigger& rTrigger) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move operator
|
||||
* @param[in] rTrigger Reference to the trigger to move from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CTrigger& operator=(CTrigger&& rTrigger)
|
||||
{
|
||||
Reset();
|
||||
m_pDispatch = rTrigger.m_pDispatch;
|
||||
m_pTrigger = rTrigger.m_pTrigger;
|
||||
m_ptrCallback = std::move(rTrigger.m_ptrCallback);
|
||||
rTrigger.m_pDispatch = nullptr;
|
||||
rTrigger.m_pTrigger = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Valid trigger?
|
||||
*/
|
||||
operator bool() const { return m_pTrigger ? true : false; }
|
||||
|
||||
/**
|
||||
* @brief Reset the trigger.
|
||||
*/
|
||||
void Reset()
|
||||
{
|
||||
if (m_pDispatch && m_pTrigger)
|
||||
{
|
||||
IObjectDestroy* pDestroy = m_pTrigger->GetInterface<IObjectDestroy>();
|
||||
pDestroy->DestroyObject();
|
||||
}
|
||||
|
||||
m_pDispatch = nullptr;
|
||||
m_pTrigger = nullptr;
|
||||
m_ptrCallback.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a signal that should trigger.
|
||||
* @param[in] rSignal Reference to the signal.
|
||||
*/
|
||||
void AddSignal(const CSignal& rSignal)
|
||||
{
|
||||
if (!m_pTrigger) return;
|
||||
ITxTrigger* pTrigger = m_pTrigger->GetInterface<ITxTrigger>();
|
||||
if (!pTrigger) return;
|
||||
|
||||
pTrigger->AddSignal(rSignal.GetName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove a signal from the trigger.
|
||||
* @param[in] rSignal Reference to the signal.
|
||||
*/
|
||||
void RemoveSignal(const CSignal& rSignal)
|
||||
{
|
||||
if (!m_pTrigger) return;
|
||||
ITxTrigger* pTrigger = m_pTrigger->GetInterface<ITxTrigger>();
|
||||
if (!pTrigger) return;
|
||||
|
||||
pTrigger->RemoveSignal(rSignal.GetName());
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Get the pointer of the callback object.
|
||||
* @return Interface pointer to the callback.
|
||||
*/
|
||||
IInterfaceAccess* GetCallback()
|
||||
{
|
||||
return m_ptrCallback.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign the trigger object.
|
||||
* @param[in] pTrigger Pointer to the interface to the trigger object.
|
||||
*/
|
||||
void Assign(IInterfaceAccess* pTrigger)
|
||||
{
|
||||
m_pTrigger = pTrigger;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Trigger callback wrapper object.
|
||||
*/
|
||||
struct STriggerCallback : public IInterfaceAccess, public ITxTriggerCallback
|
||||
{
|
||||
STriggerCallback(std::function<void()> fnExecute) : m_fnExecute(fnExecute)
|
||||
{}
|
||||
|
||||
protected:
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(ITxTriggerCallback)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief Execute the trigger. Overload of ITxTriggerCallback::Execute.
|
||||
*/
|
||||
virtual void Execute() override
|
||||
{
|
||||
if (m_fnExecute) m_fnExecute();
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> m_fnExecute; ///< Execution callback function.
|
||||
};
|
||||
|
||||
CDispatchService* m_pDispatch = nullptr; ///< Pointer to the dispatch class.
|
||||
IInterfaceAccess* m_pTrigger = nullptr; ///< Trigger object
|
||||
std::unique_ptr<STriggerCallback> m_ptrCallback; ///< Callback object
|
||||
};
|
||||
|
||||
inline CDispatchService::CDispatchService()
|
||||
{}
|
||||
|
||||
inline CDispatchService::~CDispatchService()
|
||||
{}
|
||||
|
||||
template <typename TType>
|
||||
inline CSignal CDispatchService::RegisterTxSignal(const u8string& rssName, TType tDefVal)
|
||||
{
|
||||
ISignalTransmission* pRegister = GetObject<ISignalTransmission>("DataDispatchService");
|
||||
CSignal signal;
|
||||
if (pRegister)
|
||||
signal = CSignal(*this, rssName,
|
||||
pRegister->RegisterTxSignal(rssName, any_t(tDefVal)),
|
||||
true);
|
||||
return signal;
|
||||
}
|
||||
|
||||
inline CSignal CDispatchService::RegisterRxSignal(const u8string& rssName)
|
||||
{
|
||||
ISignalTransmission* pRegister = GetObject<ISignalTransmission>("DataDispatchService");
|
||||
CSignal signal;
|
||||
if (pRegister)
|
||||
signal = CSignal(*this, rssName, pRegister->RegisterRxSignal(rssName), true);
|
||||
return signal;
|
||||
}
|
||||
|
||||
inline CSignal CDispatchService::AddPublisher(const u8string& rssSignalName)
|
||||
{
|
||||
ISignalAccess* pAccess = GetObject<ISignalAccess>("DataDispatchService");
|
||||
CSignal signal;
|
||||
if (pAccess)
|
||||
signal = CSignal(*this, rssSignalName, pAccess->RequestSignalPublisher(rssSignalName), false);
|
||||
return signal;
|
||||
}
|
||||
|
||||
inline CSignal CDispatchService::Subscribe(const u8string& rssSignalName, std::function<void(any_t)> func)
|
||||
{
|
||||
ISignalAccess* pAccess = GetObject<ISignalAccess>("DataDispatchService");
|
||||
CSignal signal(*this, rssSignalName, func);
|
||||
if (pAccess)
|
||||
signal.Assign(pAccess->AddSignalSubscription(rssSignalName, signal.GetSubscriptionEventHandler()));
|
||||
return signal;
|
||||
}
|
||||
|
||||
template <typename TType>
|
||||
inline CSignal CDispatchService::Subscribe(const u8string& rssSignalName, std::atomic<TType>& rtVal)
|
||||
{
|
||||
ISignalAccess* pAccess = GetObject<ISignalAccess>("DataDispatchService");
|
||||
CSignal signal(*this, rssSignalName, rtVal);
|
||||
if (pAccess)
|
||||
signal.Assign(pAccess->AddSignalSubscription(rssSignalName, signal.GetSubscriptionEventHandler()));
|
||||
return signal;
|
||||
}
|
||||
|
||||
inline sequence<SSignalRegistration> CDispatchService::GetRegisteredSignals() const
|
||||
{
|
||||
ISignalAccess* pAccess = GetObject<ISignalAccess>("DataDispatchService");
|
||||
sequence<SSignalRegistration> seqSignalNames;
|
||||
if (pAccess) seqSignalNames = pAccess->GetRegisteredSignals();
|
||||
return seqSignalNames;
|
||||
}
|
||||
|
||||
inline CTransaction CDispatchService::CreateTransaction()
|
||||
{
|
||||
IDispatchTransaction* pTransaction = GetObject<IDispatchTransaction>("DataDispatchService");
|
||||
CTransaction transaction;
|
||||
if (pTransaction) transaction = CTransaction(*this, pTransaction->CreateTransaction());
|
||||
return transaction;
|
||||
}
|
||||
|
||||
inline void CDispatchService::FinishTransaction(CTransaction& rTransaction)
|
||||
{
|
||||
rTransaction.Finish();
|
||||
}
|
||||
|
||||
inline CTrigger CDispatchService::CreateTxTrigger(std::function<void()> fnExecute, bool bSpontaneous /*= true*/,
|
||||
uint32_t uiDelayTime /*= 0*/, uint32_t uiPeriod /*= 0ul*/, bool bOnlyWhenActive /*= false*/)
|
||||
{
|
||||
if (!fnExecute) return CTrigger();
|
||||
if (!bSpontaneous && !uiPeriod) return CTrigger();
|
||||
ISignalTransmission* pSignalTransmission = GetObject<ISignalTransmission>("DataDispatchService");
|
||||
if (!pSignalTransmission) return CTrigger();
|
||||
uint32_t uiFlags = 0;
|
||||
if (bSpontaneous) uiFlags |= static_cast<uint32_t>(ISignalTransmission::ETxTriggerBehavior::spontaneous);
|
||||
if (uiPeriod && bOnlyWhenActive) uiFlags |= static_cast<uint32_t>(ISignalTransmission::ETxTriggerBehavior::periodic_if_active);
|
||||
CTrigger trigger(*this, fnExecute);
|
||||
trigger.Assign(pSignalTransmission->CreateTxTrigger(uiPeriod, uiDelayTime, uiFlags, trigger.GetCallback()));
|
||||
return trigger;
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
} // namespace sdv
|
||||
|
||||
|
||||
#endif // !defined SIGNAL_SUPPORT_H
|
||||
2317
export/support/string.h
Normal file
2317
export/support/string.h
Normal file
File diff suppressed because it is too large
Load Diff
2939
export/support/string.inl
Normal file
2939
export/support/string.inl
Normal file
File diff suppressed because it is too large
Load Diff
181
export/support/timer.h
Normal file
181
export/support/timer.h
Normal file
@@ -0,0 +1,181 @@
|
||||
#ifndef VAPI_TASK_TIMER_H
|
||||
#define VAPI_TASK_TIMER_H
|
||||
|
||||
#include "../interfaces/timer.h"
|
||||
#include "interface_ptr.h"
|
||||
#include "local_service_access.h"
|
||||
#include <functional>
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
/**
|
||||
* @brief Task timer class.
|
||||
*/
|
||||
class CTaskTimer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Dfault constructor
|
||||
*/
|
||||
CTaskTimer() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] uiPeriod The period to create a timer for.
|
||||
* @param[in] fnCallback Callback function to be called on task execution.
|
||||
*/
|
||||
CTaskTimer(uint32_t uiPeriod, std::function<void()> fnCallback) :
|
||||
m_ptrCallback(std::make_unique<STimerCallback>(fnCallback))
|
||||
{
|
||||
if (!m_ptrCallback) return;
|
||||
if (!uiPeriod) return;
|
||||
|
||||
// Get the task timer service.
|
||||
sdv::core::ITaskTimer* pTaskTimer = sdv::core::GetObject<sdv::core::ITaskTimer>("TaskTimerService");
|
||||
if (!pTaskTimer)
|
||||
{
|
||||
pTaskTimer = sdv::core::GetObject<sdv::core::ITaskTimer>("SimulationTaskTimerService");
|
||||
if (!pTaskTimer) return;
|
||||
}
|
||||
|
||||
// Create the timer
|
||||
m_pTimer = pTaskTimer->CreateTimer(uiPeriod, m_ptrCallback.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] uiPeriod The period to create a timer for.
|
||||
* @param[in] pTask Pointer to the interface of the task object to be called. The object must expose
|
||||
* sdv::core::ITastExecute.
|
||||
*/
|
||||
CTaskTimer(uint32_t uiPeriod, sdv::IInterfaceAccess* pTask)
|
||||
{
|
||||
if (!uiPeriod) return;
|
||||
|
||||
// Get the task timer service.
|
||||
sdv::core::ITaskTimer* pTaskTimer = sdv::core::GetObject<sdv::core::ITaskTimer>("TaskTimerService");
|
||||
if (!pTaskTimer)
|
||||
{
|
||||
pTaskTimer = sdv::core::GetObject<sdv::core::ITaskTimer>("SimulationTaskTimerService");
|
||||
if (!pTaskTimer) return;
|
||||
}
|
||||
|
||||
// Create the timer
|
||||
m_pTimer = pTaskTimer->CreateTimer(uiPeriod, pTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor is deleted.
|
||||
*/
|
||||
CTaskTimer(const CTaskTimer&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
* @param[in] rtimer Reference to the timer to move from.
|
||||
*/
|
||||
CTaskTimer(CTaskTimer&& rtimer) noexcept :
|
||||
m_pTimer(rtimer.m_pTimer), m_uiPeriod(rtimer.m_uiPeriod), m_ptrCallback(std::move(rtimer.m_ptrCallback))
|
||||
{
|
||||
rtimer.m_pTimer = nullptr;
|
||||
rtimer.m_uiPeriod = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CTaskTimer()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator is deleted.
|
||||
*/
|
||||
CTaskTimer& operator=(const CTaskTimer&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move operator
|
||||
* @param[in] rtimer Reference to the timer to move from.
|
||||
* @return Reference to this timer object.
|
||||
*/
|
||||
CTaskTimer& operator=(CTaskTimer&& rtimer) noexcept
|
||||
{
|
||||
Reset();
|
||||
m_pTimer = rtimer.m_pTimer;
|
||||
m_ptrCallback = std::move(rtimer.m_ptrCallback);
|
||||
m_uiPeriod = rtimer.m_uiPeriod;
|
||||
rtimer.m_pTimer = nullptr;
|
||||
rtimer.m_uiPeriod = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether the timer is valid.
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return m_pTimer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the timer. Releases the timer object.
|
||||
*/
|
||||
void Reset()
|
||||
{
|
||||
if (m_pTimer)
|
||||
{
|
||||
IObjectDestroy* pDestroy = m_pTimer->GetInterface<IObjectDestroy>();
|
||||
if (pDestroy)
|
||||
pDestroy->DestroyObject();
|
||||
m_pTimer = nullptr;
|
||||
}
|
||||
m_ptrCallback.reset();
|
||||
m_uiPeriod = 0ul;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the task timer period.
|
||||
* @return The period of the timer in ms.
|
||||
*/
|
||||
uint32_t GetPeriod() const
|
||||
{
|
||||
return m_uiPeriod;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Timer callback wrapper object.
|
||||
*/
|
||||
struct STimerCallback : public IInterfaceAccess, public core::ITaskExecute
|
||||
{
|
||||
STimerCallback(std::function<void()> fnCallback) : m_fnCallback(fnCallback)
|
||||
{}
|
||||
|
||||
protected:
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(core::ITaskExecute)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief Execute the trigger. Overload of ITxTriggerCallback::Execute.
|
||||
*/
|
||||
virtual void Execute() override
|
||||
{
|
||||
if (m_fnCallback) m_fnCallback();
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> m_fnCallback; ///< Callback function
|
||||
};
|
||||
|
||||
sdv::IInterfaceAccess* m_pTimer = nullptr; ///< Timer object
|
||||
uint32_t m_uiPeriod = 0ul; ///< Task timer period
|
||||
std::unique_ptr<STimerCallback> m_ptrCallback; ///< Callback object
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined VAPI_TASK_TIMER_H
|
||||
379
export/support/toml.h
Normal file
379
export/support/toml.h
Normal file
@@ -0,0 +1,379 @@
|
||||
#ifndef SDV_CONFIG_H
|
||||
#define SDV_CONFIG_H
|
||||
|
||||
#include "../interfaces/toml.h"
|
||||
#include "interface_ptr.h"
|
||||
#include "local_service_access.h"
|
||||
|
||||
namespace sdv::toml
|
||||
{
|
||||
/**
|
||||
* @brief Node class allowing access to the type and value.
|
||||
*/
|
||||
class CNode
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
CNode() = default;
|
||||
|
||||
/**
|
||||
* @brief Node assignment constructor.
|
||||
* @param[in] rptrNode Reference to the node interface.
|
||||
*/
|
||||
CNode(const TInterfaceAccessPtr& rptrNode);
|
||||
|
||||
/**
|
||||
* @brief Node assignment operator.
|
||||
* @param[in] rptrNode Reference to the node interface.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CNode& operator=(const TInterfaceAccessPtr& rptrNode);
|
||||
|
||||
/**
|
||||
* @brief Does the class contain a valid node?
|
||||
* @return Returns 'true' if the class contains a valid node; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsValid() const;
|
||||
|
||||
/**
|
||||
* @brief Does the class contain a valid node?
|
||||
* @return Returns 'true' if the class contains a valid node; 'false' otherwise.
|
||||
*/
|
||||
virtual operator bool() const;
|
||||
|
||||
/**
|
||||
* @brief Return the node name.
|
||||
* @return String containing the node name.
|
||||
*/
|
||||
sdv::u8string GetName();
|
||||
|
||||
/**
|
||||
* @brief Get the node type.
|
||||
* @return The node type.
|
||||
*/
|
||||
ENodeType GetType();
|
||||
|
||||
/**
|
||||
* @brief Get the node value if the node contains a value.
|
||||
* @return The node value.
|
||||
*/
|
||||
sdv::any_t GetValue();
|
||||
|
||||
/**
|
||||
* @brief Clear the node class.
|
||||
*/
|
||||
virtual void Clear();
|
||||
|
||||
/**
|
||||
* @brief Get the TOML string from this node including all children.
|
||||
* @return The TOMl string.
|
||||
*/
|
||||
sdv::u8string GetTOML() const;
|
||||
|
||||
protected:
|
||||
TInterfaceAccessPtr m_ptrNode; ///< Pointer to the node interface.
|
||||
INodeInfo* m_pNodeInfo = nullptr; ///< Node information interface.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Node collection class representing a table or array node.
|
||||
*/
|
||||
class CNodeCollection : public CNode
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
CNodeCollection() = default;
|
||||
|
||||
/**
|
||||
* @brief Node assignment constructor.
|
||||
* @param[in] rptrNode Reference to the node interface.
|
||||
*/
|
||||
CNodeCollection(const TInterfaceAccessPtr& rptrNode);
|
||||
|
||||
/**
|
||||
* @brief Node assignment constructor.
|
||||
* @param[in] rNode Reference to the node class.
|
||||
*/
|
||||
CNodeCollection(const CNode& rNode);
|
||||
|
||||
/**
|
||||
* @brief Node assignment operator.
|
||||
* @param[in] rptrNode Reference to the node interface.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CNodeCollection& operator=(const TInterfaceAccessPtr& rptrNode);
|
||||
|
||||
/**
|
||||
* @brief Node assignment operator.
|
||||
* @param[in] rNode Reference to the node class.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CNodeCollection& operator=(const CNode& rNode);
|
||||
|
||||
/**
|
||||
* @brief Does the class contain a valid node?
|
||||
* @return Returns 'true' if the class contains a valid node; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsValid() const override;
|
||||
|
||||
/**
|
||||
* @brief Does the class contain a valid node?
|
||||
* @return Returns 'true' if the class contains a valid node; 'false' otherwise.
|
||||
*/
|
||||
virtual operator bool() const override;
|
||||
|
||||
/**
|
||||
* @brief Return the amount of nodes in this collection.
|
||||
* @return The amount of nodes.
|
||||
*/
|
||||
size_t GetCount() const;
|
||||
|
||||
/**
|
||||
* @brief Get the node at the provided index.
|
||||
* @param[in] nIndex The index number.
|
||||
* @return Returns the node if available or an empty node when not.
|
||||
*/
|
||||
CNode Get(size_t nIndex) const;
|
||||
|
||||
/**
|
||||
* @brief Get the node at the provided index.
|
||||
* @param[in] nIndex The index number.
|
||||
* @return Returns the node if available or an empty node when not.
|
||||
*/
|
||||
CNode operator[](size_t nIndex) const;
|
||||
|
||||
/**
|
||||
* @brief Clear the node class.
|
||||
*/
|
||||
virtual void Clear() override;
|
||||
|
||||
/**
|
||||
* @brief Get direct access to a node.
|
||||
* @details Elements of tables can be accessed and traversed by using '.' to separated the parent name from child name.
|
||||
* E.g. 'parent.child' would access the 'child' element of the 'parent' table. Elements of arrays can be accessed and
|
||||
* traversed by using the index number in brackets. E.g. 'array[3]' would access the fourth element of the array 'array'.
|
||||
* These access conventions can also be chained like 'table.array[2][1].subtable.integerElement'.
|
||||
* @param[in] rssNode Reference to the node string.
|
||||
* @return Returns the node when available or an empty node when not.
|
||||
*/
|
||||
CNode GetDirect(const sdv::u8string& rssNode) const;
|
||||
|
||||
private:
|
||||
INodeCollection* m_pCollection = nullptr; ///< Pointer to the node collection interface.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief TOML parser class
|
||||
*/
|
||||
class CTOMLParser : public CNodeCollection
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
CTOMLParser() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructor providing automatic processing.
|
||||
* @param[in] rssConfig Reference to the configuration.
|
||||
*/
|
||||
CTOMLParser(const std::string& rssConfig);
|
||||
|
||||
/**
|
||||
* @brief Process a configuration. This will clear any previous configuration.
|
||||
* @param[in] rssConfig Reference to the configuration.
|
||||
* @return Returns 'true' when the processing was successful; 'false# when not.
|
||||
*/
|
||||
bool Process(const std::string& rssConfig);
|
||||
|
||||
/**
|
||||
* @brief Returns whether a valid processed configuration is available.
|
||||
* @return Returns 'true' when the configuration is valid; 'false' when not.
|
||||
*/
|
||||
virtual bool IsValid() const override;
|
||||
|
||||
/**
|
||||
* @brief Returns whether a valid processed configuration is available.
|
||||
* @return Returns 'true' when the configuration is valid; 'false' when not.
|
||||
*/
|
||||
virtual operator bool() const override;
|
||||
|
||||
// Ignore cppcheck warning for not using dynamic binding when being called through the destructor.
|
||||
// cppcheck-suppress virtualCallInConstructor
|
||||
/**
|
||||
* @brief Clear the current configuration.
|
||||
*/
|
||||
virtual void Clear() override;
|
||||
|
||||
private:
|
||||
TObjectPtr m_ptrParserUtil; ///< TOML parser utility
|
||||
ITOMLParser* m_pParser = nullptr; ///< Pointer to the parser interface.
|
||||
};
|
||||
|
||||
inline CNode::CNode(const TInterfaceAccessPtr& rptrNode)
|
||||
{
|
||||
m_pNodeInfo = rptrNode.GetInterface<INodeInfo>();
|
||||
if (!m_pNodeInfo)
|
||||
return;
|
||||
m_ptrNode = rptrNode;
|
||||
}
|
||||
|
||||
inline CNode& CNode::operator=(const TInterfaceAccessPtr& rptrNode)
|
||||
{
|
||||
CNode::Clear();
|
||||
m_pNodeInfo = rptrNode.GetInterface<INodeInfo>();
|
||||
if (!m_pNodeInfo)
|
||||
return *this;
|
||||
m_ptrNode = rptrNode;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool CNode::IsValid() const
|
||||
{
|
||||
return m_pNodeInfo ? true : false;
|
||||
}
|
||||
|
||||
inline CNode::operator bool() const
|
||||
{
|
||||
return m_pNodeInfo ? true : false;
|
||||
}
|
||||
|
||||
inline sdv::u8string CNode::GetName()
|
||||
{
|
||||
return m_pNodeInfo ? m_pNodeInfo->GetName() : sdv::u8string();
|
||||
}
|
||||
|
||||
inline ENodeType CNode::GetType()
|
||||
{
|
||||
return m_pNodeInfo ? m_pNodeInfo->GetType() : ENodeType::node_invalid;
|
||||
}
|
||||
|
||||
inline sdv::any_t CNode::GetValue()
|
||||
{
|
||||
return m_pNodeInfo ? m_pNodeInfo->GetValue() : sdv::any_t();
|
||||
}
|
||||
|
||||
inline void CNode::Clear()
|
||||
{
|
||||
m_ptrNode = nullptr;
|
||||
m_pNodeInfo = nullptr;
|
||||
}
|
||||
|
||||
inline sdv::u8string CNode::GetTOML() const
|
||||
{
|
||||
return m_pNodeInfo ? m_pNodeInfo->GetTOML() : sdv::u8string();
|
||||
}
|
||||
|
||||
inline CNodeCollection::CNodeCollection(const TInterfaceAccessPtr& rptrNode) : CNode(rptrNode)
|
||||
{
|
||||
m_pCollection = rptrNode.GetInterface<INodeCollection>();
|
||||
if (!m_pCollection) CNode::Clear();
|
||||
}
|
||||
|
||||
inline CNodeCollection::CNodeCollection(const CNode& rNode) : CNode(rNode)
|
||||
{
|
||||
m_pCollection = m_ptrNode.GetInterface<INodeCollection>();
|
||||
if (!m_pCollection) CNode::Clear();
|
||||
}
|
||||
|
||||
inline CNodeCollection& CNodeCollection::operator=(const TInterfaceAccessPtr& rptrNode)
|
||||
{
|
||||
CNode::operator=(rptrNode);
|
||||
m_pCollection = rptrNode.GetInterface<INodeCollection>();
|
||||
if (!m_pCollection) CNode::Clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline CNodeCollection& CNodeCollection::operator=(const CNode& rNode)
|
||||
{
|
||||
CNode::operator=(rNode);
|
||||
m_pCollection = m_ptrNode.GetInterface<INodeCollection>();
|
||||
if (!m_pCollection) CNode::Clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool CNodeCollection::IsValid() const
|
||||
{
|
||||
return m_pCollection ? true : false;
|
||||
}
|
||||
|
||||
inline CNodeCollection::operator bool() const
|
||||
{
|
||||
return m_pCollection ? true : false;
|
||||
}
|
||||
|
||||
inline size_t CNodeCollection::GetCount() const
|
||||
{
|
||||
return m_pCollection ? m_pCollection->GetCount() : 0;
|
||||
}
|
||||
|
||||
inline CNode CNodeCollection::Get(size_t nIndex) const
|
||||
{
|
||||
return m_pCollection ? CNode(m_pCollection->GetNode(static_cast<uint32_t>(nIndex))) : CNode();
|
||||
}
|
||||
|
||||
inline CNode CNodeCollection::operator[](size_t nIndex) const
|
||||
{
|
||||
return m_pCollection ? CNode(m_pCollection->GetNode(static_cast<uint32_t>(nIndex))) : CNode();
|
||||
}
|
||||
|
||||
inline void CNodeCollection::Clear()
|
||||
{
|
||||
CNode::Clear();
|
||||
m_pCollection = nullptr;
|
||||
}
|
||||
|
||||
inline CNode CNodeCollection::GetDirect(const sdv::u8string& rssNode) const
|
||||
{
|
||||
return m_pCollection ? CNode(m_pCollection->GetNodeDirect(rssNode)) : CNode();
|
||||
}
|
||||
|
||||
inline CTOMLParser::CTOMLParser(const std::string& rssConfig)
|
||||
{
|
||||
Process(rssConfig);
|
||||
}
|
||||
|
||||
inline bool CTOMLParser::Process(const std::string& rssConfig)
|
||||
{
|
||||
Clear();
|
||||
m_ptrParserUtil = sdv::core::CreateUtility("TOMLParserUtility");
|
||||
m_pParser = m_ptrParserUtil.GetInterface<ITOMLParser>();
|
||||
if (m_pParser)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_pParser->Process(rssConfig);
|
||||
CNodeCollection::operator=(m_ptrParserUtil);
|
||||
}
|
||||
catch (const sdv::toml::XTOMLParseException&)
|
||||
{
|
||||
Clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
inline bool CTOMLParser::IsValid() const
|
||||
{
|
||||
return m_pParser ? true : false;
|
||||
}
|
||||
|
||||
inline CTOMLParser::operator bool() const
|
||||
{
|
||||
return m_pParser ? true : false;
|
||||
}
|
||||
|
||||
inline void CTOMLParser::Clear()
|
||||
{
|
||||
m_pParser = nullptr;
|
||||
m_ptrParserUtil.Clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // !defined SDV_CONFIG_H
|
||||
Reference in New Issue
Block a user