diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ddbeeb..547a9c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,7 @@ endif() set(MYNTEYE_SRCS ${UVC_SRC} + src/internal/types.cc src/public/types.cc ) diff --git a/src/internal/types.cc b/src/internal/types.cc new file mode 100644 index 0000000..d50de05 --- /dev/null +++ b/src/internal/types.cc @@ -0,0 +1,48 @@ +#include "internal/types.h" + +#include + +#include +#include +#include + +MYNTEYE_BEGIN_NAMESPACE + +std::string Version::to_string() const { + std::stringstream s; + s << static_cast(major_) << "." << static_cast(minor_); + return s.str(); +} + +std::vector Version::split(const std::string &s) { + std::vector result; + auto e = s.end(); + auto i = s.begin(); + while (i != e) { + i = std::find_if_not(i, e, [](char c) { return c == '.'; }); + if (i == e) + break; + auto j = std::find(i, e, '.'); + result.emplace_back(i, j); + i = j; + } + return result; +} + +Version::value_t Version::parse_part(const std::string &name, size_t part) { + return std::stoi(split(name)[part]); +} + +std::string Type::to_string() const { + std::stringstream s; + s << std::hex << std::uppercase << std::setfill('0') << std::setw(2) + << vendor_ << std::setfill('0') << std::setw(2) << product_; + return s.str(); +} + +Type::value_t Type::parse_part( + const std::string &name, size_t pos, size_t count) { + return std::stoi(name.substr(pos, count), 0, 16); +} + +MYNTEYE_END_NAMESPACE diff --git a/src/internal/types.h b/src/internal/types.h index 8e1db19..0a3bd41 100644 --- a/src/internal/types.h +++ b/src/internal/types.h @@ -4,22 +4,139 @@ #include +#include +#include +#include + #include "mynteye/mynteye.h" -#define FOURCC(a, b, c, d) \ +MYNTEYE_BEGIN_NAMESPACE + +#define MYNTEYE_FOURCC(a, b, c, d) \ ((std::uint32_t)(a) | ((std::uint32_t)(b) << 8) | \ ((std::uint32_t)(c) << 16) | ((std::uint32_t)(d) << 24)) // NOLINT -MYNTEYE_BEGIN_NAMESPACE - /** * @ingroup enumerations * @brief Formats define how each stream can be encoded. */ enum class Format : std::uint32_t { - YUYV = FOURCC('Y', 'U', 'Y', 'V'), + YUYV = MYNTEYE_FOURCC('Y', 'U', 'Y', 'V'), }; +#undef MYNTEYE_FOURCC + +#define MYNTEYE_PROPERTY(TYPE, NAME) \ + public: \ + void set_##NAME(TYPE NAME) { \ + NAME##_ = NAME; \ + } \ + TYPE NAME() const { \ + return NAME##_; \ + } \ + \ + private: \ + TYPE NAME##_; + +/** + * Version. + */ +class Version { + public: + using size_t = std::size_t; + using value_t = std::uint8_t; + + Version(value_t major, value_t minor) : major_(major), minor_(minor) {} + explicit Version(const std::string &name) + : major_(parse_part(name, 0)), minor_(parse_part(name, 1)) {} + virtual ~Version() {} + + bool operator==(const Version &other) const { + return major_ == other.major_ && minor_ == other.minor_; + } + bool operator<=(const Version &other) const { + if (major_ < other.major_) + return true; + if (major_ > other.major_) + return false; + return minor_ <= other.minor_; + } + bool operator!=(const Version &other) const { + return !(*this == other); + } + bool operator<(const Version &other) const { + return !(*this == other) && (*this <= other); + } + bool operator>(const Version &other) const { + return !(*this <= other); + } + bool operator>=(const Version &other) const { + return (*this == other) || (*this > other); + } + bool is_between(const Version &from, const Version &until) { + return (from <= *this) && (*this <= until); + } + + std::string to_string() const; + + static std::vector split(const std::string &s); + static value_t parse_part(const std::string &name, size_t part); + + MYNTEYE_PROPERTY(value_t, major) + MYNTEYE_PROPERTY(value_t, minor) +}; + +/** + * Hardware version. + */ +class HardwareVersion : public Version { + public: + using flag_t = std::bitset<8>; + + HardwareVersion(value_t major, value_t minor, value_t flag = 0) + : Version(major, minor), flag_(flag) {} + explicit HardwareVersion(const std::string &name, value_t flag = 0) + : Version(parse_part(name, 0), parse_part(name, 1)), flag_(flag) {} + + MYNTEYE_PROPERTY(flag_t, flag) +}; + +/** + * Type. + */ +class Type { + public: + using size_t = std::size_t; + using value_t = std::uint16_t; + + Type(value_t vendor, value_t product) : vendor_(vendor), product_(product) {} + explicit Type(const std::string &name) + : vendor_(parse_part(name, 0, 2)), product_(parse_part(name, 2, 2)) {} + virtual ~Type() {} + + std::string to_string() const; + static value_t parse_part(const std::string &name, size_t pos, size_t count); + + MYNTEYE_PROPERTY(value_t, vendor) + MYNTEYE_PROPERTY(value_t, product) +}; + +/** + * Device infomation. + */ +struct DeviceInfo { + std::string name; + std::string serial_number; + Version firmware_version; + HardwareVersion hardware_version; + Version spec_version; + Type lens_type; + Type imu_type; + std::uint16_t nominal_baseline; +}; + +#undef MYNTEYE_PROPERTY + MYNTEYE_END_NAMESPACE #endif // MYNTEYE_INTERNAL_TYPES_H_ NOLINT diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 72c8a67..9b48da0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -63,12 +63,15 @@ set_outdir( include_directories( ${GTEST_DIR}/include + ${PRO_DIR}/src ) +file(GLOB TEST_INTERNAL_SRC "internal/*.cc") file(GLOB TEST_PUBLIC_SRC "public/*.cc") add_executable(${PROJECT_NAME} gtest_main.cc + ${TEST_INTERNAL_SRC} ${TEST_PUBLIC_SRC} ) target_link_libraries(${PROJECT_NAME} ${GTEST_LIBS} mynteye) diff --git a/test/internal/types_test.cc b/test/internal/types_test.cc new file mode 100644 index 0000000..9d557d1 --- /dev/null +++ b/test/internal/types_test.cc @@ -0,0 +1,112 @@ +#include "gtest/gtest.h" + +#include "internal/types.h" + +MYNTEYE_USE_NAMESPACE + +class VersionTest : public ::testing::Test { + protected: + VersionTest() + : ver_1_0(Version(1, 0)), + ver_1_2(Version(1, 2)), + ver_2_0(Version(2, 0)) {} + + virtual ~VersionTest() {} + + virtual void SetUp() {} + + virtual void TearDown() {} + + Version ver_1_0; + Version ver_1_2; + Version ver_2_0; +}; + +TEST_F(VersionTest, Properties) { + EXPECT_EQ(1, ver_1_0.major()); + EXPECT_EQ(0, ver_1_0.minor()); +} + +TEST_F(VersionTest, Operators) { + EXPECT_TRUE(ver_1_0 == ver_1_0); + EXPECT_TRUE(ver_1_0 <= ver_1_2); + EXPECT_TRUE(ver_1_0 != ver_1_2); + EXPECT_TRUE(ver_1_0 < ver_1_2); + EXPECT_TRUE(ver_1_2 > ver_1_0); + EXPECT_TRUE(ver_1_2 >= ver_1_0); + + EXPECT_TRUE(ver_1_0 <= ver_1_0); + EXPECT_TRUE(ver_1_2 >= ver_1_2); + + EXPECT_TRUE(ver_1_2 == ver_1_2); + EXPECT_TRUE(ver_1_2 <= ver_2_0); + EXPECT_TRUE(ver_1_2 != ver_2_0); + EXPECT_TRUE(ver_1_2 < ver_2_0); + EXPECT_TRUE(ver_2_0 > ver_1_2); + EXPECT_TRUE(ver_2_0 >= ver_1_2); + + EXPECT_TRUE(ver_1_2 <= ver_1_2); + EXPECT_TRUE(ver_2_0 >= ver_2_0); +} + +TEST_F(VersionTest, Between) { + EXPECT_TRUE(ver_1_0.is_between(ver_1_0, ver_2_0)); + EXPECT_TRUE(ver_1_2.is_between(ver_1_0, ver_2_0)); + EXPECT_TRUE(ver_2_0.is_between(ver_1_0, ver_2_0)); + + EXPECT_FALSE(ver_1_0.is_between(ver_1_2, ver_2_0)); + EXPECT_FALSE(ver_2_0.is_between(ver_1_0, ver_1_2)); +} + +TEST_F(VersionTest, Strings) { + EXPECT_EQ("1.0", ver_1_0.to_string()); + EXPECT_EQ("1.2", ver_1_2.to_string()); + EXPECT_EQ("2.0", ver_2_0.to_string()); + + EXPECT_EQ("1.0", Version("1.0").to_string()); + EXPECT_EQ("1.2", Version("1.2").to_string()); + EXPECT_EQ("2.0", Version("2.0").to_string()); +} + +class HardwareVersionTest : public ::testing::Test { + protected: + HardwareVersionTest() : ver_1_0(HardwareVersion(1, 0)) {} + + HardwareVersion ver_1_0; +}; + +TEST_F(HardwareVersionTest, Properties) { + EXPECT_EQ(1, ver_1_0.major()); + EXPECT_EQ(0, ver_1_0.minor()); +} + +TEST_F(HardwareVersionTest, Strings) { + EXPECT_EQ("1.0", ver_1_0.to_string()); + EXPECT_EQ("1.0", HardwareVersion("1.0").to_string()); +} + +TEST_F(HardwareVersionTest, Flags) { + auto flag = ver_1_0.flag(); + EXPECT_EQ("00000000", flag.to_string()); + + flag[0] = true; + flag[flag.size() - 1] = true; + EXPECT_EQ("10000001", flag.to_string()); +} + +class TypeTest : public ::testing::Test { + protected: + TypeTest() : type_1_2a(Type(1, 0x2A)) {} + + Type type_1_2a; +}; + +TEST_F(TypeTest, Properties) { + EXPECT_EQ(1, type_1_2a.vendor()); + EXPECT_EQ(0x2A, type_1_2a.product()); +} + +TEST_F(TypeTest, Strings) { + EXPECT_EQ("012A", type_1_2a.to_string()); + EXPECT_EQ("010A", Type("010A").to_string()); +}