Skip to content

Commit

Permalink
Merge pull request #55 from ami-iit/conversions
Browse files Browse the repository at this point in the history
Adds reflection and conversions from common types
  • Loading branch information
S-Dafarra authored Apr 28, 2022
2 parents 1555d24 + a94caa1 commit ed9b196
Show file tree
Hide file tree
Showing 25 changed files with 1,040 additions and 70 deletions.
26 changes: 2 additions & 24 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ on:
pull_request:

env:
# commit from vcpkg's master branch on 2020/10/06
vcpkg_TAG: 76a7e9248fb3c57350b559966dcaa2d52a5e4458
Catch2_TAG: v2.11.3

jobs:
Expand All @@ -16,7 +14,7 @@ jobs:
strategy:
matrix:
build_type: [Release, Debug]
os: [ubuntu-latest, windows-latest, macOS-latest]
os: [ubuntu-latest, macOS-latest]
fail-fast: false

steps:
Expand All @@ -39,15 +37,6 @@ jobs:
for apt_file in `grep -lr microsoft /etc/apt/sources.list.d/`; do sudo rm $apt_file; done
# Restore from cache the previously built ports. If "cache miss"
# then provision vcpkg, install desired ports, finally cache everything for the next run.
- name: Dependencies [Windows]
if: matrix.os == 'windows-latest'
uses: lukka/run-vcpkg@v6
with:
vcpkgArguments: '--triplet x64-windows matio catch2'
vcpkgGitCommitId: ${{ env.vcpkg_TAG }}

- name: Dependencies [macOS]
if: matrix.os == 'macOS-latest'
run: |
Expand All @@ -58,7 +47,7 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install libmatio-dev valgrind
sudo apt-get install libmatio-dev valgrind libeigen3-dev
- name: Cache Source-based Dependencies
id: cache-source-deps
Expand Down Expand Up @@ -88,17 +77,6 @@ jobs:
# CMAKE-BASED PROJECT
# ===================

- name: Configure [Windows]
# Use bash also on Windows (otherwise cd, mkdir, ... do not work)
if: matrix.os == 'windows-latest'
shell: bash
run: |
mkdir -p build
cd build
cmake -A x64 -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake \
-DCMAKE_PREFIX_PATH=${GITHUB_WORKSPACE}/install/deps \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/install \
-DBUILD_TESTING:BOOL=ON ..

- name: Configure [Ubuntu]
if: matrix.os == 'ubuntu-latest'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/conda-forge-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
build_type: [Release]
os: [ubuntu-latest, windows-latest, macOS-latest]
os: [ubuntu-latest, windows-2019, macOS-latest]
fail-fast: false

