diff --git a/include/duckhandy/version_bt.hpp b/include/duckhandy/version_bt.hpp new file mode 100644 index 0000000..5b7f80d --- /dev/null +++ b/include/duckhandy/version_bt.hpp @@ -0,0 +1,101 @@ +/* Copyright 2016-2021 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * "duckhandy" is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "duckhandy". If not, see . + */ + +#ifndef id5594416333AA4792BFEC94E863E03B08 +#define id5594416333AA4792BFEC94E863E03B08 + +#include "int_conv.hpp" +#include +#include + +namespace dhandy { + +template +class Version { +public: + constexpr static std::size_t Count = N; + + constexpr Version (const char* const ver, bool accept_less=false); + + constexpr unsigned int operator[] (std::size_t idx) const; + constexpr unsigned int major() const; + constexpr unsigned int minor() const; + constexpr unsigned int revision() const; + +private: + unsigned int m_versions[N]; +}; + +template +inline constexpr Version::Version (const char* const ver, bool accept_less) : + m_versions{0} +{ + std::size_t z = 0; + std::size_t s = 0; + std::size_t idx = 0; + bool commit = false; + + do { + if (ver[z] >= '0' and ver[z] <= '9') { + commit = true; + } + else if (commit) { + commit = false; + m_versions[idx++] = dhandy::ary_to_int(ver + s, ver + z); + s = z + 1; + } + else { + s = z + 1; + } + } while(ver[z++] and idx < N); + + if (not accept_less and idx < N) + throw std::invalid_argument("Input version doesn't contain enough version numbers"); +} + +template +inline constexpr unsigned int Version::operator[] (std::size_t idx) const { + if (idx < N) + return m_versions[idx]; + else + throw std::out_of_range("Index is out of range"); +} + +template +inline constexpr unsigned int Version::major() const { + return m_versions[0]; +} + +template +inline constexpr unsigned int Version::minor() const { + if constexpr (N > 1) + return m_versions[1]; + else + throw std::out_of_range("Not enough version entries, there is no minor number"); +} + +template +inline constexpr unsigned int Version::revision() const { + if constexpr (N > 2) + return m_versions[2]; + else + throw std::out_of_range("Not enough version entries, there is no revision number"); +} + +} //namespace dhandy + +#endif diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index eaae1f8..16efbcf 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -7,6 +7,7 @@ add_executable(${PROJECT_NAME} reversed_sized_array_test.cpp bitfield_pack_test.cpp resource_pool_test.cpp + version_test.cpp ) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) diff --git a/test/unit/version_test.cpp b/test/unit/version_test.cpp new file mode 100644 index 0000000..60b8cb0 --- /dev/null +++ b/test/unit/version_test.cpp @@ -0,0 +1,94 @@ +/* Copyright 2016-2021 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * "duckhandy" is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "duckhandy". If not, see . + */ + +#include "catch2/catch.hpp" +#include "duckhandy/version_bt.hpp" + +TEST_CASE ("Version class tests", "[version][bt]") { + using dhandy::Version; + + { + constexpr Version<1> ver{"102"}; + static_assert(ver.major() == 102, "Version error"); + static_assert(ver.Count == 1, "Version error"); + CHECK(ver[0] == 102); + CHECK_THROWS(ver[1]); + CHECK_THROWS(ver[2]); + CHECK_THROWS(ver[3]); + CHECK_THROWS(ver[4]); + } + + { + constexpr Version<3> ver{".aheud15,a.ud22,cu.sh81,.nuad.h44"}; + static_assert(ver.Count == 3, "Version error"); + static_assert(ver.major() == 15, "Version error"); + static_assert(ver.minor() == 22, "Version error"); + static_assert(ver.revision() == 81, "Version error"); + CHECK(ver[0] == 15); + CHECK(ver[1] == 22); + CHECK(ver[2] == 81); + CHECK_THROWS(ver[3]); + CHECK_THROWS(ver[4]); + } + + { + constexpr Version<10> ver{"1.2.3.44.55.66.777.888.999.101010"}; + static_assert(ver.Count == 10, "Version error"); + static_assert(ver.major() == 1, "Version error"); + static_assert(ver.minor() == 2, "Version error"); + static_assert(ver.revision() == 3, "Version error"); + CHECK(ver[0] == 1); + CHECK(ver[1] == 2); + CHECK(ver[2] == 3); + CHECK(ver[3] == 44); + CHECK(ver[4] == 55); + CHECK(ver[5] == 66); + CHECK(ver[6] == 777); + CHECK(ver[7] == 888); + CHECK(ver[8] == 999); + CHECK(ver[9] == 101010); + CHECK_THROWS(ver[10]); + } + + { + constexpr Version<4> ver{"1.2.3.", true}; + static_assert(ver.Count == 4, "Version error"); + static_assert(ver.major() == 1, "Version error"); + static_assert(ver.minor() == 2, "Version error"); + static_assert(ver.revision() == 3, "Version error"); + CHECK(ver[0] == 1); + CHECK(ver[1] == 2); + CHECK(ver[2] == 3); + CHECK(ver[3] == 0); + CHECK_THROWS(ver[10]); + } + + { + constexpr Version<4> ver{"6.7.2-r1"}; + static_assert(ver.Count == 4, "Version error"); + static_assert(ver.major() == 6, "Version error"); + static_assert(ver.minor() == 7, "Version error"); + static_assert(ver.revision() == 2, "Version error"); + CHECK(ver[0] == 6); + CHECK(ver[1] == 7); + CHECK(ver[2] == 2); + CHECK(ver[3] == 1); + CHECK_THROWS(ver[10]); + } + + CHECK_THROWS(Version<4>{"4.5"}); +}