Merge remote-tracking branch 'upstream/development' into mueller/rtems-update

This commit is contained in:
Robin Müller 2021-02-09 14:13:16 +01:00
commit 5136d90659
34 changed files with 2556 additions and 2556 deletions

View File

@ -6,120 +6,120 @@
ActionHelper::ActionHelper(HasActionsIF* setOwner, ActionHelper::ActionHelper(HasActionsIF* setOwner,
MessageQueueIF* useThisQueue) : MessageQueueIF* useThisQueue) :
owner(setOwner), queueToUse(useThisQueue) { owner(setOwner), queueToUse(useThisQueue) {
} }
ActionHelper::~ActionHelper() { ActionHelper::~ActionHelper() {
} }
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) { ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) { if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
ActionId_t currentAction = ActionMessage::getActionId(command); ActionId_t currentAction = ActionMessage::getActionId(command);
prepareExecution(command->getSender(), currentAction, prepareExecution(command->getSender(), currentAction,
ActionMessage::getStoreId(command)); ActionMessage::getStoreId(command));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
return CommandMessage::UNKNOWN_COMMAND; return CommandMessage::UNKNOWN_COMMAND;
} }
} }
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) { ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE); ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore == nullptr) { if (ipcStore == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
if(queueToUse_ != nullptr) { if(queueToUse_ != nullptr) {
setQueueToUse(queueToUse_); setQueueToUse(queueToUse_);
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo,
ActionId_t commandId, ReturnValue_t result) { ActionId_t commandId, ReturnValue_t result) {
CommandMessage reply; CommandMessage reply;
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result); ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
queueToUse->sendMessage(reportTo, &reply); queueToUse->sendMessage(reportTo, &reply);
} }
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId,
ReturnValue_t result) { ReturnValue_t result) {
CommandMessage reply; CommandMessage reply;
ActionMessage::setCompletionReply(&reply, commandId, result); ActionMessage::setCompletionReply(&reply, commandId, result);
queueToUse->sendMessage(reportTo, &reply); queueToUse->sendMessage(reportTo, &reply);
} }
void ActionHelper::setQueueToUse(MessageQueueIF* queue) { void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
queueToUse = queue; queueToUse = queue;
} }
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
ActionId_t actionId, store_address_t dataAddress) { ActionId_t actionId, store_address_t dataAddress) {
const uint8_t* dataPtr = NULL; const uint8_t* dataPtr = NULL;
size_t size = 0; size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
CommandMessage reply; CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result); ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply); queueToUse->sendMessage(commandedBy, &reply);
return; return;
} }
result = owner->executeAction(actionId, commandedBy, dataPtr, size); result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress); ipcStore->deleteData(dataAddress);
if(result == HasActionsIF::EXECUTION_FINISHED) { if(result == HasActionsIF::EXECUTION_FINISHED) {
CommandMessage reply; CommandMessage reply;
ActionMessage::setCompletionReply(&reply, actionId, result); ActionMessage::setCompletionReply(&reply, actionId, result);
queueToUse->sendMessage(commandedBy, &reply); queueToUse->sendMessage(commandedBy, &reply);
} }
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
CommandMessage reply; CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result); ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply); queueToUse->sendMessage(commandedBy, &reply);
return; return;
} }
} }
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
ActionId_t replyId, SerializeIF* data, bool hideSender) { ActionId_t replyId, SerializeIF* data, bool hideSender) {
CommandMessage reply; CommandMessage reply;
store_address_t storeAddress; store_address_t storeAddress;
uint8_t *dataPtr; uint8_t *dataPtr;
size_t maxSize = data->getSerializedSize(); size_t maxSize = data->getSerializedSize();
if (maxSize == 0) { if (maxSize == 0) {
//No error, there's simply nothing to report. //No error, there's simply nothing to report.
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
size_t size = 0; size_t size = 0;
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize, ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
&dataPtr); &dataPtr);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
result = data->serialize(&dataPtr, &size, maxSize, result = data->serialize(&dataPtr, &size, maxSize,
SerializeIF::Endianness::BIG); SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeAddress); ipcStore->deleteData(storeAddress);
return result; return result;
} }
// We don't need to report the objectId, as we receive REQUESTED data // We don't need to report the objectId, as we receive REQUESTED data
// before the completion success message. // before the completion success message.
// True aperiodic replies need to be reported with // True aperiodic replies need to be reported with
// another dedicated message. // another dedicated message.
ActionMessage::setDataReply(&reply, replyId, storeAddress); ActionMessage::setDataReply(&reply, replyId, storeAddress);
// If the sender needs to be hidden, for example to handle packet // If the sender needs to be hidden, for example to handle packet
// as unrequested reply, this will be done here. // as unrequested reply, this will be done here.
if (hideSender) { if (hideSender) {
result = MessageQueueSenderIF::sendMessage(reportTo, &reply); result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
} }
else { else {
result = queueToUse->sendMessage(reportTo, &reply); result = queueToUse->sendMessage(reportTo, &reply);
} }
if (result != HasReturnvaluesIF::RETURN_OK){ if (result != HasReturnvaluesIF::RETURN_OK){
ipcStore->deleteData(storeAddress); ipcStore->deleteData(storeAddress);
} }
return result; return result;
} }
void ActionHelper::resetHelper() { void ActionHelper::resetHelper() {

View File

@ -18,68 +18,68 @@ class HasActionsIF;
class ActionHelper { class ActionHelper {
public: public:
/** /**
* Constructor of the action helper * Constructor of the action helper
* @param setOwner Pointer to the owner of the interface * @param setOwner Pointer to the owner of the interface
* @param useThisQueue messageQueue to be used, can be set during * @param useThisQueue messageQueue to be used, can be set during
* initialize function as well. * initialize function as well.
*/ */
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
virtual ~ActionHelper(); virtual ~ActionHelper();
/** /**
* Function to be called from the owner with a new command message * Function to be called from the owner with a new command message
* *
* If the message is a valid action message the helper will use the * If the message is a valid action message the helper will use the
* executeAction function from HasActionsIF. * executeAction function from HasActionsIF.
* If the message is invalid or the callback fails a message reply will be * If the message is invalid or the callback fails a message reply will be
* send to the sender of the message automatically. * send to the sender of the message automatically.
* *
* @param command Pointer to a command message received by the owner * @param command Pointer to a command message received by the owner
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message, * @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown * CommandMessage::UNKNOW_COMMAND if this message ID is unkown
*/ */
ReturnValue_t handleActionMessage(CommandMessage* command); ReturnValue_t handleActionMessage(CommandMessage* command);
/** /**
* Helper initialize function. Must be called before use of any other * Helper initialize function. Must be called before use of any other
* helper function * helper function
* @param queueToUse_ Pointer to the messageQueue to be used, optional * @param queueToUse_ Pointer to the messageQueue to be used, optional
* if queue was set in constructor * if queue was set in constructor
* @return Returns RETURN_OK if successful * @return Returns RETURN_OK if successful
*/ */
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr); ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
/** /**
* Function to be called from the owner to send a step message. * Function to be called from the owner to send a step message.
* Success or failure will be determined by the result value. * Success or failure will be determined by the result value.
* *
* @param step Number of steps already done * @param step Number of steps already done
* @param reportTo The messageQueueId to report the step message to * @param reportTo The messageQueueId to report the step message to
* @param commandId ID of the executed command * @param commandId ID of the executed command
* @param result Result of the execution * @param result Result of the execution
*/ */
void step(uint8_t step, MessageQueueId_t reportTo, void step(uint8_t step, MessageQueueId_t reportTo,
ActionId_t commandId, ActionId_t commandId,
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
/** /**
* Function to be called by the owner to send a action completion message * Function to be called by the owner to send a action completion message
* *
* @param reportTo MessageQueueId_t to report the action completion message to * @param reportTo MessageQueueId_t to report the action completion message to
* @param commandId ID of the executed command * @param commandId ID of the executed command
* @param result Result of the execution * @param result Result of the execution
*/ */
void finish(MessageQueueId_t reportTo, ActionId_t commandId, void finish(MessageQueueId_t reportTo, ActionId_t commandId,
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
/** /**
* Function to be called by the owner if an action does report data. * Function to be called by the owner if an action does report data.
* Takes a SerializeIF* pointer and serializes it into the IPC store. * Takes a SerializeIF* pointer and serializes it into the IPC store.
* @param reportTo MessageQueueId_t to report the action completion * @param reportTo MessageQueueId_t to report the action completion
* message to * message to
* @param replyId ID of the executed command * @param replyId ID of the executed command
* @param data Pointer to the data * @param data Pointer to the data
* @return Returns RETURN_OK if successful, otherwise failure code * @return Returns RETURN_OK if successful, otherwise failure code
*/ */
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
SerializeIF* data, bool hideSender = false); SerializeIF* data, bool hideSender = false);
/** /**
* Function to be called by the owner if an action does report data. * Function to be called by the owner if an action does report data.
* Takes the raw data and writes it into the IPC store. * Takes the raw data and writes it into the IPC store.
@ -91,13 +91,13 @@ public:
*/ */
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
const uint8_t* data, size_t dataSize, bool hideSender = false); const uint8_t* data, size_t dataSize, bool hideSender = false);
/** /**
* Function to setup the MessageQueueIF* of the helper. Can be used to * Function to setup the MessageQueueIF* of the helper. Can be used to
* set the MessageQueueIF* if message queue is unavailable at construction * set the MessageQueueIF* if message queue is unavailable at construction
* and initialize but must be setup before first call of other functions. * and initialize but must be setup before first call of other functions.
* @param queue Queue to be used by the helper * @param queue Queue to be used by the helper
*/ */
void setQueueToUse(MessageQueueIF *queue); void setQueueToUse(MessageQueueIF *queue);
protected: protected:
//! Increase of value of this per step //! Increase of value of this per step
static const uint8_t STEP_OFFSET = 1; static const uint8_t STEP_OFFSET = 1;
@ -108,18 +108,18 @@ protected:
//! Pointer to an IPC Store, initialized during construction or //! Pointer to an IPC Store, initialized during construction or
StorageManagerIF* ipcStore = nullptr; StorageManagerIF* ipcStore = nullptr;
/** /**
* Internal function called by handleActionMessage * Internal function called by handleActionMessage
* @param commandedBy MessageQueueID of Commander * @param commandedBy MessageQueueID of Commander
* @param actionId ID of action to be done * @param actionId ID of action to be done
* @param dataAddress Address of additional data in IPC Store * @param dataAddress Address of additional data in IPC Store
*/ */
virtual void prepareExecution(MessageQueueId_t commandedBy, virtual void prepareExecution(MessageQueueId_t commandedBy,
ActionId_t actionId, store_address_t dataAddress); ActionId_t actionId, store_address_t dataAddress);
/** /**
* @brief Default implementation is empty. * @brief Default implementation is empty.
*/ */
virtual void resetHelper(); virtual void resetHelper();
}; };
#endif /* FSFW_ACTION_ACTIONHELPER_H_ */ #endif /* FSFW_ACTION_ACTIONHELPER_H_ */

View File

@ -11,71 +11,71 @@ ActionMessage::~ActionMessage() {
} }
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid, void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
store_address_t parameters) { store_address_t parameters) {
message->setCommand(EXECUTE_ACTION); message->setCommand(EXECUTE_ACTION);
message->setParameter(fid); message->setParameter(fid);
message->setParameter2(parameters.raw); message->setParameter2(parameters.raw);
} }
ActionId_t ActionMessage::getActionId(const CommandMessage* message) { ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
return ActionId_t(message->getParameter()); return ActionId_t(message->getParameter());
} }
store_address_t ActionMessage::getStoreId(const CommandMessage* message) { store_address_t ActionMessage::getStoreId(const CommandMessage* message) {
store_address_t temp; store_address_t temp;
temp.raw = message->getParameter2(); temp.raw = message->getParameter2();
return temp; return temp;
} }
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step, void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
ReturnValue_t result) { ReturnValue_t result) {
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
message->setCommand(STEP_SUCCESS); message->setCommand(STEP_SUCCESS);
} else { } else {
message->setCommand(STEP_FAILED); message->setCommand(STEP_FAILED);
} }
message->setParameter(fid); message->setParameter(fid);
message->setParameter2((step << 16) + result); message->setParameter2((step << 16) + result);
} }
uint8_t ActionMessage::getStep(const CommandMessage* message) { uint8_t ActionMessage::getStep(const CommandMessage* message) {
return uint8_t((message->getParameter2() >> 16) & 0xFF); return uint8_t((message->getParameter2() >> 16) & 0xFF);
} }
ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) { ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) {
return message->getParameter2() & 0xFFFF; return message->getParameter2() & 0xFFFF;
} }
void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId, void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId,
store_address_t data) { store_address_t data) {
message->setCommand(DATA_REPLY); message->setCommand(DATA_REPLY);
message->setParameter(actionId); message->setParameter(actionId);
message->setParameter2(data.raw); message->setParameter2(data.raw);
} }
void ActionMessage::setCompletionReply(CommandMessage* message, void ActionMessage::setCompletionReply(CommandMessage* message,
ActionId_t fid, ReturnValue_t result) { ActionId_t fid, ReturnValue_t result) {
if (result == HasReturnvaluesIF::RETURN_OK or result == HasActionsIF::EXECUTION_FINISHED) { if (result == HasReturnvaluesIF::RETURN_OK or result == HasActionsIF::EXECUTION_FINISHED) {
message->setCommand(COMPLETION_SUCCESS); message->setCommand(COMPLETION_SUCCESS);
} else { } else {
message->setCommand(COMPLETION_FAILED); message->setCommand(COMPLETION_FAILED);
} }
message->setParameter(fid); message->setParameter(fid);
message->setParameter2(result); message->setParameter2(result);
} }
void ActionMessage::clear(CommandMessage* message) { void ActionMessage::clear(CommandMessage* message) {
switch(message->getCommand()) { switch(message->getCommand()) {
case EXECUTE_ACTION: case EXECUTE_ACTION:
case DATA_REPLY: { case DATA_REPLY: {
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>( StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
objects::IPC_STORE); objects::IPC_STORE);
if (ipcStore != NULL) { if (ipcStore != NULL) {
ipcStore->deleteData(getStoreId(message)); ipcStore->deleteData(getStoreId(message));
} }
break; break;
} }
default: default:
break; break;
} }
} }

