Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds reflection and conversions from common types #55

Merged
merged 22 commits into from
Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8990b70
Added test case to check if a span can be constructed automatically w…
S-Dafarra Dec 9, 2021
69c1194
Added ExogenousConversions, including Eigen
S-Dafarra Mar 24, 2022
da83f9c
Added more sophisticated conversions from iterators.
S-Dafarra Mar 24, 2022
f19882e
Attempt to fix macOS failure.
S-Dafarra Mar 24, 2022
685c33c
Yet another attempt to fix macOS failure.
S-Dafarra Mar 24, 2022
c4f7aa9
Updated ci to test windows only with conda and added eigen only in co…
S-Dafarra Mar 24, 2022
3030863
Inverted the parameters when calling make_variable.
S-Dafarra Mar 24, 2022
4c81bec
Bumped version
S-Dafarra Mar 24, 2022
2969d17
Moved non-template conversions to dedicated cpp file.
S-Dafarra Mar 24, 2022
8a024f9
First version using visit_struct to automatically convert structs to …
S-Dafarra Mar 25, 2022
bf7b2d1
Attempt to fix windows issues in the tests related to the comparison …
S-Dafarra Mar 25, 2022
459f1f5
Using FetchContent to retrieve visit_struct
S-Dafarra Mar 25, 2022
1485168
Improved README to consider exogenous conversions.
S-Dafarra Mar 25, 2022
75fffef
Updated CHANGELOG
S-Dafarra Mar 25, 2022
f1e54e5
Removed leftover from CMakeLists
S-Dafarra Mar 25, 2022
90f3930
Added utility metafunction to check if make_variable is callable.
S-Dafarra Mar 28, 2022
6aa0a49
Added template utility for getting the output type of make_variable.
S-Dafarra Mar 31, 2022
7ededb4
Added possibility to get Element as span.
S-Dafarra Mar 31, 2022
5b13309
Added conversion for size_t
S-Dafarra Mar 31, 2022
3b622a7
Attempt to fix macOS failure when using size_t.
S-Dafarra Mar 31, 2022
0923a53
Yet another attempt to fix macOS failure with size_t.
S-Dafarra Mar 31, 2022
a94caa1
Added static assert to check if all the struct fields are compatible.
S-Dafarra Apr 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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