.. _program_listing_file_include_libcaercpp_events_packetContainer.hpp: Program Listing for File packetContainer.hpp ============================================ |exhale_lsh| :ref:`Return to documentation for file ` (``include/libcaercpp/events/packetContainer.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef LIBCAER_EVENTS_PACKETCONTAINER_HPP_ #define LIBCAER_EVENTS_PACKETCONTAINER_HPP_ #include "../../libcaer/events/packetContainer.h" #include "common.hpp" #include "utils.hpp" #include #include #include namespace libcaer { namespace events { template 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> eventPackets; public: // Container traits (not really STL compatible). using value_type = std::shared_ptr; using const_value_type = std::shared_ptr; 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(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(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(eventPackets.capacity())); } size_type size() const noexcept { return (static_cast(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(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(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(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> findEventPacketsByType(int16_t typeID) { auto results = std::unique_ptr>(new std::vector()); 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> findEventPacketsByType(int16_t typeID) const { auto results = std::unique_ptr>(new std::vector()); 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> findEventPacketsBySource(int16_t sourceID) { auto results = std::unique_ptr>(new std::vector()); 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> findEventPacketsBySource(int16_t sourceID) const { auto results = std::unique_ptr>(new std::vector()); for (auto &packet : *this) { if (packet == nullptr) { continue; } if (packet->getEventSource() == sourceID) { results->push_back(packet); } } return (results); } std::unique_ptr copyAllEvents() const { std::unique_ptr newContainer = std::unique_ptr(new EventPacketContainer()); for (auto &packet : *this) { if (packet == nullptr) { newContainer->addEventPacket(nullptr); } else { newContainer->addEventPacket( std::shared_ptr(packet->copy(EventPacket::copyTypes::EVENTS_ONLY))); } } return (newContainer); } std::unique_ptr copyValidEvents() const { std::unique_ptr newContainer = std::unique_ptr(new EventPacketContainer()); for (auto &packet : *this) { if (packet == nullptr) { newContainer->addEventPacket(nullptr); } else { newContainer->addEventPacket( std::shared_ptr(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>::iterator, std::shared_ptr>; using const_iterator = EventPacketContainerCopyIterator>::const_iterator, std::shared_ptr>; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_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_ */