steps:
Expand All @@ -31,9 +31,9 @@ jobs:
shell: bash -l {0}
run: |
# Compilation related dependencies
mamba install cmake compilers make ninja pkg-config
mamba install cmake compilers make ninja pkg-config
# Actual dependencies
mamba install libmatio catch2
mamba install libmatio catch2 eigen
- name: Configure [Linux&macOS]
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
- Using a custom variable in InstallBasicPackageFile to backup the module path: [#47](https://github.com/ami-iit/matio-cpp/pull/47).
- Added more checks before creating a file: [#49](https://github.com/ami-iit/matio-cpp/pull/49).
- Added reflection and conversions from common types [#55](https://github.com/ami-iit/matio-cpp/pull/55)

## [0.1.1] - 2021-03-22

Expand Down
46 changes: 41 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# BSD-2-Clause license (https://opensource.org/licenses/BSD-2-Clause).

cmake_minimum_required(VERSION 3.10)
project(matioCpp VERSION 0.1.1 LANGUAGES CXX)
project(matioCpp VERSION 0.2.0 LANGUAGES CXX)

# Defines the CMAKE_INSTALL_LIBDIR, CMAKE_INSTALL_BINDIR and many other useful macros.
# See https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html
Expand Down Expand Up @@ -89,6 +89,30 @@ endif()

## Dependencies
find_package(MATIO REQUIRED)
find_package(Eigen3 QUIET)

if (Eigen3_FOUND)
set(MATIOCPP_HAS_EIGEN TRUE)
endif()

# Fetching visit_struct
include(CMakeDependentOption)
find_package(visit_struct QUIET)
cmake_dependent_option(USE_SYSTEM_visit_struct "Use system visit_struct" ON "visit_struct_FOUND" OFF)
if(USE_SYSTEM_visit_struct)
find_package(visit_struct REQUIRED)
else()
include(FetchContent)
FetchContent_Declare(visit_struct
GIT_REPOSITORY https://github.com/ami-iit/visit_struct
GIT_TAG 969fc563477906432a9fcc91addf2c1e13c56f4c)

FetchContent_GetProperties(visit_struct)
if(NOT visit_struct_POPULATED)
message(STATUS "Fetching visit_struct...")
FetchContent_MakeAvailable(visit_struct)
endif()
endif()

set(MATIOCPP_SRC src/Variable.cpp
src/ConversionUtilities.cpp
Expand All @@ -98,11 +122,14 @@ set(MATIOCPP_SRC src/Variable.cpp
src/CellArray.cpp
src/File.cpp
src/Struct.cpp
src/StructArray.cpp)
src/StructArray.cpp
src/ExogenousConversions.cpp)

set(MATIOCPP_HDR include/matioCpp/Span.h
include/matioCpp/VectorIterator.h
include/matioCpp/ConversionUtilities.h
include/matioCpp/ExogenousConversions.h
include/matioCpp/EigenConversions.h
include/matioCpp/Variable.h
include/matioCpp/ForwardDeclarations.h
include/matioCpp/Vector.h
Expand All @@ -121,7 +148,10 @@ set(MATIOCPP_TPP include/matioCpp/impl/Vector.tpp
include/matioCpp/impl/MultiDimensionalArray.tpp
include/matioCpp/impl/Element.tpp
include/matioCpp/impl/StructArrayElement.tpp
include/matioCpp/impl/File.tpp)
include/matioCpp/impl/File.tpp
include/matioCpp/impl/EigenConversions.tpp
include/matioCpp/impl/ExogenousConversions.tpp
include/matioCpp/impl/ExogenousConversionHelpers.tpp)

source_group("Template Implementation Files" FILES ${MATIOCPP_TPP})

Expand Down Expand Up @@ -149,7 +179,13 @@ target_include_directories(matioCpp PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SO
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/Autogenerated>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")

target_link_libraries(matioCpp PUBLIC MATIO::MATIO)
target_link_libraries(matioCpp PUBLIC MATIO::MATIO visit_struct::visit_struct)
list(APPEND MATIOCPP_DEPENDENCIES MATIO visit_struct)

if (Eigen3_FOUND)
target_link_libraries(matioCpp PUBLIC Eigen3::Eigen)
list(APPEND MATIOCPP_DEPENDENCIES Eigen3)
endif()

target_compile_features(matioCpp PUBLIC cxx_std_14)

Expand Down Expand Up @@ -182,7 +218,7 @@ install_basic_package_files(${PROJECT_NAME}
COMPATIBILITY AnyNewerVersion
VARS_PREFIX ${PROJECT_NAME}
NO_CHECK_REQUIRED_COMPONENTS_MACRO
DEPENDENCIES MATIO
DEPENDENCIES ${MATIOCPP_DEPENDENCIES}
OVERRIDE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/share/matioCpp/cmake)
# Add the uninstall target
include(AddUninstallTarget)
Expand Down
67 changes: 67 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ The depencies are [``CMake``](https://cmake.org/) (minimum version 3.10) and [``
- macOS: ``brew install libmatio``
- Windows, via [``vcpkg``](https://github.com/microsoft/vcpkg): ``vcpkg install --triplet x64-windows matio``

[`Eigen`](https://eigen.tuxfamily.org/index.php) is an optional dependency. If available, some conversions are defined.

For running the tests, it is necessary to install [`Catch2`](https://github.com/catchorg/Catch2). Where supported, [``valgrind``](https://valgrind.org/) can be installed to check for memory leaks.

## Linux/macOS
Expand Down Expand Up @@ -109,6 +111,71 @@ file.write(testString);
```

It is possibile to convert common types to ``matioCpp`` types with the function ``matioCpp::make_variable``. Examples:
```c++
std::vector<double> stdVec = {1.0, 2.0, 3.0, 4.0, 5.0};
auto toMatioVec = matioCpp::make_variable("test", stdVec);

std::array<float,3> array = {1.0, 2.0, 3.0};
auto toMatioArray = matioCpp::make_variable("test", array);

int classicalArray[] = {1, 2, 3};
auto toMatioClassic = matioCpp::make_variable("test", matioCpp::make_span(classicalArray, 3));

std::string string("something");
auto toMatioString = matioCpp::make_variable("name", string);

std::vector<bool> vecOfBool = {true, false, true};
auto toVecofBool = matioCpp::make_variable("vecOfBool", vecOfBool);

auto matioDouble = matioCpp::make_variable("double", 5.0);

auto matioBool = matioCpp::make_variable("bool", true);

auto matioInt = matioCpp::make_variable("int", 2);

auto matioChar = matioCpp::make_variable("char", 'f');

std::vector<std::string> stringVector = {"Huey", "Dewey", "Louie"};
auto matioCell = matioCpp::make_variable("stringVector", stringVector);
```
If ``eigen`` is available, it is also possible to convert from and to ``eigen`` types:
```c++
matioCpp::Vector<double> vector("vector", 5);
Eigen::VectorXd eigenVec = matioCpp::to_eigen(vector);
matioCpp::MultiDimensionalArray<float> matioCppMatrix("matrix");
Eigen::MatrixXf toEigenMatrix = matioCpp::to_eigen(matioCppMatrix);
Eigen::Matrix3f eigenMatrix;
eigenMatrix << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0;
auto toMatioMatrix = matioCpp::make_variable("testMatrix", eigenMatrix);
Eigen::Vector3i eigenVec;
eigenVec << 2, 4, 6;
auto toMatioEigenVec = matioCpp::make_variable("testEigen", eigenVec);
```

``matioCpp`` also exploits [``visit_struct``](https://github.com/garbageslam/visit_struct) to parse C++ structs into ``matioCpp`` structs. Example:
```c++
struct testStruct
{
int i{1};
double d{2.0};
std::string s{"test"};
std::vector<double> stdVec = {1.0, 2.0, 3.0, 4.0, 5.0};
int* notSupported = nullptr;
std::vector<std::string> stringVector = {"Huey", "Dewey", "Louie"};
std::vector<bool> vecOfBool = {true, false, true};
};
VISITABLE_STRUCT(testStruct, i, d, s, stdVec, vecOfBool, stringVector);

//----------

testStruct s;
matioCpp::Struct automaticStruct = matioCpp::make_variable("testStruct", s);
```
# Known Limitations
- Complex arrays are not yet supported
- Cannot read timeseries from a ``.mat`` file (this is a ``matio`` limitation https://github.com/tbeu/matio/issues/99)
Expand Down
9 changes: 7 additions & 2 deletions cmake/Config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@
// This is an automatically generated file.
// Please DO NOT edit this file manually.

#ifndef MATIOCPP_CONFIG_H
#define MATIOCPP_CONFIG_H
/*
* Copyright (C) 2020 Fondazione Istituto Italiano di Tecnologia
*
* This software may be modified and distributed under the terms of the
* BSD-2-Clause license (https://opensource.org/licenses/BSD-2-Clause).
*/

#ifndef MATIOCPP_CONFIG_H
#define MATIOCPP_CONFIG_H

#define MATIOCPP_VER "@PROJECT_VERSION@"

#ifndef MATIOCPP_NO_EIGEN
#cmakedefine MATIOCPP_HAS_EIGEN
#endif

#endif // MATIOCPP_CONFIG_H
36 changes: 22 additions & 14 deletions include/matioCpp/ConversionUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,28 @@ template <typename Tp> struct get_type
static_assert (matioCpp::dependent_false<Tp>::value, "Unsupported type.");
static_assert (!std::is_same<Tp, bool>::value, "Use matioCpp::Logical instead of bool.");
};

#ifdef __APPLE__
using size_t_type = unsigned long;
#else
using size_t_type = uint64_t;
#endif

// specializations
template <> struct get_type<int8_t> { using type = int8_t; static inline ValueType valueType(){return ValueType::INT8;}; static inline std::string toString(){return "int8_t" ;};};
template <> struct get_type<uint8_t> { using type = uint8_t; static inline ValueType valueType(){return ValueType::UINT8;}; static inline std::string toString(){return "uint8_t" ;};};
template <> struct get_type<int16_t> { using type = int16_t; static inline ValueType valueType(){return ValueType::INT16;}; static inline std::string toString(){return "int16_t" ;};};
template <> struct get_type<uint16_t> { using type = uint16_t; static inline ValueType valueType(){return ValueType::UINT16;}; static inline std::string toString(){return "uint16_t" ;};};
template <> struct get_type<int32_t> { using type = int32_t; static inline ValueType valueType(){return ValueType::INT32;}; static inline std::string toString(){return "int32_t" ;};};
template <> struct get_type<uint32_t> { using type = uint32_t; static inline ValueType valueType(){return ValueType::UINT32;}; static inline std::string toString(){return "uint32_t" ;};};
template <> struct get_type<float> { using type = float; static inline ValueType valueType(){return ValueType::SINGLE;}; static inline std::string toString(){return "float" ;};};
template <> struct get_type<double> { using type = double; static inline ValueType valueType(){return ValueType::DOUBLE;}; static inline std::string toString(){return "double" ;};};
template <> struct get_type<int64_t> { using type = int64_t; static inline ValueType valueType(){return ValueType::INT64;}; static inline std::string toString(){return "int64_t" ;};};
template <> struct get_type<char> { using type = char; static inline ValueType valueType(){return ValueType::UTF8;}; static inline std::string toString(){return "char" ;};};
template <> struct get_type<char16_t> { using type = char16_t; static inline ValueType valueType(){return ValueType::UTF16;}; static inline std::string toString(){return "char16_t" ;};};
template <> struct get_type<char32_t> { using type = char32_t; static inline ValueType valueType(){return ValueType::UTF32;}; static inline std::string toString(){return "char32_t" ;};};
template <> struct get_type<Logical> { using type = uint8_t; static inline ValueType valueType(){return ValueType::LOGICAL;}; static inline std::string toString(){return "matioCpp::Logical" ;};};
template <> struct get_type<int8_t> { using type = int8_t; static inline ValueType valueType(){return ValueType::INT8;}; static inline std::string toString(){return "int8_t" ;};};
template <> struct get_type<uint8_t> { using type = uint8_t; static inline ValueType valueType(){return ValueType::UINT8;}; static inline std::string toString(){return "uint8_t" ;};};
template <> struct get_type<int16_t> { using type = int16_t; static inline ValueType valueType(){return ValueType::INT16;}; static inline std::string toString(){return "int16_t" ;};};
template <> struct get_type<uint16_t> { using type = uint16_t; static inline ValueType valueType(){return ValueType::UINT16;}; static inline std::string toString(){return "uint16_t" ;};};
template <> struct get_type<int32_t> { using type = int32_t; static inline ValueType valueType(){return ValueType::INT32;}; static inline std::string toString(){return "int32_t" ;};};
template <> struct get_type<uint32_t> { using type = uint32_t; static inline ValueType valueType(){return ValueType::UINT32;}; static inline std::string toString(){return "uint32_t" ;};};
template <> struct get_type<float> { using type = float; static inline ValueType valueType(){return ValueType::SINGLE;}; static inline std::string toString(){return "float" ;};};
template <> struct get_type<double> { using type = double; static inline ValueType valueType(){return ValueType::DOUBLE;}; static inline std::string toString(){return "double" ;};};
template <> struct get_type<int64_t> { using type = int64_t; static inline ValueType valueType(){return ValueType::INT64;}; static inline std::string toString(){return "int64_t" ;};};
template <> struct get_type<size_t_type> { using type = size_t_type; static inline ValueType valueType(){return ValueType::UINT64;}; static inline std::string toString(){return "size_t" ;};};
template <> struct get_type<char> { using type = char; static inline ValueType valueType(){return ValueType::UTF8;}; static inline std::string toString(){return "char" ;};};
template <> struct get_type<char16_t> { using type = char16_t; static inline ValueType valueType(){return ValueType::UTF16;}; static inline std::string toString(){return "char16_t" ;};};
template <> struct get_type<char32_t> { using type = char32_t; static inline ValueType valueType(){return ValueType::UTF32;}; static inline std::string toString(){return "char32_t" ;};};
template <> struct get_type<Logical> { using type = uint8_t; static inline ValueType valueType(){return ValueType::LOGICAL;}; static inline std::string toString(){return "matioCpp::Logical" ;};};

/**
* @brief Utility meta-function to check if a type is compatible with a std::string
Expand Down Expand Up @@ -123,7 +131,7 @@ bool is_convertible_to_primitive_type(matioCpp::ValueType type)
return std::is_same<T, int64_t>::value;
break;
case matioCpp::ValueType::UINT64:
return std::is_same<T, uint64_t>::value;
return std::is_same<T, size_t_type>::value;
break;
case matioCpp::ValueType::UTF8:
return (std::is_same<T, char>::value || std::is_same<T, uint8_t>::value);
Expand Down
Loading

0 comments on commit ed9b196

Please sign in to comment.