View File

@ -15,29 +15,29 @@ using ActionId_t = uint32_t;
*/ */
class ActionMessage { class ActionMessage {
private: private:
ActionMessage(); ActionMessage();
public: public:
static const uint8_t MESSAGE_ID = messagetypes::ACTION; static const uint8_t MESSAGE_ID = messagetypes::ACTION;
static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1); static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1);
static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2); static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2);
static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3); static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3);
static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4); static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4);
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5); static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6); static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
virtual ~ActionMessage(); virtual ~ActionMessage();
static void setCommand(CommandMessage* message, ActionId_t fid, static void setCommand(CommandMessage* message, ActionId_t fid,
store_address_t parameters); store_address_t parameters);
static ActionId_t getActionId(const CommandMessage* message ); static ActionId_t getActionId(const CommandMessage* message );
static store_address_t getStoreId(const CommandMessage* message ); static store_address_t getStoreId(const CommandMessage* message );
static void setStepReply(CommandMessage* message, ActionId_t fid, static void setStepReply(CommandMessage* message, ActionId_t fid,
uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
static uint8_t getStep(const CommandMessage* message ); static uint8_t getStep(const CommandMessage* message );
static ReturnValue_t getReturnCode(const CommandMessage* message ); static ReturnValue_t getReturnCode(const CommandMessage* message );
static void setDataReply(CommandMessage* message, ActionId_t actionId, static void setDataReply(CommandMessage* message, ActionId_t actionId,
store_address_t data); store_address_t data);
static void setCompletionReply(CommandMessage* message, ActionId_t fid, static void setCompletionReply(CommandMessage* message, ActionId_t fid,
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
static void clear(CommandMessage* message); static void clear(CommandMessage* message);
}; };
#endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */ #endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */

View File

@ -1,7 +1,7 @@
target_sources(${LIB_FSFW_NAME} target_sources(${LIB_FSFW_NAME}
PRIVATE PRIVATE
ActionHelper.cpp ActionHelper.cpp
ActionMessage.cpp ActionMessage.cpp
CommandActionHelper.cpp CommandActionHelper.cpp
SimpleActionHelper.cpp SimpleActionHelper.cpp
) )

View File

@ -5,123 +5,123 @@
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) : CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) :
owner(setOwner), queueToUse(NULL), ipcStore( owner(setOwner), queueToUse(NULL), ipcStore(
NULL), commandCount(0), lastTarget(0) { NULL), commandCount(0), lastTarget(0) {
} }
CommandActionHelper::~CommandActionHelper() { CommandActionHelper::~CommandActionHelper() {
} }
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
ActionId_t actionId, SerializeIF *data) { ActionId_t actionId, SerializeIF *data) {
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo); HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
if (receiver == NULL) { if (receiver == NULL) {
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
} }
store_address_t storeId; store_address_t storeId;
uint8_t *storePointer; uint8_t *storePointer;
size_t maxSize = data->getSerializedSize(); size_t maxSize = data->getSerializedSize();
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
&storePointer); &storePointer);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
size_t size = 0; size_t size = 0;
result = data->serialize(&storePointer, &size, maxSize, result = data->serialize(&storePointer, &size, maxSize,
SerializeIF::Endianness::BIG); SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
return sendCommand(receiver->getCommandQueue(), actionId, storeId); return sendCommand(receiver->getCommandQueue(), actionId, storeId);
} }
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
ActionId_t actionId, const uint8_t *data, uint32_t size) { ActionId_t actionId, const uint8_t *data, uint32_t size) {
// if (commandCount != 0) { // if (commandCount != 0) {
// return CommandsFunctionsIF::ALREADY_COMMANDING; // return CommandsFunctionsIF::ALREADY_COMMANDING;
// } // }
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo); HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
if (receiver == NULL) { if (receiver == NULL) {
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
} }
store_address_t storeId; store_address_t storeId;
ReturnValue_t result = ipcStore->addData(&storeId, data, size); ReturnValue_t result = ipcStore->addData(&storeId, data, size);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
return sendCommand(receiver->getCommandQueue(), actionId, storeId); return sendCommand(receiver->getCommandQueue(), actionId, storeId);
} }
ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId, ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
ActionId_t actionId, store_address_t storeId) { ActionId_t actionId, store_address_t storeId) {
CommandMessage command; CommandMessage command;
ActionMessage::setCommand(&command, actionId, storeId); ActionMessage::setCommand(&command, actionId, storeId);
ReturnValue_t result = queueToUse->sendMessage(queueId, &command); ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeId); ipcStore->deleteData(storeId);
} }
lastTarget = queueId; lastTarget = queueId;
commandCount++; commandCount++;
return result; return result;
} }
ReturnValue_t CommandActionHelper::initialize() { ReturnValue_t CommandActionHelper::initialize() {
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE); ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore == NULL) { if (ipcStore == NULL) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
queueToUse = owner->getCommandQueuePtr(); queueToUse = owner->getCommandQueuePtr();
if (queueToUse == NULL) { if (queueToUse == NULL) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) { ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
if (reply->getSender() != lastTarget) { if (reply->getSender() != lastTarget) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
switch (reply->getCommand()) { switch (reply->getCommand()) {
case ActionMessage::COMPLETION_SUCCESS: case ActionMessage::COMPLETION_SUCCESS:
commandCount--; commandCount--;
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply)); owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
case ActionMessage::COMPLETION_FAILED: case ActionMessage::COMPLETION_FAILED:
commandCount--; commandCount--;
owner->completionFailedReceived(ActionMessage::getActionId(reply), owner->completionFailedReceived(ActionMessage::getActionId(reply),
ActionMessage::getReturnCode(reply)); ActionMessage::getReturnCode(reply));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
case ActionMessage::STEP_SUCCESS: case ActionMessage::STEP_SUCCESS:
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply), owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
ActionMessage::getStep(reply)); ActionMessage::getStep(reply));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
case ActionMessage::STEP_FAILED: case ActionMessage::STEP_FAILED:
commandCount--; commandCount--;
owner->stepFailedReceived(ActionMessage::getActionId(reply), owner->stepFailedReceived(ActionMessage::getActionId(reply),
ActionMessage::getStep(reply), ActionMessage::getStep(reply),
ActionMessage::getReturnCode(reply)); ActionMessage::getReturnCode(reply));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
case ActionMessage::DATA_REPLY: case ActionMessage::DATA_REPLY:
extractDataForOwner(ActionMessage::getActionId(reply), extractDataForOwner(ActionMessage::getActionId(reply),
ActionMessage::getStoreId(reply)); ActionMessage::getStoreId(reply));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
uint8_t CommandActionHelper::getCommandCount() const { uint8_t CommandActionHelper::getCommandCount() const {
return commandCount; return commandCount;
} }
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) { void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
const uint8_t * data = NULL; const uint8_t * data = NULL;
size_t size = 0; size_t size = 0;
ReturnValue_t result = ipcStore->getData(storeId, &data, &size); ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return; return;
} }
owner->dataReceived(actionId, data, size); owner->dataReceived(actionId, data, size);
ipcStore->deleteData(storeId); ipcStore->deleteData(storeId);
} }

View File

@ -11,26 +11,26 @@
class CommandsActionsIF; class CommandsActionsIF;
class CommandActionHelper { class CommandActionHelper {
friend class CommandsActionsIF; friend class CommandsActionsIF;
public: public:
CommandActionHelper(CommandsActionsIF* owner); CommandActionHelper(CommandsActionsIF* owner);
virtual ~CommandActionHelper(); virtual ~CommandActionHelper();
ReturnValue_t commandAction(object_id_t commandTo, ReturnValue_t commandAction(object_id_t commandTo,
ActionId_t actionId, const uint8_t* data, uint32_t size); ActionId_t actionId, const uint8_t* data, uint32_t size);
ReturnValue_t commandAction(object_id_t commandTo, ReturnValue_t commandAction(object_id_t commandTo,
ActionId_t actionId, SerializeIF* data); ActionId_t actionId, SerializeIF* data);
ReturnValue_t initialize(); ReturnValue_t initialize();
ReturnValue_t handleReply(CommandMessage* reply); ReturnValue_t handleReply(CommandMessage* reply);
uint8_t getCommandCount() const; uint8_t getCommandCount() const;
private: private:
CommandsActionsIF* owner; CommandsActionsIF* owner;
MessageQueueIF* queueToUse; MessageQueueIF* queueToUse;
StorageManagerIF* ipcStore; StorageManagerIF* ipcStore;
uint8_t commandCount; uint8_t commandCount;
MessageQueueId_t lastTarget; MessageQueueId_t lastTarget;
void extractDataForOwner(ActionId_t actionId, store_address_t storeId); void extractDataForOwner(ActionId_t actionId, store_address_t storeId);
ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId, ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId,
store_address_t storeId); store_address_t storeId);
}; };
#endif /* COMMANDACTIONHELPER_H_ */ #endif /* COMMANDACTIONHELPER_H_ */

View File

@ -15,22 +15,22 @@
* - replyReceived(id, step, cause) (if cause == OK, it's a success). * - replyReceived(id, step, cause) (if cause == OK, it's a success).
*/ */
class CommandsActionsIF { class CommandsActionsIF {
friend class CommandActionHelper; friend class CommandActionHelper;
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF; static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1); static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2); static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
virtual ~CommandsActionsIF() {} virtual ~CommandsActionsIF() {}
virtual MessageQueueIF* getCommandQueuePtr() = 0; virtual MessageQueueIF* getCommandQueuePtr() = 0;
protected: protected:
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0; virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
ReturnValue_t returnCode) = 0; ReturnValue_t returnCode) = 0;
virtual void dataReceived(ActionId_t actionId, const uint8_t* data, virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
uint32_t size) = 0; uint32_t size) = 0;
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0; virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
virtual void completionFailedReceived(ActionId_t actionId, virtual void completionFailedReceived(ActionId_t actionId,
ReturnValue_t returnCode) = 0; ReturnValue_t returnCode) = 0;
}; };

View File

@ -35,28 +35,28 @@
*/ */
class HasActionsIF { class HasActionsIF {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF; static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1); static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2); static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3); static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4); static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
virtual ~HasActionsIF() { } virtual ~HasActionsIF() { }
/** /**
* Function to get the MessageQueueId_t of the implementing object * Function to get the MessageQueueId_t of the implementing object
* @return MessageQueueId_t of the object * @return MessageQueueId_t of the object
*/ */
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;
/** /**
* Execute or initialize the execution of a certain function. * Execute or initialize the execution of a certain function.
* The ActionHelpers will execute this function and behave differently * The ActionHelpers will execute this function and behave differently
* depending on the returnvalue. * depending on the returnvalue.
* *
* @return * @return
* -@c EXECUTION_FINISHED Finish reply will be generated * -@c EXECUTION_FINISHED Finish reply will be generated
* -@c Not RETURN_OK Step failure reply will be generated * -@c Not RETURN_OK Step failure reply will be generated
*/ */
virtual ReturnValue_t executeAction(ActionId_t actionId, virtual ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0; MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
}; };

View File

@ -2,74 +2,74 @@
#include "SimpleActionHelper.h" #include "SimpleActionHelper.h"
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner, SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
MessageQueueIF* useThisQueue) : MessageQueueIF* useThisQueue) :
ActionHelper(setOwner, useThisQueue), isExecuting(false) { ActionHelper(setOwner, useThisQueue), isExecuting(false) {
} }
SimpleActionHelper::~SimpleActionHelper() { SimpleActionHelper::~SimpleActionHelper() {
} }
void SimpleActionHelper::step(ReturnValue_t result) { void SimpleActionHelper::step(ReturnValue_t result) {
// STEP_OFFESET is subtracted to compensate for adding offset in base // STEP_OFFESET is subtracted to compensate for adding offset in base
// method, which is not necessary here. // method, which is not necessary here.
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction, ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
result); result);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
resetHelper(); resetHelper();
} }
} }
void SimpleActionHelper::finish(ReturnValue_t result) { void SimpleActionHelper::finish(ReturnValue_t result) {
ActionHelper::finish(lastCommander, lastAction, result); ActionHelper::finish(lastCommander, lastAction, result);
resetHelper(); resetHelper();
} }
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) { ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
return ActionHelper::reportData(lastCommander, lastAction, data); return ActionHelper::reportData(lastCommander, lastAction, data);
} }
void SimpleActionHelper::resetHelper() { void SimpleActionHelper::resetHelper() {
stepCount = 0; stepCount = 0;
isExecuting = false; isExecuting = false;
lastAction = 0; lastAction = 0;
lastCommander = 0; lastCommander = 0;
} }
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy,
ActionId_t actionId, store_address_t dataAddress) { ActionId_t actionId, store_address_t dataAddress) {
CommandMessage reply; CommandMessage reply;
if (isExecuting) { if (isExecuting) {
ipcStore->deleteData(dataAddress); ipcStore->deleteData(dataAddress);
ActionMessage::setStepReply(&reply, actionId, 0, ActionMessage::setStepReply(&reply, actionId, 0,
HasActionsIF::IS_BUSY); HasActionsIF::IS_BUSY);
queueToUse->sendMessage(commandedBy, &reply); queueToUse->sendMessage(commandedBy, &reply);
} }
const uint8_t* dataPtr = NULL; const uint8_t* dataPtr = NULL;
size_t size = 0; size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
ActionMessage::setStepReply(&reply, actionId, 0, result); ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply); queueToUse->sendMessage(commandedBy, &reply);
return; return;
} }
lastCommander = commandedBy; lastCommander = commandedBy;
lastAction = actionId; lastAction = actionId;
result = owner->executeAction(actionId, commandedBy, dataPtr, size); result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress); ipcStore->deleteData(dataAddress);
switch (result) { switch (result) {
case HasReturnvaluesIF::RETURN_OK: case HasReturnvaluesIF::RETURN_OK:
isExecuting = true; isExecuting = true;
stepCount++; stepCount++;
break; break;
case HasActionsIF::EXECUTION_FINISHED: case HasActionsIF::EXECUTION_FINISHED:
ActionMessage::setCompletionReply(&reply, actionId, ActionMessage::setCompletionReply(&reply, actionId,
HasReturnvaluesIF::RETURN_OK); HasReturnvaluesIF::RETURN_OK);
queueToUse->sendMessage(commandedBy, &reply); queueToUse->sendMessage(commandedBy, &reply);
break; break;
default: default:
ActionMessage::setStepReply(&reply, actionId, 0, result); ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply); queueToUse->sendMessage(commandedBy, &reply);
break; break;
} }
} }

