diff --git a/CMakeLists.txt b/CMakeLists.txt index ab0c1dac6..a1a568e98 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ option (SLS_USE_TESTS "TESTS" OFF) option (SLS_USE_INTEGRATION_TESTS "Integration Tests" OFF) option(SLS_USE_SANITIZER "Sanitizers for debugging" OFF) option(SLS_USE_PYTHON "Python bindings" OFF) +option(SLS_BUILD_DOCS "Documentations" OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) @@ -182,10 +183,11 @@ configure_file( .clang-tidy ) -add_subdirectory(sample) - -add_subdirectory(docs) +#add_subdirectory(sample) +if(SLS_BUILD_DOCS) + add_subdirectory(docs) +endif(SLS_BUILD_DOCS) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 28e23b252..ccea0e58e 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -1089,14 +1089,14 @@ class Detector { /** [Eiger] If it is set, it resets chips completely (else partially) before an acquisition TODO: if it makes sense */ void setCounterBit(bool value, Positions pos = {}); - /** [Gotthard, CTB] subset modules not allowed */ - //Result> getROI(Positions pos = {}) const; + /** [Gotthard, CTB]*/ + Result> getROI(Positions pos = {}) const; /** * [Gotthard Options: Only a single chip or all chips, only 1 ROI allowed] * [CTB: multiple ROIs allowed] * subset modules not allowed */ - //void setROI(std::vector value, Positions pos = {}); + void setROI(std::vector value, Positions pos = {}); /** [CTB]*/ Result getADCEnableMask(Positions pos = {}) const; diff --git a/slsDetectorSoftware/include/Result.h b/slsDetectorSoftware/include/Result.h index 9d5f2ae7e..54d19b1a5 100644 --- a/slsDetectorSoftware/include/Result.h +++ b/slsDetectorSoftware/include/Result.h @@ -98,6 +98,11 @@ template > class Result { vec.push_back(std::forward(value)); } + template + auto emplace_back(Args &&... args) -> decltype(vec.emplace_back(args...)){ + vec.emplace_back(std::forward(args)...); + } + auto operator[](size_type pos) -> decltype(vec[pos]) { return vec[pos]; } const_reference operator[](size_type pos) const { return vec[pos]; } diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index eaa654142..a8bd836e6 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -85,7 +85,10 @@ defs::coordinates Detector::getNumberOfDetectors() const { } Result Detector::getNumberOfChannels(Positions pos) const { - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) {// TODO: also check condition that pos.size == pimpl->size()?? for other occurences as well + if (pos.empty() || + (pos.size() == 1 && + pos[0] == -1)) { // TODO: also check condition that pos.size == + // pimpl->size()?? for other occurences as well return {pimpl->getNumberOfChannels()}; } return pimpl->Parallel(&slsDetector::getNumberOfChannels, pos); @@ -636,88 +639,99 @@ void Detector::setDAC(int value, defs::dacIndex index, bool mV, Positions pos) { pimpl->Parallel(&slsDetector::setDAC, pos, value, index, mV); } - Result Detector::getTimingMode(Positions pos) const { - return pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, defs::GET_EXTERNAL_COMMUNICATION_MODE); - } +Result +Detector::getTimingMode(Positions pos) const { + return pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, + defs::GET_EXTERNAL_COMMUNICATION_MODE); +} - void Detector::setTimingMode(defs::externalCommunicationMode value, Positions pos) { - pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, value); - } +void Detector::setTimingMode(defs::externalCommunicationMode value, + Positions pos) { + pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, value); +} - Result Detector::getExternalSignalFlags(Positions pos) const { - return pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, defs::GET_EXTERNAL_SIGNAL_FLAG); - } +Result +Detector::getExternalSignalFlags(Positions pos) const { + return pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, + defs::GET_EXTERNAL_SIGNAL_FLAG); +} - void Detector::setExternalSignalFlags(defs::externalSignalFlag value, Positions pos) { - pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, value); - } +void Detector::setExternalSignalFlags(defs::externalSignalFlag value, + Positions pos) { + pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, value); +} - Result Detector::getParallelMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); - Result booleanRes; - for (unsigned int i = 0; i < res.size(); ++i) { - booleanRes[i] = (res[i] & defs::PARALLEL) ? true : false; +Result Detector::getParallelMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + defs::GET_READOUT_FLAGS); + Result booleanRes; + for (unsigned int i = 0; i < res.size(); ++i) { + booleanRes[i] = (res[i] & defs::PARALLEL) ? true : false; + } + return booleanRes; +} + +void Detector::setParallelMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + value ? defs::PARALLEL : defs::NONPARALLEL); +} + +Result Detector::getOverFlowMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + defs::GET_READOUT_FLAGS); + Result booleanRes; + for (unsigned int i = 0; i < res.size(); ++i) { + booleanRes[i] = (res[i] & defs::SHOW_OVERFLOW) ? true : false; + } + return booleanRes; +} + +void Detector::setOverFlowMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + value ? defs::SHOW_OVERFLOW : defs::NOOVERFLOW); +} + +Result Detector::getSignalType(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + defs::GET_READOUT_FLAGS); + for (auto &it : res) { + if (it & defs::ANALOG_AND_DIGITAL) { + it = 2; + } else if (it & defs::DIGITAL_ONLY) { + it = 1; + } else if (it == defs::NORMAL_READOUT) { + it = 0; + } else { + throw RuntimeError("Unknown Signal Type"); } - return booleanRes; } + return res; +} - void Detector::setParallelMode(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setReadOutFlags, pos, value ? defs::PARALLEL : defs::NONPARALLEL); - } - - Result Detector::getOverFlowMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); - Result booleanRes; - for (unsigned int i = 0; i < res.size(); ++i) { - booleanRes[i] = (res[i] & defs::SHOW_OVERFLOW) ? true : false; - } - return booleanRes; - } - - void Detector::setOverFlowMode(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setReadOutFlags, pos, value ? defs::SHOW_OVERFLOW : defs::NOOVERFLOW); - } - - Result Detector::getSignalType(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); - for (auto &it : res) { - if (it & defs::ANALOG_AND_DIGITAL) { - it = 2; - } else if (it & defs::DIGITAL_ONLY) { - it = 1; - } else if (it == defs::NORMAL_READOUT) { - it = 0; - } else { - throw RuntimeError("Unknown Signal Type"); - } - } - return res; - } - - void Detector::setSignalType(int value, Positions pos) { - defs::readOutFlags flag; - switch (value) { - case 0: - flag = defs::NORMAL_READOUT; - break; - case 1: - flag = defs::DIGITAL_ONLY; - break; - case 2: - flag = defs::ANALOG_AND_DIGITAL; - break; - default: - throw RuntimeError("Unknown Signal Type"); - } - pimpl->Parallel(&slsDetector::setReadOutFlags, pos, flag); +void Detector::setSignalType(int value, Positions pos) { + defs::readOutFlags flag; + switch (value) { + case 0: + flag = defs::NORMAL_READOUT; + break; + case 1: + flag = defs::DIGITAL_ONLY; + break; + case 2: + flag = defs::ANALOG_AND_DIGITAL; + break; + default: + throw RuntimeError("Unknown Signal Type"); } + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, flag); +} // Erik Result Detector::getInterruptSubframe(Positions pos) const { return pimpl->Parallel(&slsDetector::getInterruptSubframe, pos); } -void Detector::setInterruptSubframe(const bool enable, Positions pos){ +void Detector::setInterruptSubframe(const bool enable, Positions pos) { pimpl->Parallel(&slsDetector::setInterruptSubframe, pos, enable); } @@ -829,7 +843,8 @@ Result Detector::getNumberofUDPInterfaces(Positions pos) const { void Detector::setNumberofUDPInterfaces(int n, Positions pos) { bool previouslyClientStreaming = getDataStreamingToClient(); - bool previouslyReceiverStreaming = getDataStreamingFromReceiver(pos).squash(false); + bool previouslyReceiverStreaming = + getDataStreamingFromReceiver(pos).squash(false); pimpl->Parallel(&slsDetector::setNumberofUDPInterfaces, pos, n); // redo the zmq sockets if enabled if (previouslyClientStreaming) { @@ -856,7 +871,8 @@ Result Detector::getClientStreamingPort(Positions pos) const { void Detector::setClientDataStreamingInPort(int port, Positions pos) { if (pos.size() > 1 && pos.size() < pimpl->size()) { - throw RuntimeError("Cannot set client streaming port to a subset of modules"); + throw RuntimeError( + "Cannot set client streaming port to a subset of modules"); } pimpl->setClientDataStreamingInPort(port, pos.empty() ? -1 : pos[0]); } @@ -867,9 +883,10 @@ Result Detector::getReceiverStreamingPort(Positions pos) const { void Detector::setReceiverDataStreamingOutPort(int port, Positions pos) { if (pos.size() > 1 && pos.size() < pimpl->size()) { - throw RuntimeError("Cannot set receiver streaming port to a subset of modules"); + throw RuntimeError( + "Cannot set receiver streaming port to a subset of modules"); } - pimpl->setReceiverDataStreamingOutPort(port, pos.empty() ? -1 : pos[0]); + pimpl->setReceiverDataStreamingOutPort(port, pos.empty() ? -1 : pos[0]); } Result Detector::getClientStreamingIP(Positions pos) const { @@ -878,7 +895,7 @@ Result Detector::getClientStreamingIP(Positions pos) const { void Detector::setClientDataStreamingInIP(const std::string &ip, Positions pos) { - bool previouslyClientStreaming = getDataStreamingToClient(); + bool previouslyClientStreaming = getDataStreamingToClient(); // TODO! probably in one call ?? pimpl->Parallel(&slsDetector::setClientStreamingIP, pos, ip); if (previouslyClientStreaming) { @@ -893,7 +910,8 @@ Result Detector::getReceiverStreamingIP(Positions pos) const { void Detector::setReceiverDataStreamingOutIP(const std::string &ip, Positions pos) { - bool previouslyReceiverStreaming = getDataStreamingFromReceiver(pos).squash(false); + bool previouslyReceiverStreaming = + getDataStreamingFromReceiver(pos).squash(false); // TODO! probably in one call pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); if (previouslyReceiverStreaming) { @@ -962,71 +980,87 @@ void Detector::setAdditionalJsonParameter(const std::string &key, pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, key, value); } -Result Detector::getDetectorMinMaxEnergyThreshold(const bool isEmax, Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, isEmax ? "emax" : "emin"); +Result Detector::getDetectorMinMaxEnergyThreshold(const bool isEmax, + Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, + isEmax ? "emax" : "emin"); Result intResult; - try{ + try { for (unsigned int i = 0; i < res.size(); ++i) { intResult[i] = stoi(res[i]); } - } catch(...) { - throw RuntimeError("Cannot find or convert emin/emax string to integer"); + } catch (...) { + throw RuntimeError( + "Cannot find or convert emin/emax string to integer"); } return intResult; } -void Detector::setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, Positions pos) { - pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, isEmax ? "emax" : "emin", std::to_string(value)); +void Detector::setDetectorMinMaxEnergyThreshold(const bool isEmax, + const int value, + Positions pos) { + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, + isEmax ? "emax" : "emin", std::to_string(value)); } Result Detector::getFrameMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, "frameMode"); + auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, + "frameMode"); Result intResult; - try{ + try { for (unsigned int i = 0; i < res.size(); ++i) { intResult[i] = defs::getFrameModeType(res[i]); } - } catch(...) { - throw RuntimeError("Cannot find or convert frameMode string to integer"); + } catch (...) { + throw RuntimeError( + "Cannot find or convert frameMode string to integer"); } return intResult; } void Detector::setFrameMode(defs::frameModeType value, Positions pos) { - pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, "frameMode", defs::getFrameModeType(value)); + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, "frameMode", + defs::getFrameModeType(value)); } Result Detector::getDetectorMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, "detectorMode"); + auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, + "detectorMode"); Result intResult; - try{ + try { for (unsigned int i = 0; i < res.size(); ++i) { intResult[i] = defs::getDetectorModeType(res[i]); } - } catch(...) { - throw RuntimeError("Cannot find or convert detectorMode string to integer"); + } catch (...) { + throw RuntimeError( + "Cannot find or convert detectorMode string to integer"); } return intResult; } void Detector::setDetectorMode(defs::detectorModeType value, Positions pos) { - pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, "detectorMode", defs::getDetectorModeType(value)); + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, + "detectorMode", defs::getDetectorModeType(value)); } Result Detector::getDigitalTestBit(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DIGITAL_BIT_TEST, -1); + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DIGITAL_BIT_TEST, -1); } Result Detector::setDigitalTestBit(int value, Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DIGITAL_BIT_TEST, value); + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DIGITAL_BIT_TEST, value); } Result Detector::executeFirmwareTest(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DETECTOR_FIRMWARE_TEST, -1); + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DETECTOR_FIRMWARE_TEST, -1); } Result Detector::executeBusTest(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DETECTOR_BUS_TEST, -1); + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DETECTOR_BUS_TEST, -1); } void Detector::loadDarkImage(const std::string &fname, Positions pos) { @@ -1037,7 +1071,8 @@ void Detector::loadDarkImage(const std::string &fname, Positions pos) { if (pos.size() > 1) { throw RuntimeError("Cannot load dark image on a subset of modules"); } - pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::DARK_IMAGE, fname); + pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::DARK_IMAGE, + fname); } void Detector::loadGainImage(const std::string &fname, Positions pos) { @@ -1048,21 +1083,26 @@ void Detector::loadGainImage(const std::string &fname, Positions pos) { if (pos.size() > 1) { throw RuntimeError("Cannot load gain image on a subset of modules"); } - pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::GAIN_IMAGE, fname); + pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::GAIN_IMAGE, + fname); } -void Detector::getCounterMemoryBlock(const std::string &fname, bool startACQ, Positions pos) { +void Detector::getCounterMemoryBlock(const std::string &fname, bool startACQ, + Positions pos) { if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { pimpl->writeCounterBlockFile(fname, static_cast(startACQ), -1); } if (pos.size() > 1) { - throw RuntimeError("Cannot load get counter memory block on a subset of modules"); + throw RuntimeError( + "Cannot load get counter memory block on a subset of modules"); } - pimpl->Parallel(&slsDetector::writeCounterBlockFile, pos, fname, static_cast(startACQ)); + pimpl->Parallel(&slsDetector::writeCounterBlockFile, pos, fname, + static_cast(startACQ)); } void Detector::resetCounterBlock(bool startACQ, Positions pos) { - pimpl->Parallel(&slsDetector::resetCounterBlock, pos, static_cast(startACQ)); + pimpl->Parallel(&slsDetector::resetCounterBlock, pos, + static_cast(startACQ)); } Result Detector::getCounterBit(Positions pos) const { @@ -1072,33 +1112,42 @@ Result Detector::getCounterBit(Positions pos) const { void Detector::setCounterBit(bool value, Positions pos) { pimpl->Parallel(&slsDetector::setCounterBit, pos, value); } -/*TODO: + Result> Detector::getROI(Positions pos) const { - int n = 0; - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { - auto res = pimpl->getROI(n, -1); - std::vector arrayRes(n); - std::copy_n(res, n * sizeof(defs::ROI), arrayRes.begin()); - return arrayRes; - } else if (pos.size() > 1) { - throw RuntimeError("Cannot get roi from a subset of modules"); - } else { - auto res = pimpl->Parallel(&slsDetector::getROI, pos, n); - std::vector arrayRes(n); - std::copy_n(res, n * sizeof(defs::ROI), arrayRes.begin()); - return arrayRes; + //vector holding module_id for the modules that should be read + const std::vector id_vec = [&]() { + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)){ + std::vector tmp; + for(size_t i=0; i!= pimpl->size(); ++i) + tmp.push_back(i); + return tmp; + }else{ + return pos; + } + }(); + + //values to return + Result> res; + + //for each detector id get the ROI + for (const auto& i :id_vec){ + int n = 0; + auto ptr = pimpl->getROI(n, i); + res.emplace_back(ptr, ptr+n); } + return res; } void Detector::setROI(std::vector value, Positions pos) { if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { pimpl->setROI(static_cast(value.size()), value.data(), -1); } else if (pos.size() > 1) { - throw RuntimeError("Cannot set roi to a subset of modules"); + throw RuntimeError("Cannot set roi to a subset of modules"); } else { - pimpl->Parallel(&slsDetector::setROI, pos, static_cast(value.size()), value.data()); + pimpl->Parallel(&slsDetector::setROI, pos, + static_cast(value.size()), value.data()); } -}*/ +} Result Detector::getADCEnableMask(Positions pos) const { return pimpl->Parallel(&slsDetector::getADCEnableMask, pos); diff --git a/slsDetectorSoftware/tests/test-Result.cpp b/slsDetectorSoftware/tests/test-Result.cpp index 352df0f68..ceb8f3d07 100644 --- a/slsDetectorSoftware/tests/test-Result.cpp +++ b/slsDetectorSoftware/tests/test-Result.cpp @@ -134,3 +134,34 @@ TEST_CASE("Convert from Result to Result") { REQUIRE(res2[1] == ns(50)); REQUIRE(res2[2] == ns(236)); } + + +TEST_CASE("Result of vectors"){ + using VecVec = std::vector>; + VecVec vecvec{{1,2,3}, {4,5,6}}; + Result res{vecvec}; +} + +TEST_CASE("emplace back"){ + std::vector vec{1,2,3,4,5}; + Result> res; + res.emplace_back(vec.begin(), vec.end()); + REQUIRE(res.size() == 1); + REQUIRE(res[0].size() == 5); + REQUIRE(res[0] == vec); +} + +TEST_CASE("Free function begin end"){ + Result res{"ett", "nio", "sjutton"}; + REQUIRE(begin(res) == res.begin()); + REQUIRE(end(res) == res.end()); +} + +TEST_CASE("Sorting a Result"){ + Result res{4,5,1,3}; + std::sort(res.begin(), res.end()); + REQUIRE(res[0] == 1); + REQUIRE(res[1] == 3); + REQUIRE(res[2] == 4); + REQUIRE(res[3] == 5); +} \ No newline at end of file diff --git a/slsSupportLib/include/FixedCapacityContainer.h b/slsSupportLib/include/FixedCapacityContainer.h index 443426336..f6b57caa9 100644 --- a/slsSupportLib/include/FixedCapacityContainer.h +++ b/slsSupportLib/include/FixedCapacityContainer.h @@ -1,11 +1,11 @@ #pragma once +#include "TypeTraits.h" #include #include +#include #include #include -#include "TypeTraits.h" - namespace sls { template class FixedCapacityContainer { @@ -15,35 +15,35 @@ template class FixedCapacityContainer { using iterator = typename std::array::iterator; using const_iterator = typename std::array::const_iterator; + private: + size_type current_size{}; + std::array data_; + + public: FixedCapacityContainer() = default; - explicit FixedCapacityContainer(std::initializer_list l) { - current_size = l.size(); + + explicit FixedCapacityContainer(std::initializer_list l) + : current_size(l.size()) { + size_check(l.size()); std::copy(l.begin(), l.end(), data_.begin()); } + /** Copy construct from another container */ template ::value && + is_container::value && std::is_same::value>::type> - explicit FixedCapacityContainer(const V &v) { - if (v.size() > Capacity) { - throw std::runtime_error( - "Capacity needs to be same size or larger than vector"); - } - current_size = v.size(); + FixedCapacityContainer(const V &v) : current_size(v.size()) { + size_check(v.size()); std::copy(v.begin(), v.end(), data_.begin()); } - template - explicit FixedCapacityContainer( - const FixedCapacityContainer &other) noexcept { - static_assert(Capacity >= OtherCapacity, - "Container needs to be same size or larger"); - current_size = other.size(); - std::copy(other.cbegin(), other.cend(), data_.begin()); - } - - FixedCapacityContainer &operator=(const std::vector &other) { + /** copy assignment from another container */ + template + typename std::enable_if::value, + FixedCapacityContainer &>::type + operator=(const V &other) { + size_check(other.size()); std::copy(other.begin(), other.end(), data_.begin()); current_size = other.size(); return *this; @@ -110,42 +110,37 @@ template class FixedCapacityContainer { // iterators iterator begin() noexcept { return data_.begin(); } + // auto begin() noexcept -> decltype(data_.begin()) { return data_.begin(); + // } const_iterator begin() const noexcept { return data_.begin(); } iterator end() noexcept { return &data_[current_size]; } const_iterator end() const noexcept { return &data_[current_size]; } const_iterator cbegin() const noexcept { return data_.cbegin(); } const_iterator cend() const noexcept { return &data_[current_size]; } - private: - size_type current_size{}; - std::array data_; + void size_check(size_type s) const { + if (s > Capacity) { + throw std::runtime_error( + "Capacity needs to be same size or larger than vector"); + } + } + } __attribute__((packed)); -/* Free function concerning FixedCapacityContainer */ -template -typename FixedCapacityContainer::iterator -begin(FixedCapacityContainer &container) noexcept { - return container.begin(); -} - -template -typename FixedCapacityContainer::iterator -end(FixedCapacityContainer &container) noexcept { - return container.end(); -} - -template -bool operator==( - const std::vector &vec, +/** support flipped order compare */ +template +typename std::enable_if::value, bool>::type operator==( + const C &container, const FixedCapacityContainer &fixed_container) noexcept { - return fixed_container == vec; + return fixed_container.operator==(container); } -template -bool operator!=( - const std::vector &vec, +/** support flipped order compare */ +template +typename std::enable_if::value, bool>::type operator!=( + const C &container, const FixedCapacityContainer &fixed_container) noexcept { - return fixed_container != vec; + return fixed_container.operator!=(container); } } // namespace sls diff --git a/slsSupportLib/tests/test-FixedCapacityContainer.cpp b/slsSupportLib/tests/test-FixedCapacityContainer.cpp index 4d3552e6f..3fc6089dc 100644 --- a/slsSupportLib/tests/test-FixedCapacityContainer.cpp +++ b/slsSupportLib/tests/test-FixedCapacityContainer.cpp @@ -1,28 +1,81 @@ #include "FixedCapacityContainer.h" -#include "catch.hpp" #include "TypeTraits.h" +#include "catch.hpp" -#include #include +#include using sls::FixedCapacityContainer; -TEST_CASE("FixedCapacityContainer is a container"){ - REQUIRE(sls::is_container>::value == true); +TEST_CASE("FixedCapacityContainer is a container") { + REQUIRE(sls::is_container>::value == true); } +TEST_CASE("Compare array and fixed capacity container") { + std::array arr{1, 2, 3}; + std::array arr2{1, 7, 3}; + FixedCapacityContainer fcc{1, 2, 3}; + REQUIRE(fcc == arr); + REQUIRE(arr == fcc); + REQUIRE_FALSE(fcc != arr); + REQUIRE_FALSE(arr != fcc); + REQUIRE_FALSE(fcc == arr2); + REQUIRE_FALSE(arr2 == fcc); +} -TEST_CASE("Construct from vector"){ - std::vector vec{1,2,3}; +TEST_CASE("Compare vector and fixed capacity container") { + std::vector vec{1, 2, 3}; + std::vector vec2{10, 2, 3}; + FixedCapacityContainer fcc{1, 2, 3}; + REQUIRE(fcc == vec); + REQUIRE(vec == fcc); + REQUIRE_FALSE(fcc != vec); + REQUIRE_FALSE(vec != fcc); + REQUIRE_FALSE(fcc == vec2); + REQUIRE_FALSE(vec2 == fcc); +} + +TEST_CASE("Construct from vector") { + std::vector vec{1, 2, 3}; FixedCapacityContainer fcc{vec}; REQUIRE(fcc == vec); } -TEST_CASE("Construct from array"){ - std::array arr{1,2,3}; +TEST_CASE("Copy construct from vector") { + std::vector vec{1, 2, 3}; + FixedCapacityContainer fcc = vec; + REQUIRE(fcc == vec); +} + +TEST_CASE("Copy assignment from vector") { + std::vector vec{1, 2, 3}; + FixedCapacityContainer fcc; + fcc = vec; + REQUIRE(fcc == vec); +} + +TEST_CASE("Construct from array") { + std::array arr{1, 2, 3}; FixedCapacityContainer fcc{arr}; REQUIRE(fcc == arr); } +TEST_CASE("Copy assign from array") { + std::array arr{1, 2, 3}; + FixedCapacityContainer fcc; + fcc = arr; + REQUIRE(fcc == arr); +} + +TEST_CASE("Copy construct from array") { + std::array arr{1, 2, 3}; + FixedCapacityContainer fcc = arr; + REQUIRE(fcc == arr); +} + +TEST_CASE("Free function and method gives the same iterators") { + FixedCapacityContainer fcc{1, 2, 3}; + REQUIRE(std::begin(fcc) == fcc.begin()); +} SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { GIVEN("A default constructed container") { @@ -30,7 +83,7 @@ SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { FixedCapacityContainer vec; REQUIRE(vec.empty()); - REQUIRE(vec.size() == 0); //NOLINT + REQUIRE(vec.size() == 0); // NOLINT REQUIRE(vec.capacity() == n_elem); REQUIRE(sizeof(vec) == sizeof(int) * n_elem + sizeof(size_t)); @@ -94,13 +147,12 @@ SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { WHEN("We try to resize beyond the capacity") { THEN("it throws") { CHECK_THROWS(vec.resize(25)); } } - WHEN("We call front and back"){ - THEN("They return referenced to the first and last element"){ + WHEN("We call front and back") { + THEN("They return referenced to the first and last element") { REQUIRE(vec.front() == 23); REQUIRE(&vec.front() == &vec[0]); REQUIRE(vec.back() == 11); REQUIRE(&vec.back() == &vec[2]); - } } } @@ -163,7 +215,8 @@ SCENARIO("Comparison of FixedCapacityContainers", "[support]") { } } -SCENARIO("Sorting, removing and other manipulation of a container", "[support]") { +SCENARIO("Sorting, removing and other manipulation of a container", + "[support]") { GIVEN("An unsorted container") { FixedCapacityContainer a{14, 12, 90, 12}; WHEN("We sort it") { @@ -175,23 +228,23 @@ SCENARIO("Sorting, removing and other manipulation of a container", "[support]") REQUIRE(a[3] == 90); } } - WHEN("Sorting is done using free function for begin and end") { - std::sort(begin(a), end(a)); - THEN("it also works") { - REQUIRE(a[0] == 12); - REQUIRE(a[1] == 12); - REQUIRE(a[2] == 14); - REQUIRE(a[3] == 90); - } - } - WHEN("Erasing elements of a certain value") { - a.erase(std::remove(begin(a), end(a), 12)); - THEN("all elements of that value are removed") { - REQUIRE(a.size() == 2); - REQUIRE(a[0] == 14); - REQUIRE(a[1] == 90); - } - } + // WHEN("Sorting is done using free function for begin and end") { + // std::sort(begin(a), end(a)); + // THEN("it also works") { + // REQUIRE(a[0] == 12); + // REQUIRE(a[1] == 12); + // REQUIRE(a[2] == 14); + // REQUIRE(a[3] == 90); + // } + // } + // WHEN("Erasing elements of a certain value") { + // a.erase(std::remove(begin(a), end(a), 12)); + // THEN("all elements of that value are removed") { + // REQUIRE(a.size() == 2); + // REQUIRE(a[0] == 14); + // REQUIRE(a[1] == 90); + // } + // } } } @@ -221,30 +274,28 @@ SCENARIO("Assigning containers to each other", "[support]") { REQUIRE(c[2] == 3); } } - WHEN("We create a const FixedCapacityContainer"){ + WHEN("We create a const FixedCapacityContainer") { const FixedCapacityContainer c(a); - THEN("The values are still the same using const operators"){ + THEN("The values are still the same using const operators") { REQUIRE(c[0] == 1); REQUIRE(c[1] == 2); REQUIRE(c[2] == 3); REQUIRE(c.front() == 1); REQUIRE(c.back() == 3); - } } } } -SCENARIO("Converting to vector", "[support]"){ - GIVEN("a FixedCapacityContainer"){ - FixedCapacityContainer a{1,2,3}; - WHEN("Converted into a vector"){ +SCENARIO("Converting to vector", "[support]") { + GIVEN("a FixedCapacityContainer") { + FixedCapacityContainer a{1, 2, 3}; + WHEN("Converted into a vector") { std::vector b(a); - THEN("Data and size matches"){ + THEN("Data and size matches") { REQUIRE(a == b); REQUIRE(a.size() == b.size()); } } } } -