diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index cd4ef42..f6c10e8 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -2,9 +2,11 @@ set(SourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/DType.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp ) + add_library(core STATIC ${SourceFiles}) target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) @@ -18,6 +20,7 @@ endif() if(AARE_TESTS) set(TestSources ${CMAKE_CURRENT_SOURCE_DIR}/test/defs.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/DType.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/ProducerConsumerQueue.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/NDArray.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/NDView.test.cpp diff --git a/core/include/aare/DType.hpp b/core/include/aare/DType.hpp new file mode 100644 index 0000000..02ca63b --- /dev/null +++ b/core/include/aare/DType.hpp @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include + +namespace aare { + +enum class endian +{ +#ifdef _WIN32 + little = 0, + big = 1, + native = little +#else + little = __ORDER_LITTLE_ENDIAN__, + big = __ORDER_BIG_ENDIAN__, + native = __BYTE_ORDER__ +#endif +}; + +class DType { + static_assert(sizeof(long)==sizeof(int64_t), "long should be 64bits"); + public: + enum TypeIndex { INT8, UINT8, INT16, UINT16, INT32, UINT32, INT64, UINT64, FLOAT, DOUBLE, ERROR }; + + explicit DType(const std::type_info &t); + explicit DType(std::string_view sv); + //not explicit to allow conversions form enum to DType + DType(DType::TypeIndex ti); + + bool operator==(const DType &other) const noexcept; + bool operator!=(const DType &other) const noexcept; + bool operator==(const std::type_info &t) const; + bool operator!=(const std::type_info &t) const; + // bool operator==(DType::TypeIndex ti) const; + // bool operator!=(DType::TypeIndex ti) const; + std::string str() const; + + + private: + TypeIndex m_type{TypeIndex::ERROR}; + +}; + +} // namespace aare \ No newline at end of file diff --git a/core/src/DType.cpp b/core/src/DType.cpp new file mode 100644 index 0000000..cde3b30 --- /dev/null +++ b/core/src/DType.cpp @@ -0,0 +1,128 @@ + +#include "aare/DType.hpp" +#include + +namespace aare { + +DType::DType(const std::type_info &t) { + if (t == typeid(int8_t)) + m_type = TypeIndex::INT8; + else if (t == typeid(uint8_t)) + m_type = TypeIndex::UINT8; + else if (t == typeid(int16_t)) + m_type = TypeIndex::INT16; + else if (t == typeid(uint16_t)) + m_type = TypeIndex::UINT16; + else if (t == typeid(int32_t)) + m_type = TypeIndex::INT32; + else if (t == typeid(uint32_t)) + m_type = TypeIndex::UINT32; + else if (t == typeid(int64_t)) + m_type = TypeIndex::INT64; + else if (t == typeid(long)) + m_type = TypeIndex::INT64; + else if (t == typeid(uint64_t)) + m_type = TypeIndex::UINT64; + else if (t == typeid(float)) + m_type = TypeIndex::FLOAT; + else if (t == typeid(double)) + m_type = TypeIndex::DOUBLE; + else + throw std::runtime_error( + "Could not construct data type. Type not supported."); +} + +DType::DType(DType::TypeIndex ti):m_type(ti){} + +DType::DType(std::string_view sv) { + + // Check if the file is using our native endianess + if (auto pos = sv.find_first_of("<>"); pos != std::string_view::npos) { + const auto endianess = [](const char c) { + if (c == '<') + return endian::little; + return endian::big; + }(sv[pos]); + if (endianess != endian::native) { + throw std::runtime_error("Non native endianess not supported"); + } + } + + // we are done with the endianess so we can remove the prefix + sv.remove_prefix(std::min(sv.find_first_not_of("<>"), sv.size())); + + if (sv == "i1") + m_type = TypeIndex::INT8; + else if (sv == "u1") + m_type = TypeIndex::UINT8; + else if (sv == "i2") + m_type = TypeIndex::INT16; + else if (sv == "u2") + m_type = TypeIndex::UINT16; + else if (sv == "i4") + m_type = TypeIndex::INT32; + else if (sv == "u4") + m_type = TypeIndex::UINT32; + else if (sv == "i8") + m_type = TypeIndex::INT64; + else if (sv == "u8") + m_type = TypeIndex::UINT64; + else if (sv == "f4") + m_type = TypeIndex::FLOAT; + else if (sv == "f8") + m_type = TypeIndex::DOUBLE; + else + throw std::runtime_error( + "Could not construct data type. Type no supported."); +} + +std::string DType::str() const { + + char ec; + if (endian::native == endian::little) + ec = '<'; + else + ec = '>'; + + switch (m_type) { + case TypeIndex::INT8: + return fmt::format("{}i1", ec); + case TypeIndex::UINT8: + return fmt::format("{}u1", ec); + case TypeIndex::INT16: + return fmt::format("{}i2", ec); + case TypeIndex::UINT16: + return fmt::format("{}u2", ec); + case TypeIndex::INT32: + return fmt::format("{}i4", ec); + case TypeIndex::UINT32: + return fmt::format("{}u4", ec); + case TypeIndex::INT64: + return fmt::format("{}i8", ec); + case TypeIndex::UINT64: + return fmt::format("{}u8", ec); + case TypeIndex::FLOAT: + return "f4"; + case TypeIndex::DOUBLE: + return "f8"; + case TypeIndex::ERROR: + return "ERROR"; + } + return {}; +} + +bool DType::operator==(const DType &other) const noexcept { + return m_type == other.m_type; +} +bool DType::operator!=(const DType &other) const noexcept { + return !(*this == other); +} + +bool DType::operator==(const std::type_info &t) const { + return DType(t) == *this; +} +bool DType::operator!=(const std::type_info &t) const { + return DType(t) != *this; +} + +} // namespace pl diff --git a/core/test/DType.test.cpp b/core/test/DType.test.cpp new file mode 100644 index 0000000..a06792e --- /dev/null +++ b/core/test/DType.test.cpp @@ -0,0 +1,58 @@ + + +#include "aare/DType.hpp" +#include + +using aare::DType; +using aare::endian; + + + +TEST_CASE("Construct from typeid") { + REQUIRE(DType(typeid(int)) == typeid(int)); + REQUIRE(DType(typeid(int)) != typeid(double)); +} + +TEST_CASE("Construct from string") { + if (endian::native == endian::little){ + REQUIRE(DType("i1") == typeid(int8_t)); + REQUIRE(DType(">u1") == typeid(uint8_t)); + REQUIRE(DType(">i2") == typeid(int16_t)); + REQUIRE(DType(">u2") == typeid(uint16_t)); + REQUIRE(DType(">i4") == typeid(int)); + REQUIRE(DType(">u4") == typeid(unsigned)); + REQUIRE(DType(">i4") == typeid(int32_t)); + REQUIRE(DType(">i8") == typeid(long)); + REQUIRE(DType(">i8") == typeid(int64_t)); + REQUIRE(DType(">u4") == typeid(uint32_t)); + REQUIRE(DType(">u8") == typeid(uint64_t)); + REQUIRE(DType("f4") == typeid(float)); + REQUIRE(DType("f8") == typeid(double)); + } + +} + +TEST_CASE("Construct from string with endianess"){ + //TODO! handle big endian system in test! + REQUIRE(DType("i4") == typeid(int32_t)); +} + + +TEST_CASE("Convert to string") { REQUIRE(DType(typeid(int)).str() == "