View File

@ -4,27 +4,27 @@
#include "ActionHelper.h" #include "ActionHelper.h"
/** /**
* @brief This is an action helper which is only able to service one action * @brief This is an action helper which is only able to service one action
* at a time but remembers last commander and last action which * at a time but remembers last commander and last action which
* simplifies usage * simplifies usage
*/ */
class SimpleActionHelper: public ActionHelper { class SimpleActionHelper: public ActionHelper {
public: public:
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
virtual ~SimpleActionHelper(); virtual ~SimpleActionHelper();
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
ReturnValue_t reportData(SerializeIF* data); ReturnValue_t reportData(SerializeIF* data);
protected: protected:
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress); store_address_t dataAddress);
virtual void resetHelper(); virtual void resetHelper();
private: private:
bool isExecuting; bool isExecuting;
MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE; MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE;
ActionId_t lastAction = 0; ActionId_t lastAction = 0;
uint8_t stepCount = 0; uint8_t stepCount = 0;
}; };
#endif /* SIMPLEACTIONHELPER_H_ */ #endif /* SIMPLEACTIONHELPER_H_ */

View File

@ -6,7 +6,7 @@
#include "../serialize/SerializeIF.h" #include "../serialize/SerializeIF.h"
/** /**
* @brief A List that stores its values in an array. * @brief A List that stores its values in an array.
* @details * @details
* The underlying storage is an array that can be allocated by the class * The underlying storage is an array that can be allocated by the class
* itself or supplied via ctor. * itself or supplied via ctor.
@ -15,237 +15,237 @@
*/ */
template<typename T, typename count_t = uint8_t> template<typename T, typename count_t = uint8_t>
class ArrayList { class ArrayList {
template<typename U, typename count> friend class SerialArrayListAdapter; template<typename U, typename count> friend class SerialArrayListAdapter;
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST; static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01); static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
/** /**
* This is the allocating constructor. * This is the allocating constructor.
* It allocates an array of the specified size. * It allocates an array of the specified size.
* @param maxSize * @param maxSize
*/ */
ArrayList(count_t maxSize) : ArrayList(count_t maxSize) :
size(0), maxSize_(maxSize), allocated(true) { size(0), maxSize_(maxSize), allocated(true) {
entries = new T[maxSize]; entries = new T[maxSize];
} }
/** /**
* This is the non-allocating constructor * This is the non-allocating constructor
* *
* It expects a pointer to an array of a certain size and initializes * It expects a pointer to an array of a certain size and initializes
* itself to it. * itself to it.
* *
* @param storage the array to use as backend * @param storage the array to use as backend
* @param maxSize size of storage * @param maxSize size of storage
* @param size size of data already present in storage * @param size size of data already present in storage
*/ */
ArrayList(T *storage, count_t maxSize, count_t size = 0) : ArrayList(T *storage, count_t maxSize, count_t size = 0) :
size(size), entries(storage), maxSize_(maxSize), allocated(false) { size(size), entries(storage), maxSize_(maxSize), allocated(false) {
} }
/** /**
* Copying is forbiden by declaring copy ctor and copy assignment deleted * Copying is forbiden by declaring copy ctor and copy assignment deleted
* It is too ambigous in this case. * It is too ambigous in this case.
* (Allocate a new backend? Use the same? What to do in an modifying call?) * (Allocate a new backend? Use the same? What to do in an modifying call?)
*/ */
ArrayList(const ArrayList& other) = delete; ArrayList(const ArrayList& other) = delete;
const ArrayList& operator=(const ArrayList& other) = delete; const ArrayList& operator=(const ArrayList& other) = delete;
/** /**
* Number of Elements stored in this List * Number of Elements stored in this List
*/ */
count_t size; count_t size;
/** /**
* Destructor, if the allocating constructor was used, it deletes the array. * Destructor, if the allocating constructor was used, it deletes the array.
*/ */
virtual ~ArrayList() { virtual ~ArrayList() {
if (allocated) { if (allocated) {
delete[] entries; delete[] entries;
} }
} }
/** /**
* An Iterator to go trough an ArrayList * An Iterator to go trough an ArrayList
* *
* It stores a pointer to an element and increments the * It stores a pointer to an element and increments the
* pointer when incremented itself. * pointer when incremented itself.
*/ */
class Iterator { class Iterator {
public: public:
/** /**
* Empty ctor, points to NULL * Empty ctor, points to NULL
*/ */
Iterator(): value(0) {} Iterator(): value(0) {}
/** /**
* Initializes the Iterator to point to an element * Initializes the Iterator to point to an element
* *
* @param initialize * @param initialize
*/ */
Iterator(T *initialize) { Iterator(T *initialize) {
value = initialize; value = initialize;
} }
/** /**
* The current element the iterator points to * The current element the iterator points to
*/ */
T *value; T *value;
Iterator& operator++() { Iterator& operator++() {
value++; value++;
return *this; return *this;
} }
Iterator operator++(int) { Iterator operator++(int) {
Iterator tmp(*this); Iterator tmp(*this);
operator++(); operator++();
return tmp; return tmp;
} }
Iterator& operator--() { Iterator& operator--() {
value--; value--;
return *this; return *this;
} }
Iterator operator--(int) { Iterator operator--(int) {
Iterator tmp(*this); Iterator tmp(*this);
operator--(); operator--();
return tmp; return tmp;
} }
T& operator*() { T& operator*() {
return *value; return *value;
} }
const T& operator*() const { const T& operator*() const {
return *value; return *value;
} }
T *operator->() { T *operator->() {
return value; return value;
} }
const T *operator->() const { const T *operator->() const {
return value; return value;
} }
}; };
friend bool operator==(const ArrayList::Iterator& lhs, friend bool operator==(const ArrayList::Iterator& lhs,
const ArrayList::Iterator& rhs) { const ArrayList::Iterator& rhs) {
return (lhs.value == rhs.value); return (lhs.value == rhs.value);
} }
friend bool operator!=(const ArrayList::Iterator& lhs, friend bool operator!=(const ArrayList::Iterator& lhs,
const ArrayList::Iterator& rhs) { const ArrayList::Iterator& rhs) {
return not (lhs.value == rhs.value); return not (lhs.value == rhs.value);
} }
/** /**
* Iterator pointing to the first stored elmement * Iterator pointing to the first stored elmement
* *
* @return Iterator to the first element * @return Iterator to the first element
*/ */
Iterator begin() const { Iterator begin() const {
return Iterator(&entries[0]); return Iterator(&entries[0]);
} }
/** /**
* returns an Iterator pointing to the element after the last stored entry * returns an Iterator pointing to the element after the last stored entry
* *
* @return Iterator to the element after the last entry * @return Iterator to the element after the last entry
*/ */
Iterator end() const { Iterator end() const {
return Iterator(&entries[size]); return Iterator(&entries[size]);
} }
T & operator[](count_t i) const { T & operator[](count_t i) const {
return entries[i]; return entries[i];
} }
/** /**
* The first element * The first element
* *
* @return pointer to the first stored element * @return pointer to the first stored element
*/ */
T *front() { T *front() {
return entries; return entries;
} }
/** /**
* The last element * The last element
* *
* does not return a valid pointer if called on an empty list. * does not return a valid pointer if called on an empty list.
* *
* @return pointer to the last stored element * @return pointer to the last stored element
*/ */
T *back() { T *back() {
return &entries[size - 1]; return &entries[size - 1];
//Alternative solution //Alternative solution
//return const_cast<T*>(static_cast<const T*>(*this).back()); //return const_cast<T*>(static_cast<const T*>(*this).back());
} }
const T* back() const{ const T* back() const{
return &entries[size-1]; return &entries[size-1];
} }
/** /**
* The maximum number of elements this List can contain * The maximum number of elements this List can contain
* *
* @return maximum number of elements * @return maximum number of elements
*/ */
size_t maxSize() const { size_t maxSize() const {
return this->maxSize_; return this->maxSize_;
} }
/** /**
* Insert a new element into the list. * Insert a new element into the list.
* *
* The new element is inserted after the last stored element. * The new element is inserted after the last stored element.
* *
* @param entry * @param entry
* @return * @return
* -@c FULL if the List is full * -@c FULL if the List is full
* -@c RETURN_OK else * -@c RETURN_OK else
*/ */
ReturnValue_t insert(T entry) { ReturnValue_t insert(T entry) {
if (size >= maxSize_) { if (size >= maxSize_) {
return FULL; return FULL;
} }
entries[size] = entry; entries[size] = entry;
++size; ++size;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
/** /**
* clear the List * clear the List
* *
* This does not actually clear all entries, it only sets the size to 0. * This does not actually clear all entries, it only sets the size to 0.
*/ */
void clear() { void clear() {
size = 0; size = 0;
} }
count_t remaining() { count_t remaining() {
return (maxSize_ - size); return (maxSize_ - size);
} }
protected: protected:
/** /**
* pointer to the array in which the entries are stored * pointer to the array in which the entries are stored
*/ */
T *entries; T *entries;
/** /**
* remembering the maximum size * remembering the maximum size
*/ */
size_t maxSize_; size_t maxSize_;
/** /**
* true if the array was allocated and needs to be deleted in the destructor. * true if the array was allocated and needs to be deleted in the destructor.
*/ */
bool allocated; bool allocated;
}; };

View File

@ -7,65 +7,65 @@
template<typename Tp> template<typename Tp>
class BinaryNode { class BinaryNode {
public: public:
BinaryNode(Tp* setValue) : BinaryNode(Tp* setValue) :
value(setValue), left(NULL), right(NULL), parent(NULL) { value(setValue), left(NULL), right(NULL), parent(NULL) {
} }
Tp *value; Tp *value;
BinaryNode* left; BinaryNode* left;
BinaryNode* right; BinaryNode* right;
BinaryNode* parent; BinaryNode* parent;
}; };
template<typename Tp> template<typename Tp>
class ExplicitNodeIterator { class ExplicitNodeIterator {
public: public:
typedef ExplicitNodeIterator<Tp> _Self; typedef ExplicitNodeIterator<Tp> _Self;
typedef BinaryNode<Tp> _Node; typedef BinaryNode<Tp> _Node;
typedef Tp value_type; typedef Tp value_type;
typedef Tp* pointer; typedef Tp* pointer;
typedef Tp& reference; typedef Tp& reference;
ExplicitNodeIterator() : ExplicitNodeIterator() :
element(NULL) { element(NULL) {
} }
ExplicitNodeIterator(_Node* node) : ExplicitNodeIterator(_Node* node) :
element(node) { element(node) {
} }
BinaryNode<Tp>* element; BinaryNode<Tp>* element;
_Self up() { _Self up() {
return _Self(element->parent); return _Self(element->parent);
} }
_Self left() { _Self left() {
if (element != NULL) { if (element != NULL) {
return _Self(element->left); return _Self(element->left);
} else { } else {
return _Self(NULL); return _Self(NULL);
} }
} }
_Self right() { _Self right() {
if (element != NULL) { if (element != NULL) {
return _Self(element->right); return _Self(element->right);
} else { } else {
return _Self(NULL); return _Self(NULL);
} }
} }
bool operator==(const _Self& __x) const { bool operator==(const _Self& __x) const {
return element == __x.element; return element == __x.element;
} }
bool operator!=(const _Self& __x) const { bool operator!=(const _Self& __x) const {
return element != __x.element; return element != __x.element;
} }
pointer pointer
operator->() const { operator->() const {
if (element != NULL) { if (element != NULL) {
return element->value; return element->value;
} else { } else {
return NULL; return NULL;
} }
} }
pointer operator*() const { pointer operator*() const {
return this->operator->(); return this->operator->();
} }
}; };
@ -75,77 +75,77 @@ public:
template<typename Tp> template<typename Tp>
class BinaryTree { class BinaryTree {
public: public:
typedef ExplicitNodeIterator<Tp> iterator; typedef ExplicitNodeIterator<Tp> iterator;
typedef BinaryNode<Tp> Node; typedef BinaryNode<Tp> Node;
typedef std::pair<iterator, iterator> children; typedef std::pair<iterator, iterator> children;
BinaryTree() : BinaryTree() :
rootNode(NULL) { rootNode(NULL) {
} }
BinaryTree(Node* rootNode) : BinaryTree(Node* rootNode) :
rootNode(rootNode) { rootNode(rootNode) {
} }
iterator begin() const { iterator begin() const {
return iterator(rootNode); return iterator(rootNode);
} }
static iterator end() { static iterator end() {
return iterator(NULL); return iterator(NULL);
} }
iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) { iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) {
newNode->parent = parentNode.element; newNode->parent = parentNode.element;
if (parentNode.element != NULL) { if (parentNode.element != NULL) {
if (insertLeft) { if (insertLeft) {
parentNode.element->left = newNode; parentNode.element->left = newNode;
} else { } else {
parentNode.element->right = newNode; parentNode.element->right = newNode;
} }
} else { } else {
//Insert first element. //Insert first element.
rootNode = newNode; rootNode = newNode;
} }
return iterator(newNode); return iterator(newNode);
} }
//No recursion to children. Needs to be done externally. //No recursion to children. Needs to be done externally.
children erase(iterator node) { children erase(iterator node) {
if (node.element == rootNode) { if (node.element == rootNode) {
//We're root node //We're root node
rootNode = NULL; rootNode = NULL;
} else { } else {
//Delete parent's reference //Delete parent's reference
if (node.up().left() == node) { if (node.up().left() == node) {
node.up().element->left = NULL; node.up().element->left = NULL;
} else { } else {
node.up().element->right = NULL; node.up().element->right = NULL;
} }
} }
return children(node.element->left, node.element->right); return children(node.element->left, node.element->right);
} }
static uint32_t countLeft(iterator start) { static uint32_t countLeft(iterator start) {
if (start == end()) { if (start == end()) {
return 0; return 0;
} }
//We also count the start node itself. //We also count the start node itself.
uint32_t count = 1; uint32_t count = 1;
while (start.left() != end()) { while (start.left() != end()) {
count++; count++;
start = start.left(); start = start.left();
} }
return count; return count;
} }
static uint32_t countRight(iterator start) { static uint32_t countRight(iterator start) {
if (start == end()) { if (start == end()) {
return 0; return 0;
} }
//We also count the start node itself. //We also count the start node itself.
uint32_t count = 1; uint32_t count = 1;
while (start.right() != end()) { while (start.right() != end()) {
count++; count++;
start = start.right(); start = start.right();
} }
return count; return count;
} }
protected: protected:
Node* rootNode; Node* rootNode;
}; };

