Program Listing for File packetContainer.h
↰ Return to documentation for file (include/libcaer/events/packetContainer.h
)
#ifndef LIBCAER_EVENTS_PACKETCONTAINER_H_
#define LIBCAER_EVENTS_PACKETCONTAINER_H_
#include "common.h"
#ifdef __cplusplus
extern "C" {
#endif
PACKED_STRUCT(struct caer_event_packet_container {
int64_t lowestEventTimestamp;
int64_t highestEventTimestamp;
int32_t eventsNumber;
int32_t eventsValidNumber;
int32_t eventPacketsNumber;
caerEventPacketHeader eventPackets[];
});
typedef struct caer_event_packet_container *caerEventPacketContainer;
typedef const struct caer_event_packet_container *caerEventPacketContainerConst;
static inline caerEventPacketContainer caerEventPacketContainerAllocate(int32_t eventPacketsNumber) {
if (eventPacketsNumber <= 0) {
return (NULL);
}
size_t eventPacketContainerSize
= sizeof(struct caer_event_packet_container) + ((size_t) eventPacketsNumber * sizeof(caerEventPacketHeader));
caerEventPacketContainer packetContainer = (caerEventPacketContainer) calloc(1, eventPacketContainerSize);
if (packetContainer == NULL) {
caerLogEHO(CAER_LOG_CRITICAL, "EventPacket Container",
"Failed to allocate %zu bytes of memory for Event Packet Container, containing %" PRIi32
" packets. Error: %d.",
eventPacketContainerSize, eventPacketsNumber, errno);
return (NULL);
}
// Fill in header fields. Don't care about endianness here, purely internal
// memory construct, never meant for inter-system exchange.
packetContainer->eventPacketsNumber = eventPacketsNumber;
packetContainer->lowestEventTimestamp = -1;
packetContainer->highestEventTimestamp = -1;
return (packetContainer);
}
// Forward declaration for use in set operations.
static inline void caerEventPacketContainerUpdateStatistics(caerEventPacketContainer container);
static inline int32_t caerEventPacketContainerGetEventPacketsNumber(caerEventPacketContainerConst container) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return (0);
}
return (container->eventPacketsNumber);
}
static inline void caerEventPacketContainerSetEventPacketsNumber(
caerEventPacketContainer container, int32_t eventPacketsNumber) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return;
}
if (eventPacketsNumber < 0) {
// Negative numbers (bit 31 set) are not allowed!
caerLogEHO(CAER_LOG_CRITICAL, "EventPacket Container",
"Called caerEventPacketContainerSetEventPacketsNumber() with negative value!");
return;
}
container->eventPacketsNumber = eventPacketsNumber;
// Always update all the statics on set operation.
caerEventPacketContainerUpdateStatistics(container);
}
static inline caerEventPacketHeader caerEventPacketContainerGetEventPacket(
caerEventPacketContainerConst container, int32_t n) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return (NULL);
}
// Check that we're not out of bounds.
if (n < 0 || n >= caerEventPacketContainerGetEventPacketsNumber(container)) {
caerLogEHO(CAER_LOG_CRITICAL, "EventPacket Container",
"Called caerEventPacketContainerGetEventPacket() with invalid event offset %" PRIi32
", while maximum allowed value is %" PRIi32 ". Negative values are not allowed!",
n, caerEventPacketContainerGetEventPacketsNumber(container) - 1);
return (NULL);
}
// Return a pointer to the specified event packet.
return (container->eventPackets[n]);
}
static inline caerEventPacketHeaderConst caerEventPacketContainerGetEventPacketConst(
caerEventPacketContainerConst container, int32_t n) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return (NULL);
}
// Check that we're not out of bounds.
if (n < 0 || n >= caerEventPacketContainerGetEventPacketsNumber(container)) {
caerLogEHO(CAER_LOG_CRITICAL, "EventPacket Container",
"Called caerEventPacketContainerGetEventPacketConst() with invalid event offset %" PRIi32
", while maximum allowed value is %" PRIi32 ". Negative values are not allowed!",
n, caerEventPacketContainerGetEventPacketsNumber(container) - 1);
return (NULL);
}
// Return a pointer to the specified event packet.
return (container->eventPackets[n]);
}
static inline void caerEventPacketContainerSetEventPacket(
caerEventPacketContainer container, int32_t n, caerEventPacketHeader packetHeader) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return;
}
// Check that we're not out of bounds.
if (n < 0 || n >= caerEventPacketContainerGetEventPacketsNumber(container)) {
caerLogEHO(CAER_LOG_CRITICAL, "EventPacket Container",
"Called caerEventPacketContainerSetEventPacket() with invalid event offset %" PRIi32
", while maximum allowed value is %" PRIi32 ". Negative values are not allowed!",
n, caerEventPacketContainerGetEventPacketsNumber(container) - 1);
return;
}
// Store the given event packet.
container->eventPackets[n] = packetHeader;
// Always update all the statics on set operation.
caerEventPacketContainerUpdateStatistics(container);
}
static inline void caerEventPacketContainerFree(caerEventPacketContainer container) {
if (container == NULL) {
return;
}
// Free packet container and ensure all subordinate memory is also freed.
int32_t eventPacketsNum = caerEventPacketContainerGetEventPacketsNumber(container);
for (int32_t i = 0; i < eventPacketsNum; i++) {
caerEventPacketHeader packetHeader = caerEventPacketContainerGetEventPacket(container, i);
if (packetHeader != NULL) {
free(packetHeader);
}
}
free(container);
}
static inline int64_t caerEventPacketContainerGetLowestEventTimestamp(caerEventPacketContainerConst container) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return (-1);
}
return (container->lowestEventTimestamp);
}
static inline int64_t caerEventPacketContainerGetHighestEventTimestamp(caerEventPacketContainerConst container) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return (-1);
}
return (container->highestEventTimestamp);
}
static inline int32_t caerEventPacketContainerGetEventsNumber(caerEventPacketContainerConst container) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return (0);
}
return (container->eventsNumber);
}
static inline int32_t caerEventPacketContainerGetEventsValidNumber(caerEventPacketContainerConst container) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return (0);
}
return (container->eventsValidNumber);
}
#define CAER_EVENT_PACKET_CONTAINER_ITERATOR_START(PACKET_CONTAINER) \
if ((PACKET_CONTAINER) != NULL) { \
for (int32_t caerEventPacketContainerIteratorCounter = 0; \
caerEventPacketContainerIteratorCounter \
< caerEventPacketContainerGetEventPacketsNumber(PACKET_CONTAINER); \
caerEventPacketContainerIteratorCounter++) { \
caerEventPacketHeader caerEventPacketContainerIteratorElement \
= caerEventPacketContainerGetEventPacket(PACKET_CONTAINER, caerEventPacketContainerIteratorCounter); \
if (caerEventPacketContainerIteratorElement == NULL) { \
continue; \
}
#define CAER_EVENT_PACKET_CONTAINER_CONST_ITERATOR_START(PACKET_CONTAINER) \
if ((PACKET_CONTAINER) != NULL) { \
for (int32_t caerEventPacketContainerIteratorCounter = 0; \
caerEventPacketContainerIteratorCounter \
< caerEventPacketContainerGetEventPacketsNumber(PACKET_CONTAINER); \
caerEventPacketContainerIteratorCounter++) { \
caerEventPacketHeaderConst caerEventPacketContainerIteratorElement \
= caerEventPacketContainerGetEventPacketConst( \
PACKET_CONTAINER, caerEventPacketContainerIteratorCounter); \
if (caerEventPacketContainerIteratorElement == NULL) { \
continue; \
}
#define CAER_EVENT_PACKET_CONTAINER_ITERATOR_END \
} \
}
static inline void caerEventPacketContainerUpdateStatistics(caerEventPacketContainer container) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return;
}
int64_t lowestTimestamp = -1;
int64_t highestTimestamp = -1;
int32_t eventsNumber = 0;
int32_t eventsValid = 0;
CAER_EVENT_PACKET_CONTAINER_CONST_ITERATOR_START(container)
// If packet has no events, skip it, it contributes nothing to statistics.
if (caerEventPacketHeaderGetEventNumber(caerEventPacketContainerIteratorElement) == 0) {
continue;
}
// Get timestamps to update lowest/highest tracking.
const void *firstEvent = caerGenericEventGetEvent(caerEventPacketContainerIteratorElement, 0);
int64_t currLowestEventTimestamp
= caerGenericEventGetTimestamp64(firstEvent, caerEventPacketContainerIteratorElement);
const void *lastEvent = caerGenericEventGetEvent(caerEventPacketContainerIteratorElement,
caerEventPacketHeaderGetEventNumber(caerEventPacketContainerIteratorElement) - 1);
int64_t currHighestEventTimestamp
= caerGenericEventGetTimestamp64(lastEvent, caerEventPacketContainerIteratorElement);
// Update tracked timestamps (or initialize if needed).
if ((lowestTimestamp == -1) || (lowestTimestamp > currLowestEventTimestamp)) {
lowestTimestamp = currLowestEventTimestamp;
}
if ((highestTimestamp == -1) || (highestTimestamp < currHighestEventTimestamp)) {
highestTimestamp = currHighestEventTimestamp;
}
eventsNumber += caerEventPacketHeaderGetEventNumber(caerEventPacketContainerIteratorElement);
eventsValid += caerEventPacketHeaderGetEventValid(caerEventPacketContainerIteratorElement);
CAER_EVENT_PACKET_CONTAINER_ITERATOR_END
container->lowestEventTimestamp = lowestTimestamp;
container->highestEventTimestamp = highestTimestamp;
container->eventsNumber = eventsNumber;
container->eventsValidNumber = eventsValid;
}
static inline caerEventPacketHeader caerEventPacketContainerFindEventPacketByType(
caerEventPacketContainerConst container, int16_t typeID) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return (NULL);
}
CAER_EVENT_PACKET_CONTAINER_ITERATOR_START(container)
if (caerEventPacketHeaderGetEventType(caerEventPacketContainerIteratorElement) == typeID) {
// Found it, return it.
return (caerEventPacketContainerIteratorElement);
}
CAER_EVENT_PACKET_CONTAINER_ITERATOR_END
// Found nothing, return nothing.
return (NULL);
}
static inline caerEventPacketHeaderConst caerEventPacketContainerFindEventPacketByTypeConst(
caerEventPacketContainerConst container, int16_t typeID) {
// Non-existing (empty) containers have no valid packets in them!
if (container == NULL) {
return (NULL);
}
CAER_EVENT_PACKET_CONTAINER_CONST_ITERATOR_START(container)
if (caerEventPacketHeaderGetEventType(caerEventPacketContainerIteratorElement) == typeID) {
// Found it, return it.
return (caerEventPacketContainerIteratorElement);
}
CAER_EVENT_PACKET_CONTAINER_ITERATOR_END
// Found nothing, return nothing.
return (NULL);
}
static inline caerEventPacketContainer caerEventPacketContainerCopyAllEvents(caerEventPacketContainerConst container) {
if (container == NULL) {
return (NULL);
}
caerEventPacketContainer newContainer
= caerEventPacketContainerAllocate(caerEventPacketContainerGetEventPacketsNumber(container));
if (newContainer == NULL) {
return (NULL);
}
CAER_EVENT_PACKET_CONTAINER_CONST_ITERATOR_START(container)
caerEventPacketContainerSetEventPacket(newContainer, caerEventPacketContainerIteratorCounter,
caerEventPacketCopyOnlyEvents(caerEventPacketContainerIteratorElement));
CAER_EVENT_PACKET_CONTAINER_ITERATOR_END
return (newContainer);
}
static inline caerEventPacketContainer caerEventPacketContainerCopyValidEvents(
caerEventPacketContainerConst container) {
if (container == NULL) {
return (NULL);
}
caerEventPacketContainer newContainer
= caerEventPacketContainerAllocate(caerEventPacketContainerGetEventPacketsNumber(container));
if (newContainer == NULL) {
return (NULL);
}
CAER_EVENT_PACKET_CONTAINER_CONST_ITERATOR_START(container)
caerEventPacketContainerSetEventPacket(newContainer, caerEventPacketContainerIteratorCounter,
caerEventPacketCopyOnlyValidEvents(caerEventPacketContainerIteratorElement));
CAER_EVENT_PACKET_CONTAINER_ITERATOR_END
return (newContainer);
}
#ifdef __cplusplus
}
#endif
#endif /* LIBCAER_EVENTS_PACKETCONTAINER_H_ */