diff --git a/protocol/esta/dmx/patch.cpp b/protocol/esta/dmx/patch.cpp index b23126e..17e3275 100644 --- a/protocol/esta/dmx/patch.cpp +++ b/protocol/esta/dmx/patch.cpp @@ -22,6 +22,7 @@ SOFTWARE. */ +#include "dmx.h" #include "patch.h" namespace DMX { @@ -34,4 +35,118 @@ Patch::Patch() } + +/** + * @brief Add a Device to the patch. + * @param dev + */ +void Patch::addDevice(const std::shared_ptr dev) +{ + devices_.emplace(dev); +} + + +/** + * @brief Remove a Device from the patch. + * @param dev + */ +void Patch::remDevice(const std::shared_ptr dev) +{ + for (auto it = devices_.begin(); it != devices_.end();) + { + if (it->expired()) // purge stale devices + it = devices_.erase(it); + else if (it->lock() == dev) + it = devices_.erase(it); + else + ++it; + } +} + + +/** + * @brief Check if a Device is in the patch. + * @param dev + * @return + */ +bool Patch::hasDevice(const std::shared_ptr dev) +{ + for (auto it = devices_.begin(); it != devices_.end();) + { + if (it->expired()) // purge stale devices + it = devices_.erase(it); + else if (it->lock() == dev) + return true; + else + ++it; + } + return false; +} + + +/** + * @brief Get the list of patched Devices. + * @return + */ +const std::set> * Patch::devices() const +{ + return &devices_; +} + + +/** + * @brief Check the patch for device footprint conflicts + * @return + */ +std::set> Patch::conflicts() +{ + std::set> bad; + + for (auto it = devices_.begin(); it != devices_.end();) + { + if (it->expired()) { // purge stale devices + it = devices_.erase(it); + continue; + } + + auto dev = it->lock(); + + // footprint cannot overlow universe + if (dev->address() + dev->footprint() >= E111_LAST_SLOT) { + bad.emplace(dev); + ++it; + continue; + } + + // start address cannot overlap the prior device + if (it != devices_.begin()) { + auto prev = std::prev(it)->lock(); + if (dev->address() < prev->address() + prev->footprint()) { + bad.emplace(dev); + ++it; + continue; + } + } + + // footprint cannot overlap the next device + auto nextItr = std::next(it); + while(true) { + if (nextItr == devices_.end()) // device is the last member of the patch + break; + if (nextItr->expired()) { // next device is stale, purge it + nextItr = devices_.erase(nextItr); + continue; + } + auto next = nextItr->lock(); + if (dev->address() + dev->footprint() >= next->address()) + bad.emplace(dev); + break; + } + + ++it; + } + + return bad; +} + } // namespace DMX diff --git a/protocol/esta/dmx/patch.h b/protocol/esta/dmx/patch.h index df266e8..7f870a1 100644 --- a/protocol/esta/dmx/patch.h +++ b/protocol/esta/dmx/patch.h @@ -23,6 +23,11 @@ */ #pragma once +#include "device.h" + +#include +#include + namespace DMX { /** @@ -32,6 +37,16 @@ class Patch { public: explicit Patch(); + + void addDevice(const std::shared_ptr); + void remDevice(const std::shared_ptr); + bool hasDevice(const std::shared_ptr); + + const std::set> *devices() const; + std::set> conflicts(); + +private: + std::set> devices_; }; } // namespace DMX