View File

@ -1,5 +1,5 @@
target_sources(${LIB_FSFW_NAME} target_sources(${LIB_FSFW_NAME}
PRIVATE PRIVATE
SharedRingBuffer.cpp SharedRingBuffer.cpp
SimpleRingBuffer.cpp SimpleRingBuffer.cpp
) )

View File

@ -5,8 +5,8 @@
#include <vector> #include <vector>
/** /**
* @brief Simple First-In-First-Out data structure. The maximum size * @brief Simple First-In-First-Out data structure. The maximum size
* can be set in the constructor. * can be set in the constructor.
* @details * @details
* The maximum capacity can be determined at run-time, so this container * The maximum capacity can be determined at run-time, so this container
* performs dynamic memory allocation! * performs dynamic memory allocation!
@ -17,39 +17,39 @@
template<typename T> template<typename T>
class DynamicFIFO: public FIFOBase<T> { class DynamicFIFO: public FIFOBase<T> {
public: public:
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity), DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
fifoVector(maxCapacity) { fifoVector(maxCapacity) {
// trying to pass the pointer of the uninitialized vector // trying to pass the pointer of the uninitialized vector
// to the FIFOBase constructor directly lead to a super evil bug. // to the FIFOBase constructor directly lead to a super evil bug.
// So we do it like this now. // So we do it like this now.
this->setContainer(fifoVector.data()); this->setContainer(fifoVector.data());
}; };
/** /**
* @brief Custom copy constructor which prevents setting the * @brief Custom copy constructor which prevents setting the
* underlying pointer wrong. This function allocates memory! * underlying pointer wrong. This function allocates memory!
* @details This is a very heavy operation so try to avoid this! * @details This is a very heavy operation so try to avoid this!
* *
*/ */
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other), DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
fifoVector(other.maxCapacity) { fifoVector(other.maxCapacity) {
this->fifoVector = other.fifoVector; this->fifoVector = other.fifoVector;
this->setContainer(fifoVector.data()); this->setContainer(fifoVector.data());
} }
/** /**
* @brief Custom assignment operator * @brief Custom assignment operator
* @details This is a very heavy operation so try to avoid this! * @details This is a very heavy operation so try to avoid this!
* @param other DyamicFIFO to copy from * @param other DyamicFIFO to copy from
*/ */
DynamicFIFO& operator=(const DynamicFIFO& other){ DynamicFIFO& operator=(const DynamicFIFO& other){
FIFOBase<T>::operator=(other); FIFOBase<T>::operator=(other);
this->fifoVector = other.fifoVector; this->fifoVector = other.fifoVector;
this->setContainer(fifoVector.data()); this->setContainer(fifoVector.data());
return *this; return *this;
} }
private: private:
std::vector<T> fifoVector; std::vector<T> fifoVector;
}; };
#endif /* FSFW_CONTAINER_DYNAMICFIFO_H_ */ #endif /* FSFW_CONTAINER_DYNAMICFIFO_H_ */

View File

@ -5,8 +5,8 @@
#include <array> #include <array>
/** /**
* @brief Simple First-In-First-Out data structure with size fixed at * @brief Simple First-In-First-Out data structure with size fixed at
* compile time * compile time
* @details * @details
* Performs no dynamic memory allocation. * Performs no dynamic memory allocation.
* The public interface of FIFOBase exposes the user interface for the FIFO. * The public interface of FIFOBase exposes the user interface for the FIFO.
@ -16,32 +16,32 @@
template<typename T, size_t capacity> template<typename T, size_t capacity>
class FIFO: public FIFOBase<T> { class FIFO: public FIFOBase<T> {
public: public:
FIFO(): FIFOBase<T>(nullptr, capacity) { FIFO(): FIFOBase<T>(nullptr, capacity) {
this->setContainer(fifoArray.data()); this->setContainer(fifoArray.data());
}; };
/** /**
* @brief Custom copy constructor to set pointer correctly. * @brief Custom copy constructor to set pointer correctly.
* @param other * @param other
*/ */
FIFO(const FIFO& other): FIFOBase<T>(other) { FIFO(const FIFO& other): FIFOBase<T>(other) {
this->fifoArray = other.fifoArray; this->fifoArray = other.fifoArray;
this->setContainer(fifoArray.data()); this->setContainer(fifoArray.data());
} }
/** /**
* @brief Custom assignment operator * @brief Custom assignment operator
* @param other * @param other
*/ */
FIFO& operator=(const FIFO& other){ FIFO& operator=(const FIFO& other){
FIFOBase<T>::operator=(other); FIFOBase<T>::operator=(other);
this->fifoArray = other.fifoArray; this->fifoArray = other.fifoArray;
this->setContainer(fifoArray.data()); this->setContainer(fifoArray.data());
return *this; return *this;
} }
private: private:
std::array<T, capacity> fifoArray; std::array<T, capacity> fifoArray;
}; };
#endif /* FSFW_CONTAINER_FIFO_H_ */ #endif /* FSFW_CONTAINER_FIFO_H_ */

View File

@ -8,70 +8,70 @@
template <typename T> template <typename T>
class FIFOBase { class FIFOBase {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS; static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1); static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2); static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
/** Default ctor, takes pointer to first entry of underlying container /** Default ctor, takes pointer to first entry of underlying container
* and maximum capacity */ * and maximum capacity */
FIFOBase(T* values, const size_t maxCapacity); FIFOBase(T* values, const size_t maxCapacity);
/** /**
* Insert value into FIFO * Insert value into FIFO
* @param value * @param value
* @return RETURN_OK on success, FULL if full * @return RETURN_OK on success, FULL if full
*/ */
ReturnValue_t insert(T value); ReturnValue_t insert(T value);
/** /**
* Retrieve item from FIFO. This removes the item from the FIFO. * Retrieve item from FIFO. This removes the item from the FIFO.
* @param value Must point to a valid T * @param value Must point to a valid T
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
*/ */
ReturnValue_t retrieve(T *value); ReturnValue_t retrieve(T *value);
/** /**
* Retrieve item from FIFO without removing it from FIFO. * Retrieve item from FIFO without removing it from FIFO.
* @param value Must point to a valid T * @param value Must point to a valid T
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
*/ */
ReturnValue_t peek(T * value); ReturnValue_t peek(T * value);
/** /**
* Remove item from FIFO. * Remove item from FIFO.
* @return RETURN_OK on success, EMPTY if empty * @return RETURN_OK on success, EMPTY if empty
*/ */
ReturnValue_t pop(); ReturnValue_t pop();
/*** /***
* Check if FIFO is empty * Check if FIFO is empty
* @return True if empty, False if not * @return True if empty, False if not
*/ */
bool empty(); bool empty();
/*** /***
* Check if FIFO is Full * Check if FIFO is Full
* @return True if full, False if not * @return True if full, False if not
*/ */
bool full(); bool full();
/*** /***
* Current used size (elements) used * Current used size (elements) used
* @return size_t in elements * @return size_t in elements
*/ */
size_t size(); size_t size();
/*** /***
* Get maximal capacity of fifo * Get maximal capacity of fifo
* @return size_t with max capacity of this fifo * @return size_t with max capacity of this fifo
*/ */
size_t getMaxCapacity() const; size_t getMaxCapacity() const;
protected: protected:
void setContainer(T* data); void setContainer(T* data);
size_t maxCapacity = 0; size_t maxCapacity = 0;
T* values; T* values;
size_t readIndex = 0; size_t readIndex = 0;
size_t writeIndex = 0; size_t writeIndex = 0;
size_t currentSize = 0; size_t currentSize = 0;
size_t next(size_t current); size_t next(size_t current);
}; };
#include "FIFOBase.tpp" #include "FIFOBase.tpp"

View File

