Program Listing for File packetContainer.hpp
↰ Return to documentation for file (include/libcaercpp/events/packetContainer.hpp
)
#ifndef LIBCAER_EVENTS_PACKETCONTAINER_HPP_
#define LIBCAER_EVENTS_PACKETCONTAINER_HPP_
#include "../../libcaer/events/packetContainer.h"
#include "common.hpp"
#include "utils.hpp"
#include <memory>
#include <utility>
#include <vector>
namespace libcaer {
namespace events {
template<class InteralIterator, class SharedPtrType>
class EventPacketContainerCopyIterator {
private:
// Original vector iterator or const_iterator.
InteralIterator eventPacketsIterator;
// currElement acts as a kind of cache: not only does it allow us
// to add deep-constness (when needed), but it also stores a copy of
// the shared_ptr we're iterating over, effectively increasing its
// reference count by one while it is in use by the iterator and its
// user, thus ensuring the object can never disappear from under us.
mutable SharedPtrType currElement;
public:
// Iterator traits.
using iterator_category = typename InteralIterator::iterator_category;
using value_type = SharedPtrType;
using pointer = const SharedPtrType *;
using reference = const SharedPtrType &;
using difference_type = typename InteralIterator::difference_type;
using size_type = typename InteralIterator::difference_type;
// Constructors.
EventPacketContainerCopyIterator() {
// Empty constructor fine here, results in calls to default
// constructors for members:
// - eventPacketsIterator() => empty/nothing iterator
// - currElement() => empty/nullptr shared_ptr
}
EventPacketContainerCopyIterator(InteralIterator _eventPacketsIterator) :
eventPacketsIterator(_eventPacketsIterator) {
// Don't initialize currElement, it is initialized/updated
// right before every use.
}
// Data access operators.
reference operator*() const noexcept {
currElement = *eventPacketsIterator;
return (currElement);
}
pointer operator->() const noexcept {
currElement = *eventPacketsIterator;
return (&currElement);
}
reference operator[](size_type idx) const noexcept {
currElement = eventPacketsIterator[idx];
return (currElement);
}
// Comparison operators.
bool operator==(const EventPacketContainerCopyIterator &rhs) const noexcept {
return (eventPacketsIterator == rhs.eventPacketsIterator);
}
bool operator!=(const EventPacketContainerCopyIterator &rhs) const noexcept {
return (eventPacketsIterator != rhs.eventPacketsIterator);
}
bool operator<(const EventPacketContainerCopyIterator &rhs) const noexcept {
return (eventPacketsIterator < rhs.eventPacketsIterator);
}
bool operator>(const EventPacketContainerCopyIterator &rhs) const noexcept {
return (eventPacketsIterator > rhs.eventPacketsIterator);
}
bool operator<=(const EventPacketContainerCopyIterator &rhs) const noexcept {
return (eventPacketsIterator <= rhs.eventPacketsIterator);
}
bool operator>=(const EventPacketContainerCopyIterator &rhs) const noexcept {
return (eventPacketsIterator >= rhs.eventPacketsIterator);
}
// Prefix increment.
EventPacketContainerCopyIterator &operator++() noexcept {
++eventPacketsIterator;
return (*this);
}
// Postfix increment.
EventPacketContainerCopyIterator operator++(int) noexcept {
InteralIterator currIterator = eventPacketsIterator;
++eventPacketsIterator;
return (EventPacketContainerCopyIterator(currIterator));
}
// Prefix decrement.
EventPacketContainerCopyIterator &operator--() noexcept {
--eventPacketsIterator;
return (*this);
}
// Postfix decrement.
EventPacketContainerCopyIterator operator--(int) noexcept {
InteralIterator currIterator = eventPacketsIterator;
--eventPacketsIterator;
return (EventPacketContainerCopyIterator(currIterator));
}
// Iter += N.
EventPacketContainerCopyIterator &operator+=(size_type add) noexcept {
eventPacketsIterator += add;
return (*this);
}
// Iter + N.
EventPacketContainerCopyIterator operator+(size_type add) const noexcept {
return (EventPacketContainerCopyIterator(eventPacketsIterator + add));
}
// N + Iter. Must be friend as Iter is right-hand-side.
friend EventPacketContainerCopyIterator operator+(
size_type lhs, const EventPacketContainerCopyIterator &rhs) noexcept {
return (EventPacketContainerCopyIterator(rhs.eventPacketsIterator + lhs));
}
// Iter -= N.
EventPacketContainerCopyIterator &operator-=(size_type sub) noexcept {
eventPacketsIterator -= sub;
return (*this);
}
// Iter - N. (N - Iter doesn't make sense!)
EventPacketContainerCopyIterator operator-(size_type sub) const noexcept {
return (EventPacketContainerCopyIterator(eventPacketsIterator - sub));
}
// Iter - Iter. (Iter + Iter doesn't make sense!)
difference_type operator-(const EventPacketContainerCopyIterator &rhs) const noexcept {
// Distance in pointed-to-elements.
return (eventPacketsIterator - rhs.eventPacketsIterator);
}
// Swap two iterators.
void swap(EventPacketContainerCopyIterator &rhs) noexcept {
std::swap(eventPacketsIterator, rhs.eventPacketsIterator);
std::swap(currElement, rhs.currElement);
}
};
class EventPacketContainer {
private:
int64_t lowestEventTimestamp;
int64_t highestEventTimestamp;
int32_t eventsNumber;
int32_t eventsValidNumber;
std::vector<std::shared_ptr<EventPacket>> eventPackets;
public:
// Container traits (not really STL compatible).
using value_type = std::shared_ptr<EventPacket>;
using const_value_type = std::shared_ptr<const EventPacket>;
using size_type = int32_t;
using difference_type = ptrdiff_t;
EventPacketContainer() :
lowestEventTimestamp(-1), highestEventTimestamp(-1), eventsNumber(0), eventsValidNumber(0) {
}
EventPacketContainer(size_type eventPacketsNumber) :
lowestEventTimestamp(-1), highestEventTimestamp(-1), eventsNumber(0), eventsValidNumber(0) {
if (eventPacketsNumber <= 0) {
throw std::invalid_argument("Negative or zero capacity not allowed on explicit construction.");
}
// Initialize and fill vector after having checked size value.
eventPackets.reserve(static_cast<size_t>(eventPacketsNumber));
for (size_type i = 0; i < eventPacketsNumber; i++) {
eventPackets.emplace_back(); // Call empty constructor.
}
}
EventPacketContainer(caerEventPacketContainer packetContainer, bool takeMemoryOwnership = true) {
if (packetContainer == nullptr) {
throw std::runtime_error("Failed to initialize event packet container: null pointer.");
}
lowestEventTimestamp = caerEventPacketContainerGetLowestEventTimestamp(packetContainer);
highestEventTimestamp = caerEventPacketContainerGetHighestEventTimestamp(packetContainer);
eventsNumber = caerEventPacketContainerGetEventsNumber(packetContainer);
eventsValidNumber = caerEventPacketContainerGetEventsValidNumber(packetContainer);
// Initialize and fill vector.
int32_t eventPacketsNumber = caerEventPacketContainerGetEventPacketsNumber(packetContainer);
eventPackets.reserve(static_cast<size_t>(eventPacketsNumber));
for (size_type i = 0; i < eventPacketsNumber; i++) {
caerEventPacketHeader packet = caerEventPacketContainerGetEventPacket(packetContainer, i);
if (packet != nullptr) {
eventPackets.push_back(libcaer::events::utils::makeSharedFromCStruct(packet, takeMemoryOwnership));
}
else {
eventPackets.emplace_back(); // Call empty constructor.
}
}
}
// The default destructor is fine here, as it will call the vector's
// destructor, which will call all of its content's destructors; those
// are shared_ptr, so if their count reaches zero it will then call the
// EventPacketHeader destructor, and everything is fine.
// Same for copy/move assignment/constructors, the defaults are fine,
// as vector and shared_ptr take care of all the book-keeping.
// EventPackets vector accessors.
size_type capacity() const noexcept {
return (static_cast<size_type>(eventPackets.capacity()));
}
size_type size() const noexcept {
return (static_cast<size_type>(eventPackets.size()));
}
bool empty() const noexcept {
return (eventPackets.empty());
}
void clear() noexcept {
eventPackets.clear();
}
value_type getEventPacket(size_type index) {
// Support negative indexes to go from the end of the event packet container.
if (index < 0) {
index = size() + index;
}
if (index < 0 || index >= size()) {
throw std::out_of_range("Index out of range.");
}
return (eventPackets[static_cast<size_t>(index)]);
}
value_type operator[](size_type index) {
return (getEventPacket(index));
}
const_value_type getEventPacket(size_type index) const {
// Support negative indexes to go from the end of the event packet container.
if (index < 0) {
index = size() + index;
}
if (index < 0 || index >= size()) {
throw std::out_of_range("Index out of range.");
}
return (eventPackets[static_cast<size_t>(index)]);
}
const_value_type operator[](size_type index) const {
return (getEventPacket(index));
}
void setEventPacket(size_type index, value_type packetHeader) {
// Support negative indexes to go from the end of the event packet container.
if (index < 0) {
index = size() + index;
}
if (index < 0 || index >= size()) {
throw std::out_of_range("Index out of range.");
}
eventPackets[static_cast<size_t>(index)] = packetHeader;
updateStatistics();
}
void addEventPacket(value_type packetHeader) {
eventPackets.push_back(packetHeader);
updateStatistics();
}
int64_t getLowestEventTimestamp() const noexcept {
return (lowestEventTimestamp);
}
int64_t getHighestEventTimestamp() const noexcept {
return (highestEventTimestamp);
}
int32_t getEventsNumber() const noexcept {
return (eventsNumber);
}
int32_t getEventsValidNumber() const noexcept {
return (eventsValidNumber);
}
void updateStatistics() noexcept {
int64_t lowestTimestamp = -1;
int64_t highestTimestamp = -1;
int32_t events = 0;
int32_t eventsValid = 0;
for (auto &packet : *this) {
if (packet == nullptr) {
continue;
}
// If packet has no events, skip it, it contributes nothing to statistics.
if (packet->getEventNumber() == 0) {
continue;
}
// Get timestamps to update lowest/highest tracking.
const auto firstEvent = packet->genericGetEvent(0);
int64_t currLowestEventTimestamp = firstEvent.getTimestamp64();
const auto lastEvent = packet->genericGetEvent(-1);
int64_t currHighestEventTimestamp = lastEvent.getTimestamp64();
// Update tracked timestamps (or initialize if needed).
if ((lowestTimestamp == -1) || (lowestTimestamp > currLowestEventTimestamp)) {
lowestTimestamp = currLowestEventTimestamp;
}
if ((highestTimestamp == -1) || (highestTimestamp < currHighestEventTimestamp)) {
highestTimestamp = currHighestEventTimestamp;
}
events += packet->getEventNumber();
eventsValid += packet->getEventValid();
}
lowestEventTimestamp = lowestTimestamp;
highestEventTimestamp = highestTimestamp;
eventsNumber = events;
eventsValidNumber = eventsValid;
}
value_type findEventPacketByType(int16_t typeID) {
for (auto &packet : *this) {
if (packet == nullptr) {
continue;
}
if (packet->getEventType() == typeID) {
return (packet);
}
}
return (nullptr);
}
std::unique_ptr<std::vector<value_type>> findEventPacketsByType(int16_t typeID) {
auto results = std::unique_ptr<std::vector<value_type>>(new std::vector<value_type>());
for (auto &packet : *this) {
if (packet == nullptr) {
continue;
}
if (packet->getEventType() == typeID) {
results->push_back(packet);
}
}
return (results);
}
const_value_type findEventPacketByType(int16_t typeID) const {
for (auto &packet : *this) {
if (packet == nullptr) {
continue;
}
if (packet->getEventType() == typeID) {
return (packet);
}
}
return (nullptr);
}
std::unique_ptr<std::vector<const_value_type>> findEventPacketsByType(int16_t typeID) const {
auto results = std::unique_ptr<std::vector<const_value_type>>(new std::vector<const_value_type>());
for (auto &packet : *this) {
if (packet == nullptr) {
continue;
}
if (packet->getEventType() == typeID) {
results->push_back(packet);
}
}
return (results);
}
value_type findEventPacketBySource(int16_t sourceID) {
for (auto &packet : *this) {
if (packet == nullptr) {
continue;
}
if (packet->getEventSource() == sourceID) {
return (packet);
}
}
return (nullptr);
}
std::unique_ptr<std::vector<value_type>> findEventPacketsBySource(int16_t sourceID) {
auto results = std::unique_ptr<std::vector<value_type>>(new std::vector<value_type>());
for (auto &packet : *this) {
if (packet == nullptr) {
continue;
}
if (packet->getEventSource() == sourceID) {
results->push_back(packet);
}
}
return (results);
}
const_value_type findEventPacketBySource(int16_t sourceID) const {
for (auto &packet : *this) {
if (packet == nullptr) {
continue;
}
if (packet->getEventSource() == sourceID) {
return (packet);
}
}
return (nullptr);
}
std::unique_ptr<std::vector<const_value_type>> findEventPacketsBySource(int16_t sourceID) const {
auto results = std::unique_ptr<std::vector<const_value_type>>(new std::vector<const_value_type>());
for (auto &packet : *this) {
if (packet == nullptr) {
continue;
}
if (packet->getEventSource() == sourceID) {
results->push_back(packet);
}
}
return (results);
}
std::unique_ptr<EventPacketContainer> copyAllEvents() const {
std::unique_ptr<EventPacketContainer> newContainer
= std::unique_ptr<EventPacketContainer>(new EventPacketContainer());
for (auto &packet : *this) {
if (packet == nullptr) {
newContainer->addEventPacket(nullptr);
}
else {
newContainer->addEventPacket(
std::shared_ptr<EventPacket>(packet->copy(EventPacket::copyTypes::EVENTS_ONLY)));
}
}
return (newContainer);
}
std::unique_ptr<EventPacketContainer> copyValidEvents() const {
std::unique_ptr<EventPacketContainer> newContainer
= std::unique_ptr<EventPacketContainer>(new EventPacketContainer());
for (auto &packet : *this) {
if (packet == nullptr) {
newContainer->addEventPacket(nullptr);
}
else {
newContainer->addEventPacket(
std::shared_ptr<EventPacket>(packet->copy(EventPacket::copyTypes::VALID_EVENTS_ONLY)));
}
}
return (newContainer);
}
// Iterator support (the returned shared_ptr are always read-only copies, so actual modifications to
// what is pointed to can only happen through setEventPacket() and addEventPacket()).
using iterator = EventPacketContainerCopyIterator<std::vector<std::shared_ptr<EventPacket>>::iterator,
std::shared_ptr<EventPacket>>;
using const_iterator = EventPacketContainerCopyIterator<std::vector<std::shared_ptr<EventPacket>>::const_iterator,
std::shared_ptr<const EventPacket>>;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
iterator begin() noexcept {
return (iterator(eventPackets.begin()));
}
iterator end() noexcept {
return (iterator(eventPackets.end()));
}
const_iterator begin() const noexcept {
return (cbegin());
}
const_iterator end() const noexcept {
return (cend());
}
const_iterator cbegin() const noexcept {
return (const_iterator(eventPackets.cbegin()));
}
const_iterator cend() const noexcept {
return (const_iterator(eventPackets.cend()));
}
reverse_iterator rbegin() noexcept {
return (reverse_iterator(end()));
}
reverse_iterator rend() noexcept {
return (reverse_iterator(begin()));
}
const_reverse_iterator rbegin() const noexcept {
return (crbegin());
}
const_reverse_iterator rend() const noexcept {
return (crend());
}
const_reverse_iterator crbegin() const noexcept {
return (const_reverse_iterator(cend()));
}
const_reverse_iterator crend() const noexcept {
return (const_reverse_iterator(cbegin()));
}
};
} // namespace events
} // namespace libcaer
#endif /* LIBCAER_EVENTS_PACKETCONTAINER_HPP_ */