From 8e2494729b9f43a929eb7df13f3e7a72b37df25b Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 12 Aug 2019 14:23:12 +0200 Subject: [PATCH] WIP --- .../include/FixedCapacityContainer.h | 235 +++++++----------- slsSupportLib/include/ToString.h | 11 +- slsSupportLib/include/TypeTraits.h | 21 ++ .../tests/test-FixedCapacityContainer.cpp | 20 ++ slsSupportLib/tests/test-ToString.cpp | 31 +-- slsSupportLib/tests/test-TypeTraits.cpp | 5 + 6 files changed, 167 insertions(+), 156 deletions(-) diff --git a/slsSupportLib/include/FixedCapacityContainer.h b/slsSupportLib/include/FixedCapacityContainer.h index d53136baa..443426336 100644 --- a/slsSupportLib/include/FixedCapacityContainer.h +++ b/slsSupportLib/include/FixedCapacityContainer.h @@ -4,176 +4,133 @@ #include #include +#include "TypeTraits.h" + namespace sls { template class FixedCapacityContainer { + public: + using size_type = typename std::array::size_type; + using value_type = typename std::array::value_type; + using iterator = typename std::array::iterator; + using const_iterator = typename std::array::const_iterator; + FixedCapacityContainer() = default; - explicit FixedCapacityContainer(std::initializer_list l); - explicit FixedCapacityContainer(const std::vector &v); + explicit FixedCapacityContainer(std::initializer_list l) { + current_size = l.size(); + std::copy(l.begin(), l.end(), data_.begin()); + } + + template ::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(); + std::copy(v.begin(), v.end(), data_.begin()); + } template explicit FixedCapacityContainer( - const FixedCapacityContainer &other) noexcept; + 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); + FixedCapacityContainer &operator=(const std::vector &other) { + std::copy(other.begin(), other.end(), data_.begin()); + current_size = other.size(); + return *this; + } - bool operator==(const std::vector &other) const noexcept; - bool operator!=(const std::vector &other) const noexcept; + /** Compare FixedCapacityContainer with any other container*/ + template + typename std::enable_if::value, bool>::type + operator==(const V &other) const noexcept { + if (current_size != other.size()) { + return false; + } else { + for (size_t i = 0; i != current_size; ++i) { + if (data_[i] != other[i]) { + return false; + } + } + } + return true; + } - operator std::vector(){return std::vector(begin(), end());} + template + typename std::enable_if::value, bool>::type + operator!=(const V &other) const noexcept { + return !(*this == other); + } - template - bool operator==(const FixedCapacityContainer &other) const - noexcept; - - template - bool operator!=(const FixedCapacityContainer &other) const - noexcept; + operator std::vector() { return std::vector(begin(), end()); } T &operator[](size_t i) { return data_[i]; } const T &operator[](size_t i) const { return data_[i]; } - - constexpr size_t size() const noexcept { return size_; } - bool empty() const noexcept { return size_ == 0; } + constexpr size_type size() const noexcept { return current_size; } + bool empty() const noexcept { return current_size == 0; } constexpr size_t capacity() const noexcept { return Capacity; } - void push_back(const T &value); - void resize(size_t new_size); - void erase(T *ptr); + void push_back(const T &value) { + if (current_size == Capacity) { + throw std::runtime_error("Container is full"); + } else { + data_[current_size] = value; + ++current_size; + } + } + + void resize(size_t new_size) { + if (new_size > Capacity) { + throw std::runtime_error("Cannot resize beyond capacity"); + } else { + current_size = new_size; + } + } + + void erase(T *ptr) { + if (ptr >= begin() && ptr < end()) { + current_size = static_cast(ptr - begin()); + } else { + throw std::runtime_error("tried to erase with a ptr outside obj"); + } + } T &front() noexcept { return data_.front(); } - T &back() noexcept { return data_[size_ - 1]; } + T &back() noexcept { return data_[current_size - 1]; } constexpr const T &front() const noexcept { return data_.front(); } - constexpr const T &back() const noexcept { return data_[size_ - 1]; } + constexpr const T &back() const noexcept { return data_[current_size - 1]; } // iterators - T *begin() noexcept { return &data_[0]; } - T *end() noexcept { return &data_[size_]; } - const T *cbegin() const noexcept { return &data_[0]; } - const T *cend() const noexcept { return &data_[size_]; } + iterator begin() noexcept { 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_t size_{0}; + size_type current_size{}; std::array data_; } __attribute__((packed)); -/* Member functions */ -template -FixedCapacityContainer::FixedCapacityContainer( - std::initializer_list l) { - size_ = l.size(); - std::copy(l.begin(), l.end(), data_.begin()); -} - -template -FixedCapacityContainer::FixedCapacityContainer( - const std::vector &v) { - if (v.size() > Capacity) { - throw std::runtime_error( - "Capacity needs to be same size or larger than vector"); - } - size_ = v.size(); - std::copy(v.begin(), v.end(), data_.begin()); -} - -template -template -FixedCapacityContainer::FixedCapacityContainer( - const FixedCapacityContainer &other) noexcept { - static_assert(Capacity >= OtherCapacity, - "Container needs to be same size or larger"); - size_ = other.size(); - std::copy(other.cbegin(), other.cend(), data_.begin()); -} - -template -void FixedCapacityContainer::push_back(const T &value) { - if (size_ == Capacity) { - throw std::runtime_error("Container is full"); - } else { - data_[size_] = value; - ++size_; - } -} -template -void FixedCapacityContainer::resize(size_t new_size) { - if (new_size > Capacity) { - throw std::runtime_error("Cannot resize beyond capacity"); - } else { - size_ = new_size; - } -} - -template -FixedCapacityContainer &FixedCapacityContainer:: -operator=(const std::vector &other) { - std::copy(other.begin(), other.end(), data_.begin()); - size_ = other.size(); - return *this; -} - -template -bool FixedCapacityContainer:: -operator==(const std::vector &other) const noexcept { - if (size_ != other.size()) { - return false; - } else { - for (size_t i = 0; i != size_; ++i) { - if (data_[i] != other[i]) { - return false; - } - } - } - return true; -} - -template -bool FixedCapacityContainer:: -operator!=(const std::vector &other) const noexcept { - return !(*this == other); -} - -template -template -bool FixedCapacityContainer:: -operator==(const FixedCapacityContainer &other) const - noexcept { - if (size_ != other.size()) { - return false; - } else { - for (size_t i = 0; i != size_; ++i) { - if (data_[i] != other[i]) { - return false; - } - } - } - return true; -} - -template -template -bool FixedCapacityContainer:: -operator!=(const FixedCapacityContainer &other) const - noexcept { - return !(*this == other); -} - -template -void FixedCapacityContainer::erase(T *ptr) { - if (ptr >= begin() && ptr < end()) { - size_ = static_cast(ptr - begin()); - } else { - throw std::runtime_error("tried to erase with a ptr outside obj"); - } -} - /* Free function concerning FixedCapacityContainer */ template -constexpr T *begin(FixedCapacityContainer &container) noexcept { +typename FixedCapacityContainer::iterator +begin(FixedCapacityContainer &container) noexcept { return container.begin(); } template -constexpr T *end(FixedCapacityContainer &container) noexcept { +typename FixedCapacityContainer::iterator +end(FixedCapacityContainer &container) noexcept { return container.end(); } diff --git a/slsSupportLib/include/ToString.h b/slsSupportLib/include/ToString.h index b032151e5..03d601fa3 100644 --- a/slsSupportLib/include/ToString.h +++ b/slsSupportLib/include/ToString.h @@ -2,9 +2,9 @@ /** * \file ToString.h - * + * * Conversion from various types to std::string - * + * */ #include "TimeHelper.h" @@ -137,4 +137,11 @@ template T StringTo(std::string t) { return StringTo(t, unit); } +/** For types with a .str() method use this for conversion */ +template +typename std::enable_if::value, std::string>::type +ToString(const T &obj) { + return obj.str(); +} + } // namespace sls diff --git a/slsSupportLib/include/TypeTraits.h b/slsSupportLib/include/TypeTraits.h index b7297389c..71d37e9ad 100644 --- a/slsSupportLib/include/TypeTraits.h +++ b/slsSupportLib/include/TypeTraits.h @@ -58,4 +58,25 @@ struct is_container< decltype(std::declval().empty())>, void>::type> : public std::true_type {}; + +/** + * Type trait to evaluate if template parameter is + * complying with a standard container + */ +template +struct is_light_container : std::false_type {}; + +template struct is_light_container_helper {}; + +template +struct is_light_container< + T, typename std::conditional< + false, + is_container_helper().size()), + decltype(std::declval().begin()), + decltype(std::declval().end())>, + void>::type> : public std::true_type {}; + } // namespace sls \ No newline at end of file diff --git a/slsSupportLib/tests/test-FixedCapacityContainer.cpp b/slsSupportLib/tests/test-FixedCapacityContainer.cpp index d4853cab7..4d3552e6f 100644 --- a/slsSupportLib/tests/test-FixedCapacityContainer.cpp +++ b/slsSupportLib/tests/test-FixedCapacityContainer.cpp @@ -1,8 +1,28 @@ #include "FixedCapacityContainer.h" #include "catch.hpp" +#include "TypeTraits.h" +#include +#include using sls::FixedCapacityContainer; +TEST_CASE("FixedCapacityContainer is a container"){ + REQUIRE(sls::is_container>::value == true); +} + + +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}; + FixedCapacityContainer fcc{arr}; + REQUIRE(fcc == arr); +} + SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { GIVEN("A default constructed container") { diff --git a/slsSupportLib/tests/test-ToString.cpp b/slsSupportLib/tests/test-ToString.cpp index 6ec8c3f4f..dfc255d48 100644 --- a/slsSupportLib/tests/test-ToString.cpp +++ b/slsSupportLib/tests/test-ToString.cpp @@ -1,27 +1,25 @@ #include "TimeHelper.h" #include "ToString.h" +#include "network_utils.h" #include "catch.hpp" -#include #include - +#include // using namespace sls; -using sls::ToString; using sls::StringTo; +using sls::ToString; using namespace sls::time; - -TEST_CASE("Integer conversions", "[support]"){ +TEST_CASE("Integer conversions", "[support]") { REQUIRE(ToString(0) == "0"); REQUIRE(ToString(1) == "1"); REQUIRE(ToString(-1) == "-1"); REQUIRE(ToString(100) == "100"); REQUIRE(ToString(589633100) == "589633100"); - } -TEST_CASE("floating point conversions", "[support]"){ - //Should strip trailing zeros +TEST_CASE("floating point conversions", "[support]") { + // Should strip trailing zeros REQUIRE(ToString(0.) == "0"); REQUIRE(ToString(1.) == "1"); REQUIRE(ToString(-1.) == "-1"); @@ -32,7 +30,6 @@ TEST_CASE("floating point conversions", "[support]"){ REQUIRE(ToString(2.35010) == "2.3501"); REQUIRE(ToString(5000) == "5000"); REQUIRE(ToString(5E15) == "5000000000000000"); - } TEST_CASE("conversion from duration to string", "[support]") { @@ -55,13 +52,13 @@ TEST_CASE("string to std::chrono::duration", "[support]") { REQUIRE_THROWS(StringTo("asvn")); } -TEST_CASE("Convert vector of time", "[support]"){ +TEST_CASE("Convert vector of time", "[support]") { std::vector vec{ns(150), us(10), ns(600)}; REQUIRE(ToString(vec) == "[150ns, 10us, 600ns]"); REQUIRE(ToString(vec, "ns") == "[150ns, 10000ns, 600ns]"); } -TEST_CASE("Vector of int", "[support]"){ +TEST_CASE("Vector of int", "[support]") { std::vector vec; REQUIRE(ToString(vec) == "[]"); @@ -73,10 +70,9 @@ TEST_CASE("Vector of int", "[support]"){ vec.push_back(5000); REQUIRE(ToString(vec) == "[1, 172, 5000]"); - } -TEST_CASE("Vector of double", "[support]"){ +TEST_CASE("Vector of double", "[support]") { std::vector vec; REQUIRE(ToString(vec) == "[]"); @@ -90,8 +86,13 @@ TEST_CASE("Vector of double", "[support]"){ REQUIRE(ToString(vec) == "[1.3, 5669.325, -5669.325005]"); } -TEST_CASE("Array"){ - std::array arr{1,2,3}; +TEST_CASE("Array") { + std::array arr{1, 2, 3}; REQUIRE(ToString(arr) == "[1, 2, 3]"); +} +TEST_CASE("Convert types with str method"){ + sls::IpAddr addr; + REQUIRE(ToString(addr) == "0.0.0.0"); + REQUIRE(ToString(sls::IpAddr{}) == "0.0.0.0"); } \ No newline at end of file diff --git a/slsSupportLib/tests/test-TypeTraits.cpp b/slsSupportLib/tests/test-TypeTraits.cpp index 042eee3ac..2234ca0ae 100644 --- a/slsSupportLib/tests/test-TypeTraits.cpp +++ b/slsSupportLib/tests/test-TypeTraits.cpp @@ -4,6 +4,7 @@ #include #include #include +#include //Dummy classes only used here for testing class DummyWithStr { @@ -38,4 +39,8 @@ TEST_CASE("sls::is_duration"){ REQUIRE(sls::is_duration::value == false); REQUIRE(sls::is_duration>::value == false); +} + +TEST_CASE("initializer list"){ + REQUIRE(sls::is_light_container>::value == true); } \ No newline at end of file