@ -7,87 +7,87 @@
template<typename T> template<typename T>
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity): inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity):
maxCapacity(maxCapacity), values(values){}; maxCapacity(maxCapacity), values(values){};
template<typename T> template<typename T>
inline ReturnValue_t FIFOBase<T>::insert(T value) { inline ReturnValue_t FIFOBase<T>::insert(T value) {
if (full()) { if (full()) {
return FULL; return FULL;
} else { } else {
values[writeIndex] = value; values[writeIndex] = value;
writeIndex = next(writeIndex); writeIndex = next(writeIndex);
++currentSize; ++currentSize;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
}; };
template<typename T> template<typename T>
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) { inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
if (empty()) { if (empty()) {
return EMPTY; return EMPTY;
} else { } else {
if (value == nullptr){ if (value == nullptr){
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
*value = values[readIndex]; *value = values[readIndex];
readIndex = next(readIndex); readIndex = next(readIndex);
--currentSize; --currentSize;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
}; };
template<typename T> template<typename T>
inline ReturnValue_t FIFOBase<T>::peek(T* value) { inline ReturnValue_t FIFOBase<T>::peek(T* value) {
if(empty()) { if(empty()) {
return EMPTY; return EMPTY;
} else { } else {
if (value == nullptr){ if (value == nullptr){
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
*value = values[readIndex]; *value = values[readIndex];
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
}; };
template<typename T> template<typename T>
inline ReturnValue_t FIFOBase<T>::pop() { inline ReturnValue_t FIFOBase<T>::pop() {
T value; T value;
return this->retrieve(&value); return this->retrieve(&value);
}; };
template<typename T> template<typename T>
inline bool FIFOBase<T>::empty() { inline bool FIFOBase<T>::empty() {
return (currentSize == 0); return (currentSize == 0);
}; };
template<typename T> template<typename T>
inline bool FIFOBase<T>::full() { inline bool FIFOBase<T>::full() {
return (currentSize == maxCapacity); return (currentSize == maxCapacity);
} }
template<typename T> template<typename T>
inline size_t FIFOBase<T>::size() { inline size_t FIFOBase<T>::size() {
return currentSize; return currentSize;
} }
template<typename T> template<typename T>
inline size_t FIFOBase<T>::next(size_t current) { inline size_t FIFOBase<T>::next(size_t current) {
++current; ++current;
if (current == maxCapacity) { if (current == maxCapacity) {
current = 0; current = 0;
} }
return current; return current;
} }
template<typename T> template<typename T>
inline size_t FIFOBase<T>::getMaxCapacity() const { inline size_t FIFOBase<T>::getMaxCapacity() const {
return maxCapacity; return maxCapacity;
} }
template<typename T> template<typename T>
inline void FIFOBase<T>::setContainer(T *data) { inline void FIFOBase<T>::setContainer(T *data) {
this->values = data; this->values = data;
} }
#endif #endif

View File

@ -8,30 +8,30 @@
*/ */
template<typename T, size_t MAX_SIZE, typename count_t = uint8_t> template<typename T, size_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList: public ArrayList<T, count_t> { class FixedArrayList: public ArrayList<T, count_t> {
static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE"); static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
private: private:
T data[MAX_SIZE]; T data[MAX_SIZE];
public: public:
FixedArrayList() : FixedArrayList() :
ArrayList<T, count_t>(data, MAX_SIZE) { ArrayList<T, count_t>(data, MAX_SIZE) {
} }
FixedArrayList(const FixedArrayList& other) : FixedArrayList(const FixedArrayList& other) :
ArrayList<T, count_t>(data, MAX_SIZE) { ArrayList<T, count_t>(data, MAX_SIZE) {
memcpy(this->data, other.data, sizeof(this->data)); memcpy(this->data, other.data, sizeof(this->data));
this->entries = data; this->entries = data;
this->size = other.size; this->size = other.size;
} }
FixedArrayList& operator=(FixedArrayList other) { FixedArrayList& operator=(FixedArrayList other) {
memcpy(this->data, other.data, sizeof(this->data)); memcpy(this->data, other.data, sizeof(this->data));
this->entries = data; this->entries = data;
this->size = other.size; this->size = other.size;
return *this; return *this;
} }
virtual ~FixedArrayList() { virtual ~FixedArrayList() {
} }
}; };

View File

@ -18,212 +18,212 @@
*/ */
template<typename key_t, typename T> template<typename key_t, typename T>
class FixedMap: public SerializeIF { class FixedMap: public SerializeIF {
static_assert (std::is_trivially_copyable<T>::value or static_assert (std::is_trivially_copyable<T>::value or
std::is_base_of<SerializeIF, T>::value, std::is_base_of<SerializeIF, T>::value,
"Types used in FixedMap must either be trivial copy-able or a " "Types used in FixedMap must either be trivial copy-able or a "
"derived class from SerializeIF to be serialize-able"); "derived class from SerializeIF to be serialize-able");
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
private: private:
static const key_t EMPTY_SLOT = -1; static const key_t EMPTY_SLOT = -1;
ArrayList<std::pair<key_t, T>, uint32_t> theMap; ArrayList<std::pair<key_t, T>, uint32_t> theMap;
uint32_t _size; uint32_t _size;
uint32_t findIndex(key_t key) const { uint32_t findIndex(key_t key) const {
if (_size == 0) { if (_size == 0) {
return 1; return 1;
} }
uint32_t i = 0; uint32_t i = 0;
for (i = 0; i < _size; ++i) { for (i = 0; i < _size; ++i) {
if (theMap[i].first == key) { if (theMap[i].first == key) {
return i; return i;
} }
} }
return i; return i;
} }
public: public:
FixedMap(uint32_t maxSize) : FixedMap(uint32_t maxSize) :
theMap(maxSize), _size(0) { theMap(maxSize), _size(0) {
} }
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator { class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
public: public:
Iterator() : Iterator() :
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() { ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
} }
Iterator(std::pair<key_t, T> *pair) : Iterator(std::pair<key_t, T> *pair) :
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) { ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
} }
}; };
friend bool operator==(const typename FixedMap::Iterator& lhs, friend bool operator==(const typename FixedMap::Iterator& lhs,
const typename FixedMap::Iterator& rhs) { const typename FixedMap::Iterator& rhs) {
return (lhs.value == rhs.value); return (lhs.value == rhs.value);
} }
friend bool operator!=(const typename FixedMap::Iterator& lhs, friend bool operator!=(const typename FixedMap::Iterator& lhs,
const typename FixedMap::Iterator& rhs) { const typename FixedMap::Iterator& rhs) {
return not (lhs.value == rhs.value); return not (lhs.value == rhs.value);
} }
Iterator begin() const { Iterator begin() const {
return Iterator(&theMap[0]); return Iterator(&theMap[0]);
} }
Iterator end() const { Iterator end() const {
return Iterator(&theMap[_size]); return Iterator(&theMap[_size]);
} }
uint32_t size() const { uint32_t size() const {
return _size; return _size;
} }
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) {
if (exists(key) == HasReturnvaluesIF::RETURN_OK) { if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
return KEY_ALREADY_EXISTS; return KEY_ALREADY_EXISTS;
} }
if (_size == theMap.maxSize()) { if (_size == theMap.maxSize()) {
return MAP_FULL; return MAP_FULL;
} }
theMap[_size].first = key; theMap[_size].first = key;
theMap[_size].second = value; theMap[_size].second = value;
if (storedValue != nullptr) { if (storedValue != nullptr) {
*storedValue = Iterator(&theMap[_size]); *storedValue = Iterator(&theMap[_size]);
} }
++_size; ++_size;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t insert(std::pair<key_t, T> pair) { ReturnValue_t insert(std::pair<key_t, T> pair) {
return insert(pair.first, pair.second); return insert(pair.first, pair.second);
} }
ReturnValue_t exists(key_t key) const { ReturnValue_t exists(key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST; ReturnValue_t result = KEY_DOES_NOT_EXIST;
if (findIndex(key) < _size) { if (findIndex(key) < _size) {
result = HasReturnvaluesIF::RETURN_OK; result = HasReturnvaluesIF::RETURN_OK;
} }
return result; return result;
} }
ReturnValue_t erase(Iterator *iter) { ReturnValue_t erase(Iterator *iter) {
uint32_t i; uint32_t i;
if ((i = findIndex((*iter).value->first)) >= _size) { if ((i = findIndex((*iter).value->first)) >= _size) {
return KEY_DOES_NOT_EXIST; return KEY_DOES_NOT_EXIST;
} }
theMap[i] = theMap[_size - 1]; theMap[i] = theMap[_size - 1];
--_size; --_size;
--((*iter).value); --((*iter).value);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t erase(key_t key) { ReturnValue_t erase(key_t key) {
uint32_t i; uint32_t i;
if ((i = findIndex(key)) >= _size) { if ((i = findIndex(key)) >= _size) {
return KEY_DOES_NOT_EXIST; return KEY_DOES_NOT_EXIST;
} }
theMap[i] = theMap[_size - 1]; theMap[i] = theMap[_size - 1];
--_size; --_size;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
T *findValue(key_t key) const { T *findValue(key_t key) const {
return &theMap[findIndex(key)].second; return &theMap[findIndex(key)].second;
} }
Iterator find(key_t key) const { Iterator find(key_t key) const {
ReturnValue_t result = exists(key); ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return end(); return end();
} }
return Iterator(&theMap[findIndex(key)]); return Iterator(&theMap[findIndex(key)]);
} }
ReturnValue_t find(key_t key, T **value) const { ReturnValue_t find(key_t key, T **value) const {
ReturnValue_t result = exists(key); ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
*value = &theMap[findIndex(key)].second; *value = &theMap[findIndex(key)].second;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
bool empty() { bool empty() {
if(_size == 0) { if(_size == 0) {
return true; return true;
} }
else { else {
return false; return false;
} }
} }
bool full() { bool full() {
if(_size >= theMap.maxSize()) { if(_size >= theMap.maxSize()) {
return true; return true;
} }
else { else {
return false; return false;
} }
} }
void clear() { void clear() {
_size = 0; _size = 0;
} }
uint32_t maxSize() const { uint32_t maxSize() const {
return theMap.maxSize(); return theMap.maxSize();
} }
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const { size_t maxSize, Endianness streamEndianness) const {
ReturnValue_t result = SerializeAdapter::serialize(&this->_size, ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
buffer, size, maxSize, streamEndianness); buffer, size, maxSize, streamEndianness);
uint32_t i = 0; uint32_t i = 0;
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) { while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
result = SerializeAdapter::serialize(&theMap[i].first, buffer, result = SerializeAdapter::serialize(&theMap[i].first, buffer,
size, maxSize, streamEndianness); size, maxSize, streamEndianness);
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size, result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
maxSize, streamEndianness); maxSize, streamEndianness);
++i; ++i;
} }
return result; return result;
} }
virtual size_t getSerializedSize() const { virtual size_t getSerializedSize() const {
uint32_t printSize = sizeof(_size); uint32_t printSize = sizeof(_size);
uint32_t i = 0; uint32_t i = 0;
for (i = 0; i < _size; ++i) { for (i = 0; i < _size; ++i) {
printSize += SerializeAdapter::getSerializedSize( printSize += SerializeAdapter::getSerializedSize(
&theMap[i].first); &theMap[i].first);
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second); printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
} }
return printSize; return printSize;
} }
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) { Endianness streamEndianness) {
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size, ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
buffer, size, streamEndianness); buffer, size, streamEndianness);
if (this->_size > theMap.maxSize()) { if (this->_size > theMap.maxSize()) {
return SerializeIF::TOO_MANY_ELEMENTS; return SerializeIF::TOO_MANY_ELEMENTS;
} }
uint32_t i = 0; uint32_t i = 0;
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) { while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer, result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
size, streamEndianness); size, streamEndianness);
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size, result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
streamEndianness); streamEndianness);
++i; ++i;
} }
return result; return result;
} }
}; };

View File

@ -34,172 +34,172 @@
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>> template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
class FixedOrderedMultimap { class FixedOrderedMultimap {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP; static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
/*** /***
* Constructor which needs a size_t for the maximum allowed size * Constructor which needs a size_t for the maximum allowed size
* *
* Can not be resized during runtime * Can not be resized during runtime
* *
* Allocates memory at construction * Allocates memory at construction
* @param maxSize size_t of Maximum allowed size * @param maxSize size_t of Maximum allowed size
*/ */
FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){ FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
} }
/*** /***
* Virtual destructor frees Memory by deleting its member * Virtual destructor frees Memory by deleting its member
*/ */
virtual ~FixedOrderedMultimap() { virtual ~FixedOrderedMultimap() {
} }
/*** /***
* Special iterator for FixedOrderedMultimap * Special iterator for FixedOrderedMultimap
*/ */
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator { class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
public: public:
Iterator() : Iterator() :
ArrayList<std::pair<key_t, T>, size_t>::Iterator() { ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
} }
Iterator(std::pair<key_t, T> *pair) : Iterator(std::pair<key_t, T> *pair) :
ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) { ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
} }
}; };
/*** /***
* Returns an iterator pointing to the first element * Returns an iterator pointing to the first element
* @return Iterator pointing to first element * @return Iterator pointing to first element
*/ */
Iterator begin() const { Iterator begin() const {
return Iterator(&theMap[0]); return Iterator(&theMap[0]);
} }
/** /**
* Returns an iterator pointing to one element past the end * Returns an iterator pointing to one element past the end
* @return Iterator pointing to one element past the end * @return Iterator pointing to one element past the end
*/ */
Iterator end() const { Iterator end() const {
return Iterator(&theMap[_size]); return Iterator(&theMap[_size]);
} }
/*** /***
* Returns the current size of the map (not maximum size!) * Returns the current size of the map (not maximum size!)
* @return Current size * @return Current size
*/ */
size_t size() const{ size_t size() const{
return _size; return _size;
} }
/** /**
* Clears the map, does not deallocate any memory * Clears the map, does not deallocate any memory
*/ */
void clear(){ void clear(){
_size = 0; _size = 0;
} }
/** /**
* Returns the maximum size of the map * Returns the maximum size of the map
* @return Maximum size of the map * @return Maximum size of the map
*/ */
size_t maxSize() const{ size_t maxSize() const{
return theMap.maxSize(); return theMap.maxSize();
} }
/*** /***
* Used to insert a key and value separately. * Used to insert a key and value separately.
* *
* @param[in] key Key of the new element * @param[in] key Key of the new element
* @param[in] value Value of the new element * @param[in] value Value of the new element
* @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr * @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available * @return RETURN_OK if insert was successful, MAP_FULL if no space is available
*/ */
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr); ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
/*** /***
* Used to insert new pair instead of single values * Used to insert new pair instead of single values
* *
* @param pair Pair to be inserted * @param pair Pair to be inserted
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available * @return RETURN_OK if insert was successful, MAP_FULL if no space is available
*/ */
ReturnValue_t insert(std::pair<key_t, T> pair); ReturnValue_t insert(std::pair<key_t, T> pair);
/*** /***
* Can be used to check if a certain key is in the map * Can be used to check if a certain key is in the map
* @param key Key to be checked * @param key Key to be checked
* @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise * @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
*/ */
ReturnValue_t exists(key_t key) const; ReturnValue_t exists(key_t key) const;
/*** /***
* Used to delete the element in the iterator * Used to delete the element in the iterator
* *
* The iterator will point to the element before or begin(), * The iterator will point to the element before or begin(),
* but never to one element in front of the map. * but never to one element in front of the map.
* *
* @warning The iterator needs to be valid and dereferenceable * @warning The iterator needs to be valid and dereferenceable
* @param[in/out] iter Pointer to iterator to the element that needs to be ereased * @param[in/out] iter Pointer to iterator to the element that needs to be ereased
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
*/ */
ReturnValue_t erase(Iterator *iter); ReturnValue_t erase(Iterator *iter);
/*** /***
* Used to erase by key * Used to erase by key
* @param key Key to be erased * @param key Key to be erased
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
*/ */
ReturnValue_t erase(key_t key); ReturnValue_t erase(key_t key);
/*** /***
* Find returns the first appearance of the key * Find returns the first appearance of the key
* *
* If the key does not exist, it points to end() * If the key does not exist, it points to end()
* *
* @param key Key to search for * @param key Key to search for
* @return Iterator pointing to the first entry of key * @return Iterator pointing to the first entry of key
*/ */
Iterator find(key_t key) const{ Iterator find(key_t key) const{
ReturnValue_t result = exists(key); ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return end(); return end();
} }
return Iterator(&theMap[findFirstIndex(key)]); return Iterator(&theMap[findFirstIndex(key)]);
}; };
/*** /***
* Finds first entry of the given key and returns a * Finds first entry of the given key and returns a
* pointer to the value * pointer to the value
* *
* @param key Key to search for * @param key Key to search for
* @param value Found value * @param value Found value
* @return RETURN_OK if it points to the value, * @return RETURN_OK if it points to the value,
* KEY_DOES_NOT_EXIST if the key is not in the map * KEY_DOES_NOT_EXIST if the key is not in the map
*/ */
ReturnValue_t find(key_t key, T **value) const; ReturnValue_t find(key_t key, T **value) const;
friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs, friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs,
const typename FixedOrderedMultimap::Iterator& rhs) { const typename FixedOrderedMultimap::Iterator& rhs) {
return (lhs.value == rhs.value); return (lhs.value == rhs.value);
} }
friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs, friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
const typename FixedOrderedMultimap::Iterator& rhs) { const typename FixedOrderedMultimap::Iterator& rhs) {
return not (lhs.value == rhs.value); return not (lhs.value == rhs.value);
} }
private: private:
typedef KEY_COMPARE compare; typedef KEY_COMPARE compare;
compare myComp; compare myComp;
ArrayList<std::pair<key_t, T>, size_t> theMap; ArrayList<std::pair<key_t, T>, size_t> theMap;
size_t _size; size_t _size;
size_t findFirstIndex(key_t key, size_t startAt = 0) const; size_t findFirstIndex(key_t key, size_t startAt = 0) const;
size_t findNicePlace(key_t key) const; size_t findNicePlace(key_t key) const;
void removeFromPosition(size_t position); void removeFromPosition(size_t position);
}; };
#include "FixedOrderedMultimap.tpp" #include "FixedOrderedMultimap.tpp"

View File

@ -4,105 +4,105 @@
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) { inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
if (_size == theMap.maxSize()) { if (_size == theMap.maxSize()) {
return MAP_FULL; return MAP_FULL;
} }
size_t position = findNicePlace(key); size_t position = findNicePlace(key);
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]), memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
(_size - position) * sizeof(std::pair<key_t,T>)); (_size - position) * sizeof(std::pair<key_t,T>));
theMap[position].first = key; theMap[position].first = key;
theMap[position].second = value; theMap[position].second = value;
++_size; ++_size;
if (storedValue != nullptr) { if (storedValue != nullptr) {
*storedValue = Iterator(&theMap[position]); *storedValue = Iterator(&theMap[position]);
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) { inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
return insert(pair.first, pair.second); return insert(pair.first, pair.second);
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const { inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST; ReturnValue_t result = KEY_DOES_NOT_EXIST;
if (findFirstIndex(key) < _size) { if (findFirstIndex(key) < _size) {
result = HasReturnvaluesIF::RETURN_OK; result = HasReturnvaluesIF::RETURN_OK;
} }
return result; return result;
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) { inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
size_t i; size_t i;
if ((i = findFirstIndex((*iter).value->first)) >= _size) { if ((i = findFirstIndex((*iter).value->first)) >= _size) {
return KEY_DOES_NOT_EXIST; return KEY_DOES_NOT_EXIST;
} }
removeFromPosition(i); removeFromPosition(i);
if (*iter != begin()) { if (*iter != begin()) {
(*iter)--; (*iter)--;
} else { } else {
*iter = begin(); *iter = begin();
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) { inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
size_t i; size_t i;
if ((i = findFirstIndex(key)) >= _size) { if ((i = findFirstIndex(key)) >= _size) {
return KEY_DOES_NOT_EXIST; return KEY_DOES_NOT_EXIST;
} }
do { do {
removeFromPosition(i); removeFromPosition(i);
i = findFirstIndex(key, i); i = findFirstIndex(key, i);
} while (i < _size); } while (i < _size);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const { inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
ReturnValue_t result = exists(key); ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
*value = &theMap[findFirstIndex(key)].second; *value = &theMap[findFirstIndex(key)].second;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const { inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
if (startAt >= _size) { if (startAt >= _size) {
return startAt + 1; return startAt + 1;
} }
size_t i = startAt; size_t i = startAt;
for (i = startAt; i < _size; ++i) { for (i = startAt; i < _size; ++i) {
if (theMap[i].first == key) { if (theMap[i].first == key) {
return i; return i;
} }
} }
return i; return i;
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const { inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
size_t i = 0; size_t i = 0;
for (i = 0; i < _size; ++i) { for (i = 0; i < _size; ++i) {
if (myComp(key, theMap[i].first)) { if (myComp(key, theMap[i].first)) {
return i; return i;
} }
} }
return i; return i;
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) { inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
if (_size <= position) { if (_size <= position) {
return; return;
} }
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]), memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
(_size - position - 1) * sizeof(std::pair<key_t,T>)); (_size - position - 1) * sizeof(std::pair<key_t,T>));
--_size; --_size;
} }

View File

@ -6,85 +6,85 @@
template<typename T, typename count_t = uint8_t> template<typename T, typename count_t = uint8_t>
class HybridIterator: public LinkedElement<T>::Iterator, class HybridIterator: public LinkedElement<T>::Iterator,
public ArrayList<T, count_t>::Iterator { public ArrayList<T, count_t>::Iterator {
public: public:
HybridIterator() {} HybridIterator() {}
HybridIterator(typename LinkedElement<T>::Iterator *iter) : HybridIterator(typename LinkedElement<T>::Iterator *iter) :
LinkedElement<T>::Iterator(*iter), value(iter->value), LinkedElement<T>::Iterator(*iter), value(iter->value),
linked(true) { linked(true) {
} }
HybridIterator(LinkedElement<T> *start) : HybridIterator(LinkedElement<T> *start) :
LinkedElement<T>::Iterator(start), value(start->value), LinkedElement<T>::Iterator(start), value(start->value),
linked(true) { linked(true) {
} }
HybridIterator(typename ArrayList<T, count_t>::Iterator start, HybridIterator(typename ArrayList<T, count_t>::Iterator start,
typename ArrayList<T, count_t>::Iterator end) : typename ArrayList<T, count_t>::Iterator end) :
ArrayList<T, count_t>::Iterator(start), value(start.value), ArrayList<T, count_t>::Iterator(start), value(start.value),
linked(false), end(end.value) { linked(false), end(end.value) {
if (value == this->end) { if (value == this->end) {
value = NULL; value = NULL;
} }
} }
HybridIterator(T *firstElement, T *lastElement) : HybridIterator(T *firstElement, T *lastElement) :
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement), ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
linked(false), end(++lastElement) { linked(false), end(++lastElement) {
if (value == end) { if (value == end) {
value = NULL; value = NULL;
} }
} }
HybridIterator& operator++() { HybridIterator& operator++() {
if (linked) { if (linked) {
LinkedElement<T>::Iterator::operator++(); LinkedElement<T>::Iterator::operator++();
if (LinkedElement<T>::Iterator::value != nullptr) { if (LinkedElement<T>::Iterator::value != nullptr) {
value = LinkedElement<T>::Iterator::value->value; value = LinkedElement<T>::Iterator::value->value;
} else { } else {
value = nullptr; value = nullptr;
} }
} else { } else {
ArrayList<T, count_t>::Iterator::operator++(); ArrayList<T, count_t>::Iterator::operator++();
value = ArrayList<T, count_t>::Iterator::value; value = ArrayList<T, count_t>::Iterator::value;
if (value == end) { if (value == end) {
value = nullptr; value = nullptr;
} }
} }
return *this; return *this;
} }
HybridIterator operator++(int) { HybridIterator operator++(int) {
HybridIterator tmp(*this); HybridIterator tmp(*this);
operator++(); operator++();
return tmp; return tmp;
} }
bool operator==(const HybridIterator& other) const { bool operator==(const HybridIterator& other) const {
return value == other.value; return value == other.value;
} }
bool operator!=(const HybridIterator& other) const { bool operator!=(const HybridIterator& other) const {
return !(*this == other); return !(*this == other);
} }
T operator*() { T operator*() {
return *value; return *value;
} }
T *operator->() { T *operator->() {
return value; return value;
} }
T* value = nullptr; T* value = nullptr;
private: private:
bool linked = false; bool linked = false;
T *end = nullptr; T *end = nullptr;
}; };
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */ #endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -22,50 +22,50 @@
*/ */
class PlacementFactory { class PlacementFactory {
public: public:
PlacementFactory(StorageManagerIF* backend) : PlacementFactory(StorageManagerIF* backend) :
dataBackend(backend) { dataBackend(backend) {
} }
/*** /***
* Generates an object of type T in the backend storage. * Generates an object of type T in the backend storage.
* *
* @warning Do not use with any Type that allocates memory internally! * @warning Do not use with any Type that allocates memory internally!
* *
* @tparam T Type of Object * @tparam T Type of Object
* @param args Constructor Arguments to be passed * @param args Constructor Arguments to be passed
* @return A pointer to the new object or a nullptr in case of failure * @return A pointer to the new object or a nullptr in case of failure
*/ */
template<typename T, typename ... Args> template<typename T, typename ... Args>
T* generate(Args&&... args) { T* generate(Args&&... args) {
store_address_t tempId; store_address_t tempId;
uint8_t* pData = nullptr; uint8_t* pData = nullptr;
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T), ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
&pData); &pData);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return nullptr; return nullptr;
} }
T* temp = new (pData) T(std::forward<Args>(args)...); T* temp = new (pData) T(std::forward<Args>(args)...);
return temp; return temp;
} }
/*** /***
* Function to destroy the object allocated with generate and free space in backend. * Function to destroy the object allocated with generate and free space in backend.
* This must be called by the user. * This must be called by the user.
* *
* @param thisElement Element to be destroyed * @param thisElement Element to be destroyed
* @return RETURN_OK if the element was destroyed, different errors on failure * @return RETURN_OK if the element was destroyed, different errors on failure
*/ */
template<typename T> template<typename T>
ReturnValue_t destroy(T* thisElement) { ReturnValue_t destroy(T* thisElement) {
if (thisElement == nullptr){ if (thisElement == nullptr){
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however). //Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
thisElement->~T(); thisElement->~T();
uint8_t* pointer = (uint8_t*) (thisElement); uint8_t* pointer = (uint8_t*) (thisElement);
return dataBackend->deleteData(pointer, sizeof(T)); return dataBackend->deleteData(pointer, sizeof(T));
} }
private: private:
StorageManagerIF* dataBackend; StorageManagerIF* dataBackend;
}; };
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */ #endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */

View File

@ -7,107 +7,107 @@
template<uint8_t N_READ_PTRS = 1> template<uint8_t N_READ_PTRS = 1>
class RingBufferBase { class RingBufferBase {
public: public:
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) : RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
start(startAddress), write(startAddress), size(size), start(startAddress), write(startAddress), size(size),
overwriteOld(overwriteOld) { overwriteOld(overwriteOld) {
for (uint8_t count = 0; count < N_READ_PTRS; count++) { for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = startAddress; read[count] = startAddress;
} }
} }
virtual ~RingBufferBase() {} virtual ~RingBufferBase() {}
bool isFull(uint8_t n = 0) { bool isFull(uint8_t n = 0) {
return (availableWriteSpace(n) == 0); return (availableWriteSpace(n) == 0);
} }
bool isEmpty(uint8_t n = 0) { bool isEmpty(uint8_t n = 0) {
return (getAvailableReadData(n) == 0); return (getAvailableReadData(n) == 0);
} }
size_t getAvailableReadData(uint8_t n = 0) const { size_t getAvailableReadData(uint8_t n = 0) const {
return ((write + size) - read[n]) % size; return ((write + size) - read[n]) % size;
} }
size_t availableWriteSpace(uint8_t n = 0) const { size_t availableWriteSpace(uint8_t n = 0) const {
//One less to avoid ambiguous full/empty problem. //One less to avoid ambiguous full/empty problem.
return (((read[n] + size) - write - 1) % size); return (((read[n] + size) - write - 1) % size);
} }
bool overwritesOld() const { bool overwritesOld() const {
return overwriteOld; return overwriteOld;
} }
size_t getMaxSize() const { size_t getMaxSize() const {
return size - 1; return size - 1;
} }
void clear() { void clear() {
write = start; write = start;
for (uint8_t count = 0; count < N_READ_PTRS; count++) { for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = start; read[count] = start;
} }
} }
size_t writeTillWrap() { size_t writeTillWrap() {
return (start + size) - write; return (start + size) - write;
} }
size_t readTillWrap(uint8_t n = 0) { size_t readTillWrap(uint8_t n = 0) {
return (start + size) - read[n]; return (start + size) - read[n];
} }
size_t getStart() const { size_t getStart() const {
return start; return start;
} }
protected: protected:
const size_t start; const size_t start;
size_t write; size_t write;
size_t read[N_READ_PTRS]; size_t read[N_READ_PTRS];
const size_t size; const size_t size;
const bool overwriteOld; const bool overwriteOld;
void incrementWrite(uint32_t amount) { void incrementWrite(uint32_t amount) {
write = ((write + amount - start) % size) + start; write = ((write + amount - start) % size) + start;
} }
void incrementRead(uint32_t amount, uint8_t n = 0) { void incrementRead(uint32_t amount, uint8_t n = 0) {
read[n] = ((read[n] + amount - start) % size) + start; read[n] = ((read[n] + amount - start) % size) + start;
} }
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) { ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
if (getAvailableReadData(n) >= amount) { if (getAvailableReadData(n) >= amount) {
incrementRead(amount, n); incrementRead(amount, n);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
ReturnValue_t writeData(uint32_t amount) { ReturnValue_t writeData(uint32_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) { if (availableWriteSpace() >= amount or overwriteOld) {
incrementWrite(amount); incrementWrite(amount);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
size_t getRead(uint8_t n = 0) const { size_t getRead(uint8_t n = 0) const {
return read[n]; return read[n];
} }
void setRead(uint32_t read, uint8_t n = 0) { void setRead(uint32_t read, uint8_t n = 0) {
if (read >= start && read < (start+size)) { if (read >= start && read < (start+size)) {
this->read[n] = read; this->read[n] = read;
} }
} }
uint32_t getWrite() const { uint32_t getWrite() const {
return write; return write;
} }
void setWrite(uint32_t write) { void setWrite(uint32_t write) {
this->write = write; this->write = write;
} }
}; };
#endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */ #endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */

View File

@ -3,23 +3,23 @@
#include "../ipc/MutexHelper.h" #include "../ipc/MutexHelper.h"
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size, SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes): bool overwriteOld, size_t maxExcessBytes):
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld, SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
maxExcessBytes) { maxExcessBytes) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer, SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
const size_t size, bool overwriteOld, size_t maxExcessBytes): const size_t size, bool overwriteOld, size_t maxExcessBytes):
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld, SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
maxExcessBytes) { maxExcessBytes) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) { void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) {
this->fifoDepth = fifoDepth; this->fifoDepth = fifoDepth;
} }
ReturnValue_t SharedRingBuffer::lockRingBufferMutex( ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
@ -38,20 +38,20 @@ MutexIF* SharedRingBuffer::getMutexHandle() const {
} }
ReturnValue_t SharedRingBuffer::initialize() { ReturnValue_t SharedRingBuffer::initialize() {
if(fifoDepth > 0) { if(fifoDepth > 0) {
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth); receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
} }
return SystemObject::initialize(); return SystemObject::initialize();
} }
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() { DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
if(receiveSizesFIFO == nullptr) { if(receiveSizesFIFO == nullptr) {
// Configuration error. // Configuration error.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer" sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
<< " was not configured to have sizes FIFO, returning nullptr!" << " was not configured to have sizes FIFO, returning nullptr!"
<< std::endl; << std::endl;
#endif #endif
} }
return receiveSizesFIFO; return receiveSizesFIFO;
} }

View File

@ -15,76 +15,76 @@
* and unlock operations. * and unlock operations.
*/ */
class SharedRingBuffer: public SystemObject, class SharedRingBuffer: public SystemObject,
public SimpleRingBuffer { public SimpleRingBuffer {
public: public:
/** /**
* This constructor allocates a new internal buffer with the supplied size. * This constructor allocates a new internal buffer with the supplied size.
* @param size * @param size
* @param overwriteOld * @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data * If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten. * will be overwritten.
*/ */
SharedRingBuffer(object_id_t objectId, const size_t size, SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes); bool overwriteOld, size_t maxExcessBytes);
/** /**
* @brief This function can be used to add an optional FIFO to the class * @brief This function can be used to add an optional FIFO to the class
* @details * @details
* This FIFO will be allocated in the initialize function (and will * This FIFO will be allocated in the initialize function (and will
* have a fixed maximum size after that). It can be used to store * have a fixed maximum size after that). It can be used to store
* values like packet sizes, for example for a shared ring buffer * values like packet sizes, for example for a shared ring buffer
* used by producer/consumer tasks. * used by producer/consumer tasks.
*/ */
void setToUseReceiveSizeFIFO(size_t fifoDepth); void setToUseReceiveSizeFIFO(size_t fifoDepth);
/** /**
* This constructor takes an external buffer with the specified size. * This constructor takes an external buffer with the specified size.
* @param buffer * @param buffer
* @param size * @param size
* @param overwriteOld * @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data * If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten. * will be overwritten.
*/ */
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size, SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes); bool overwriteOld, size_t maxExcessBytes);
/** /**
* Unless a read-only constant value is read, all operations on the * Unless a read-only constant value is read, all operations on the
* shared ring buffer should be protected by calling this function. * shared ring buffer should be protected by calling this function.
* @param timeoutType * @param timeoutType
* @param timeout * @param timeout
* @return * @return
*/ */
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType, virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
dur_millis_t timeout); dur_millis_t timeout);
/** /**
* Any locked mutex also has to be unlocked, otherwise, access to the * Any locked mutex also has to be unlocked, otherwise, access to the
* shared ring buffer will be blocked. * shared ring buffer will be blocked.
* @return * @return
*/ */
virtual ReturnValue_t unlockRingBufferMutex(); virtual ReturnValue_t unlockRingBufferMutex();
/** /**
* The mutex handle can be accessed directly, for example to perform * The mutex handle can be accessed directly, for example to perform
* the lock with the #MutexHelper for a RAII compliant lock operation. * the lock with the #MutexHelper for a RAII compliant lock operation.
* @return * @return
*/ */
MutexIF* getMutexHandle() const; MutexIF* getMutexHandle() const;
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
/** /**
* If the shared ring buffer was configured to have a sizes FIFO, a handle * If the shared ring buffer was configured to have a sizes FIFO, a handle
* to that FIFO can be retrieved with this function. * to that FIFO can be retrieved with this function.
* Do not forget to protect access with a lock if required! * Do not forget to protect access with a lock if required!
* @return * @return
*/ */
DynamicFIFO<size_t>* getReceiveSizesFIFO(); DynamicFIFO<size_t>* getReceiveSizesFIFO();
private: private:
MutexIF* mutex = nullptr; MutexIF* mutex = nullptr;
size_t fifoDepth = 0; size_t fifoDepth = 0;
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr; DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
}; };

View File

@ -2,31 +2,31 @@
#include <cstring> #include <cstring>
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
size_t maxExcessBytes) : size_t maxExcessBytes) :
RingBufferBase<>(0, size, overwriteOld), RingBufferBase<>(0, size, overwriteOld),
maxExcessBytes(maxExcessBytes) { maxExcessBytes(maxExcessBytes) {
if(maxExcessBytes > size) { if(maxExcessBytes > size) {
this->maxExcessBytes = size; this->maxExcessBytes = size;
} }
else { else {
this->maxExcessBytes = maxExcessBytes; this->maxExcessBytes = maxExcessBytes;
} }
buffer = new uint8_t[size + maxExcessBytes]; buffer = new uint8_t[size + maxExcessBytes];
} }
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size, SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes): bool overwriteOld, size_t maxExcessBytes):
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) { RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
if(maxExcessBytes > size) { if(maxExcessBytes > size) {
this->maxExcessBytes = size; this->maxExcessBytes = size;
} }
else { else {
this->maxExcessBytes = maxExcessBytes; this->maxExcessBytes = maxExcessBytes;
} }
} }
SimpleRingBuffer::~SimpleRingBuffer() { SimpleRingBuffer::~SimpleRingBuffer() {
delete[] buffer; delete[] buffer;
} }
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
@ -48,58 +48,58 @@ ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
} }
void SimpleRingBuffer::confirmBytesWritten(size_t amount) { void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
if(getExcessBytes() > 0) { if(getExcessBytes() > 0) {
moveExcessBytesToStart(); moveExcessBytesToStart();
} }
incrementWrite(amount); incrementWrite(amount);
} }
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
size_t amount) { size_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) { if (availableWriteSpace() >= amount or overwriteOld) {
size_t amountTillWrap = writeTillWrap(); size_t amountTillWrap = writeTillWrap();
if (amountTillWrap >= amount) { if (amountTillWrap >= amount) {
// remaining size in buffer is sufficient to fit full amount. // remaining size in buffer is sufficient to fit full amount.
memcpy(&buffer[write], data, amount); memcpy(&buffer[write], data, amount);
} }
else { else {
memcpy(&buffer[write], data, amountTillWrap); memcpy(&buffer[write], data, amountTillWrap);
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap); memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
} }
incrementWrite(amount); incrementWrite(amount);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount, ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) { bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR); size_t availableData = getAvailableReadData(READ_PTR);
size_t amountTillWrap = readTillWrap(READ_PTR); size_t amountTillWrap = readTillWrap(READ_PTR);
if (availableData < amount) { if (availableData < amount) {
if (readRemaining) { if (readRemaining) {
// more data available than amount specified. // more data available than amount specified.
amount = availableData; amount = availableData;
} else { } else {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
if (trueAmount != nullptr) { if (trueAmount != nullptr) {
*trueAmount = amount; *trueAmount = amount;
} }
if (amountTillWrap >= amount) { if (amountTillWrap >= amount) {
memcpy(data, &buffer[read[READ_PTR]], amount); memcpy(data, &buffer[read[READ_PTR]], amount);
} else { } else {
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap); memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap); memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
} }
if(incrementReadPtr) { if(incrementReadPtr) {
deleteData(amount, readRemaining); deleteData(amount, readRemaining);
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
size_t SimpleRingBuffer::getExcessBytes() const { size_t SimpleRingBuffer::getExcessBytes() const {
@ -114,18 +114,18 @@ void SimpleRingBuffer::moveExcessBytesToStart() {
} }
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount, ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
bool deleteRemaining, size_t* trueAmount) { bool deleteRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR); size_t availableData = getAvailableReadData(READ_PTR);
if (availableData < amount) { if (availableData < amount) {
if (deleteRemaining) { if (deleteRemaining) {
amount = availableData; amount = availableData;
} else { } else {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
if (trueAmount != nullptr) { if (trueAmount != nullptr) {
*trueAmount = amount; *trueAmount = amount;
} }
incrementRead(amount, READ_PTR); incrementRead(amount, READ_PTR);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -5,7 +5,7 @@
#include <cstddef> #include <cstddef>
/** /**
* @brief Circular buffer implementation, useful for buffering * @brief Circular buffer implementation, useful for buffering
* into data streams. * into data streams.
* @details * @details
* Note that the deleteData() has to be called to increment the read pointer. * Note that the deleteData() has to be called to increment the read pointer.
@ -25,104 +25,104 @@ public:
* with getFreeElement. * with getFreeElement.
* *
*/ */
SimpleRingBuffer(const size_t size, bool overwriteOld, SimpleRingBuffer(const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0); size_t maxExcessBytes = 0);
/** /**
* This constructor takes an external buffer with the specified size. * This constructor takes an external buffer with the specified size.
* @param buffer * @param buffer
* @param size * @param size
* @param overwriteOld * @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data * If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten. * will be overwritten.
* @param maxExcessBytes * @param maxExcessBytes
* If the buffer can accomodate additional bytes for contigous write * If the buffer can accomodate additional bytes for contigous write
* operations with getFreeElement, this is the maximum allowed additional * operations with getFreeElement, this is the maximum allowed additional
* size * size
*/ */
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld, SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0); size_t maxExcessBytes = 0);
virtual ~SimpleRingBuffer(); virtual ~SimpleRingBuffer();
/** /**
* Write to circular buffer and increment write pointer by amount. * Write to circular buffer and increment write pointer by amount.
* @param data * @param data
* @param amount * @param amount
* @return -@c RETURN_OK if write operation was successfull * @return -@c RETURN_OK if write operation was successfull
* -@c RETURN_FAILED if * -@c RETURN_FAILED if
*/ */
ReturnValue_t writeData(const uint8_t* data, size_t amount); ReturnValue_t writeData(const uint8_t* data, size_t amount);
/** /**
* Returns a pointer to a free element. If the remaining buffer is * Returns a pointer to a free element. If the remaining buffer is
* not large enough, the data will be written past the actual size * not large enough, the data will be written past the actual size
* and the amount of excess bytes will be cached. This function * and the amount of excess bytes will be cached. This function
* does not increment the write pointer! * does not increment the write pointer!
* @param writePointer Pointer to a pointer which can be used to write * @param writePointer Pointer to a pointer which can be used to write
* contiguous blocks into the ring buffer * contiguous blocks into the ring buffer
* @param amount * @param amount
* @return * @return
*/ */
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount); ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
/** /**
* This increments the write pointer and also copies the excess bytes * This increments the write pointer and also copies the excess bytes
* to the beginning. It should be called if the write operation * to the beginning. It should be called if the write operation
* conducted after calling getFreeElement() was performed. * conducted after calling getFreeElement() was performed.
* @return * @return
*/ */
void confirmBytesWritten(size_t amount); void confirmBytesWritten(size_t amount);
virtual size_t getExcessBytes() const; virtual size_t getExcessBytes() const;
/** /**
* Helper functions which moves any excess bytes to the start * Helper functions which moves any excess bytes to the start
* of the ring buffer. * of the ring buffer.
* @return * @return
*/ */
virtual void moveExcessBytesToStart(); virtual void moveExcessBytesToStart();
/** /**
* Read from circular buffer at read pointer. * Read from circular buffer at read pointer.
* @param data * @param data
* @param amount * @param amount
* @param incrementReadPtr * @param incrementReadPtr
* If this is set to true, the read pointer will be incremented. * If this is set to true, the read pointer will be incremented.
* If readRemaining is set to true, the read pointer will be incremented * If readRemaining is set to true, the read pointer will be incremented
* accordingly. * accordingly.
* @param readRemaining * @param readRemaining
* If this is set to true, the data will be read even if the amount * If this is set to true, the data will be read even if the amount
* specified exceeds the read data available. * specified exceeds the read data available.
* @param trueAmount [out] * @param trueAmount [out]
* If readRemaining was set to true, the true amount read will be assigned * If readRemaining was set to true, the true amount read will be assigned
* to the passed value. * to the passed value.
* @return * @return
* - @c RETURN_OK if data was read successfully * - @c RETURN_OK if data was read successfully
* - @c RETURN_FAILED if not enough data was available and readRemaining * - @c RETURN_FAILED if not enough data was available and readRemaining
* was set to false. * was set to false.
*/ */
ReturnValue_t readData(uint8_t* data, size_t amount, ReturnValue_t readData(uint8_t* data, size_t amount,
bool incrementReadPtr = false, bool readRemaining = false, bool incrementReadPtr = false, bool readRemaining = false,
size_t* trueAmount = nullptr); size_t* trueAmount = nullptr);
/** /**
* Delete data by incrementing read pointer. * Delete data by incrementing read pointer.
* @param amount * @param amount
* @param deleteRemaining * @param deleteRemaining
* If the amount specified is larger than the remaing size to read and this * If the amount specified is larger than the remaing size to read and this
* is set to true, the remaining amount will be deleted as well * is set to true, the remaining amount will be deleted as well
* @param trueAmount [out] * @param trueAmount [out]
* If deleteRemaining was set to true, the amount deleted will be assigned * If deleteRemaining was set to true, the amount deleted will be assigned
* to the passed value. * to the passed value.
* @return * @return
*/ */
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false, ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
size_t* trueAmount = nullptr); size_t* trueAmount = nullptr);
private: private:
static const uint8_t READ_PTR = 0; static const uint8_t READ_PTR = 0;
uint8_t* buffer = nullptr; uint8_t* buffer = nullptr;
size_t maxExcessBytes; size_t maxExcessBytes;
size_t excessBytes = 0; size_t excessBytes = 0;
}; };
#endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */ #endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */

View File

@ -5,71 +5,71 @@
#include <cstdint> #include <cstdint>
/** /**
* @brief Linked list data structure, * @brief Linked list data structure,
* each entry has a pointer to the next entry (singly) * each entry has a pointer to the next entry (singly)
* @ingroup container * @ingroup container
*/ */
template<typename T> template<typename T>
class LinkedElement { class LinkedElement {
public: public:
T *value; T *value;
class Iterator { class Iterator {
public: public:
LinkedElement<T> *value = nullptr; LinkedElement<T> *value = nullptr;
Iterator() {} Iterator() {}
Iterator(LinkedElement<T> *element) : Iterator(LinkedElement<T> *element) :
value(element) { value(element) {
} }
Iterator& operator++() { Iterator& operator++() {
value = value->getNext(); value = value->getNext();
return *this; return *this;
} }
Iterator operator++(int) { Iterator operator++(int) {
Iterator tmp(*this); Iterator tmp(*this);
operator++(); operator++();
return tmp; return tmp;
} }
bool operator==(Iterator other) { bool operator==(Iterator other) {
return value == other.value; return value == other.value;
} }
bool operator!=(Iterator other) { bool operator!=(Iterator other) {
return !(*this == other); return !(*this == other);
} }
T *operator->() { T *operator->() {
return value->value; return value->value;
} }
}; };
LinkedElement(T* setElement, LinkedElement<T>* setNext = nullptr): LinkedElement(T* setElement, LinkedElement<T>* setNext = nullptr):
value(setElement), next(setNext) {} value(setElement), next(setNext) {}
virtual ~LinkedElement(){} virtual ~LinkedElement(){}
virtual LinkedElement* getNext() const { virtual LinkedElement* getNext() const {
return next; return next;
} }
virtual void setNext(LinkedElement* next) { virtual void setNext(LinkedElement* next) {
this->next = next; this->next = next;
} }
virtual void setEnd() { virtual void setEnd() {
this->next = nullptr; this->next = nullptr;
} }
LinkedElement* begin() { LinkedElement* begin() {
return this; return this;
} }
LinkedElement* end() { LinkedElement* end() {
return nullptr; return nullptr;
} }
private: private:
LinkedElement *next; LinkedElement *next;
}; };
template<typename T> template<typename T>
@ -77,52 +77,52 @@ class SinglyLinkedList {
public: public:
using ElementIterator = typename LinkedElement<T>::Iterator; using ElementIterator = typename LinkedElement<T>::Iterator;
SinglyLinkedList() {} SinglyLinkedList() {}
SinglyLinkedList(ElementIterator start) : SinglyLinkedList(ElementIterator start) :
start(start.value) {} start(start.value) {}
SinglyLinkedList(LinkedElement<T>* startElement) : SinglyLinkedList(LinkedElement<T>* startElement) :
start(startElement) {} start(startElement) {}
ElementIterator begin() const { ElementIterator begin() const {
return ElementIterator::Iterator(start); return ElementIterator::Iterator(start);
} }
/** Returns iterator to nulltr */ /** Returns iterator to nulltr */
ElementIterator end() const { ElementIterator end() const {
return ElementIterator::Iterator(); return ElementIterator::Iterator();
} }
/** /**
* Returns last element in singly linked list. * Returns last element in singly linked list.
* @return * @return
*/ */
ElementIterator back() const { ElementIterator back() const {
LinkedElement<T> *element = start; LinkedElement<T> *element = start;
while (element->getNext() != nullptr) { while (element->getNext() != nullptr) {
element = element->getNext(); element = element->getNext();
} }
return ElementIterator::Iterator(element); return ElementIterator::Iterator(element);
} }
size_t getSize() const { size_t getSize() const {
size_t size = 0; size_t size = 0;
LinkedElement<T> *element = start; LinkedElement<T> *element = start;
while (element != nullptr) { while (element != nullptr) {
size++; size++;
element = element->getNext(); element = element->getNext();
} }
return size; return size;
} }
void setStart(LinkedElement<T>* firstElement) { void setStart(LinkedElement<T>* firstElement) {
start = firstElement; start = firstElement;
} }
void setNext(LinkedElement<T>* currentElement, void setNext(LinkedElement<T>* currentElement,
LinkedElement<T>* nextElement) { LinkedElement<T>* nextElement) {
currentElement->setNext(nextElement); currentElement->setNext(nextElement);
} }
void setLast(LinkedElement<T>* lastElement) { void setLast(LinkedElement<T>* lastElement) {
lastElement->setEnd(); lastElement->setEnd();
@ -148,7 +148,7 @@ public:
} }
protected: protected:
LinkedElement<T> *start = nullptr; LinkedElement<T> *start = nullptr;
}; };
#endif /* SINGLYLINKEDLIST_H_ */ #endif /* SINGLYLINKEDLIST_H_ */

View File

@ -1,4 +1,4 @@
target_sources(${LIB_FSFW_NAME} target_sources(${LIB_FSFW_NAME}
PRIVATE PRIVATE
ControllerBase.cpp ControllerBase.cpp
) )

View File

@ -5,128 +5,128 @@
#include "../action/HasActionsIF.h" #include "../action/HasActionsIF.h"
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId, ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth) : size_t commandQueueDepth) :
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
submode(SUBMODE_NONE), modeHelper(this), submode(SUBMODE_NONE), modeHelper(this),
healthHelper(this, setObjectId) { healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue( commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth); commandQueueDepth);
} }
ControllerBase::~ControllerBase() { ControllerBase::~ControllerBase() {
QueueFactory::instance()->deleteMessageQueue(commandQueue); QueueFactory::instance()->deleteMessageQueue(commandQueue);
} }
ReturnValue_t ControllerBase::initialize() { ReturnValue_t ControllerBase::initialize() {
ReturnValue_t result = SystemObject::initialize(); ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) { if (result != RETURN_OK) {
return result; return result;
} }
MessageQueueId_t parentQueue = 0; MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) { if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId); SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == nullptr) { if (parent == nullptr) {
return RETURN_FAILED; return RETURN_FAILED;
} }
parentQueue = parent->getCommandQueue(); parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId()); parent->registerChild(getObjectId());
} }
result = healthHelper.initialize(parentQueue); result = healthHelper.initialize(parentQueue);
if (result != RETURN_OK) { if (result != RETURN_OK) {
return result; return result;
} }
result = modeHelper.initialize(parentQueue); result = modeHelper.initialize(parentQueue);
if (result != RETURN_OK) { if (result != RETURN_OK) {
return result; return result;
} }
return RETURN_OK; return RETURN_OK;
} }
MessageQueueId_t ControllerBase::getCommandQueue() const { MessageQueueId_t ControllerBase::getCommandQueue() const {
return commandQueue->getId(); return commandQueue->getId();
} }
void ControllerBase::handleQueue() { void ControllerBase::handleQueue() {
CommandMessage command; CommandMessage command;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (result = commandQueue->receiveMessage(&command); for (result = commandQueue->receiveMessage(&command);
result == RETURN_OK; result == RETURN_OK;
result = commandQueue->receiveMessage(&command)) { result = commandQueue->receiveMessage(&command)) {
result = modeHelper.handleModeCommand(&command); result = modeHelper.handleModeCommand(&command);
if (result == RETURN_OK) { if (result == RETURN_OK) {
continue; continue;
} }
result = healthHelper.handleHealthCommand(&command); result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) { if (result == RETURN_OK) {
continue; continue;
} }
result = handleCommandMessage(&command); result = handleCommandMessage(&command);
if (result == RETURN_OK) { if (result == RETURN_OK) {
continue; continue;
} }
command.setToUnknownCommand(); command.setToUnknownCommand();
commandQueue->reply(&command); commandQueue->reply(&command);
} }
} }
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) { void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
changeHK(this->mode, this->submode, false); changeHK(this->mode, this->submode, false);
triggerEvent(CHANGING_MODE, mode, submode); triggerEvent(CHANGING_MODE, mode, submode);
this->mode = mode; this->mode = mode;
this->submode = submode; this->submode = submode;
modeHelper.modeChanged(mode, submode); modeHelper.modeChanged(mode, submode);
modeChanged(mode, submode); modeChanged(mode, submode);
announceMode(false); announceMode(false);
changeHK(this->mode, this->submode, true); changeHK(this->mode, this->submode, true);
} }
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) { void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
*mode = this->mode; *mode = this->mode;
*submode = this->submode; *submode = this->submode;
} }
void ControllerBase::setToExternalControl() { void ControllerBase::setToExternalControl() {
healthHelper.setHealth(EXTERNAL_CONTROL); healthHelper.setHealth(EXTERNAL_CONTROL);
} }
void ControllerBase::announceMode(bool recursive) { void ControllerBase::announceMode(bool recursive) {
triggerEvent(MODE_INFO, mode, submode); triggerEvent(MODE_INFO, mode, submode);
} }
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) { ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
handleQueue(); handleQueue();
performControlOperation(); performControlOperation();
return RETURN_OK; return RETURN_OK;
} }
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) { void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
return; return;
} }
ReturnValue_t ControllerBase::setHealth(HealthState health) { ReturnValue_t ControllerBase::setHealth(HealthState health) {
switch (health) { switch (health) {
case HEALTHY: case HEALTHY:
case EXTERNAL_CONTROL: case EXTERNAL_CONTROL:
healthHelper.setHealth(health); healthHelper.setHealth(health);
return RETURN_OK; return RETURN_OK;
default: default:
return INVALID_HEALTH_STATE; return INVALID_HEALTH_STATE;
} }
} }
HasHealthIF::HealthState ControllerBase::getHealth() { HasHealthIF::HealthState ControllerBase::getHealth() {
return healthHelper.getHealth(); return healthHelper.getHealth();
} }
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){ void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
executingTask = task_; executingTask = task_;
} }
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {

View File

@ -17,39 +17,39 @@
* a mode and a health state. This avoids boilerplate code. * a mode and a health state. This avoids boilerplate code.
*/ */
class ControllerBase: public HasModesIF, class ControllerBase: public HasModesIF,
public HasHealthIF, public HasHealthIF,
public ExecutableObjectIF, public ExecutableObjectIF,
public SystemObject, public SystemObject,
public HasReturnvaluesIF { public HasReturnvaluesIF {
public: public:
static const Mode_t MODE_NORMAL = 2; static const Mode_t MODE_NORMAL = 2;
ControllerBase(object_id_t setObjectId, object_id_t parentId, ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth = 3); size_t commandQueueDepth = 3);
virtual ~ControllerBase(); virtual ~ControllerBase();
/** SystemObject override */ /** SystemObject override */
virtual ReturnValue_t initialize() override; virtual ReturnValue_t initialize() override;
virtual MessageQueueId_t getCommandQueue() const override; virtual MessageQueueId_t getCommandQueue() const override;
/** HasHealthIF overrides */ /** HasHealthIF overrides */
virtual ReturnValue_t setHealth(HealthState health) override; virtual ReturnValue_t setHealth(HealthState health) override;
virtual HasHealthIF::HealthState getHealth() override; virtual HasHealthIF::HealthState getHealth() override;
/** ExecutableObjectIF overrides */ /** ExecutableObjectIF overrides */
virtual ReturnValue_t performOperation(uint8_t opCode) override; virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual void setTaskIF(PeriodicTaskIF* task) override; virtual void setTaskIF(PeriodicTaskIF* task) override;
virtual ReturnValue_t initializeAfterTaskCreation() override; virtual ReturnValue_t initializeAfterTaskCreation() override;
protected: protected:
/** /**
* Implemented by child class. Handle command messages which are not * Implemented by child class. Handle command messages which are not
* mode or health messages. * mode or health messages.
* @param message * @param message
* @return * @return
*/ */
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0; virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
/** /**
@ -60,35 +60,35 @@ protected:
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) = 0; uint32_t *msToReachTheMode) = 0;
const object_id_t parentId; const object_id_t parentId;
Mode_t mode; Mode_t mode;
Submode_t submode; Submode_t submode;
MessageQueueIF* commandQueue = nullptr; MessageQueueIF* commandQueue = nullptr;
ModeHelper modeHelper; ModeHelper modeHelper;
HealthHelper healthHelper; HealthHelper healthHelper;
/** /**
* Pointer to the task which executes this component, * Pointer to the task which executes this component,
* is invalid before setTaskIF was called. * is invalid before setTaskIF was called.
*/ */
PeriodicTaskIF* executingTask = nullptr; PeriodicTaskIF* executingTask = nullptr;
/** Handle mode and health messages */ /** Handle mode and health messages */
virtual void handleQueue(); virtual void handleQueue();
/** Mode helpers */ /** Mode helpers */
virtual void modeChanged(Mode_t mode, Submode_t submode); virtual void modeChanged(Mode_t mode, Submode_t submode);
virtual void startTransition(Mode_t mode, Submode_t submode); virtual void startTransition(Mode_t mode, Submode_t submode);
virtual void getMode(Mode_t *mode, Submode_t *submode); virtual void getMode(Mode_t *mode, Submode_t *submode);
virtual void setToExternalControl(); virtual void setToExternalControl();
virtual void announceMode(bool recursive); virtual void announceMode(bool recursive);
/** HK helpers */ /** HK helpers */
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable); virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
}; };
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */ #endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */