Skip to content

Commit

Permalink
Merge pull request #30 from dic-iit/fix/FileTest
Browse files Browse the repository at this point in the history
Add String16, String32 and checks on other types of MAT files
  • Loading branch information
S-Dafarra committed Feb 1, 2021
2 parents 949f9e5 + 9e004a9 commit 960ed1b
Show file tree
Hide file tree
Showing 13 changed files with 409 additions and 34 deletions.
36 changes: 30 additions & 6 deletions include/matioCpp/ConversionUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,30 @@ template <> struct get_type<char16_t> { using type = char16_t; static inline Va
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
*/
template <typename T>
struct is_string_compatible : std::false_type { };
template<> struct is_string_compatible<char> : std::true_type { };
template<> struct is_string_compatible<uint8_t> : std::true_type { };

/**
* @brief Utility meta-function to check if a type is compatible with a std::u16string
*/
template <typename T>
struct is_string16_compatible : std::false_type { };
template<> struct is_string16_compatible<char16_t> : std::true_type { };
template<> struct is_string16_compatible<uint16_t> : std::true_type { };

/**
* @brief Utility meta-function to check if a type is compatible with a std::u32string
*/
template <typename T>
struct is_string32_compatible : std::false_type { };
template<> struct is_string32_compatible<char32_t> : std::true_type { };
template<> struct is_string32_compatible<uint32_t> : std::true_type { };

/**
* @brief Utility function to check if certain ValueType can be converted to a primitive type T.
* @param type The input ValueType to test.
Expand All @@ -75,19 +99,19 @@ bool is_convertible_to_primitive_type(matioCpp::ValueType type)
return std::is_same<T, int8_t>::value;
break;
case matioCpp::ValueType::UINT8:
return std::is_same<T, uint8_t>::value;
return (std::is_same<T, uint8_t>::value || std::is_same<T, char>::value);
break;
case matioCpp::ValueType::INT16:
return std::is_same<T, int16_t>::value;
break;
case matioCpp::ValueType::UINT16:
return std::is_same<T, uint16_t>::value;
return (std::is_same<T, uint16_t>::value || std::is_same<T, char16_t>::value);
break;
case matioCpp::ValueType::INT32:
return std::is_same<T, int32_t>::value;
break;
case matioCpp::ValueType::UINT32:
return std::is_same<T, uint32_t>::value;
return (std::is_same<T, uint32_t>::value || std::is_same<T, char32_t>::value);
break;
case matioCpp::ValueType::SINGLE:
return std::is_same<T, float>::value;
Expand All @@ -102,13 +126,13 @@ bool is_convertible_to_primitive_type(matioCpp::ValueType type)
return std::is_same<T, uint64_t>::value;
break;
case matioCpp::ValueType::UTF8:
return std::is_same<T, char>::value;
return (std::is_same<T, char>::value || std::is_same<T, uint8_t>::value);
break;
case matioCpp::ValueType::UTF16:
return std::is_same<T, char16_t>::value;
return (std::is_same<T, char16_t>::value || std::is_same<T, uint16_t>::value);
break;
case matioCpp::ValueType::UTF32:
return std::is_same<T, char32_t>::value;
return (std::is_same<T, char32_t>::value || std::is_same<T, uint32_t>::value);
break;
case matioCpp::ValueType::LOGICAL:
return std::is_same<T, matioCpp::Logical>::value;
Expand Down
4 changes: 2 additions & 2 deletions include/matioCpp/File.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ class matioCpp::File
* @note The it performs a shallow copy of the variable.
* @return True if successful.
*/
bool write(const Variable &variable);
bool write(const Variable &variable, matioCpp::Compression compression = matioCpp::Compression::None);

/**
* @brief Write a Variable to a file in a batch
Expand All @@ -177,7 +177,7 @@ class matioCpp::File
* @return True if successful.
*/
template <class iterator>
bool write(iterator begin, iterator end);
bool write(iterator begin, iterator end, matioCpp::Compression compression = matioCpp::Compression::None);

/**
* @brief Check if the file is open
Expand Down
13 changes: 13 additions & 0 deletions include/matioCpp/ForwardDeclarations.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ enum class FileVersion
Undefined /** @brief Undefined version */
};

/**
* @brief Compression type when writing to a file
*/
enum class Compression
{
None, /** @brief No compression. **/
zlib /** @brief Use zlib compression. **/
};

/**
* @brief The delete mode of matvar_t pointers.
*/
Expand Down Expand Up @@ -182,6 +191,10 @@ class Vector;

using String = Vector<char>;

using String16 = Vector<char16_t>;

using String32 = Vector<char32_t>;

template<typename T>
class MultiDimensionalArray;

Expand Down
22 changes: 21 additions & 1 deletion include/matioCpp/Variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,30 @@ class matioCpp::Variable
matioCpp::String asString();

/**
* @brief Cast the variable as a const Vector
* @brief Cast the variable as a const String
*/
const matioCpp::String asString() const;

/**
* @brief Cast the variable as a String16.
*/
matioCpp::String16 asString16();

/**
* @brief Cast the variable as a const String16
*/
const matioCpp::String16 asString16() const;

/**
* @brief Cast the variable as a String32.
*/
matioCpp::String32 asString32();

/**
* @brief Cast the variable as a const String32
*/
const matioCpp::String32 asString32() const;

/**
* @brief Cast the variable as a MultiDimensionalArray.
*
Expand Down
13 changes: 11 additions & 2 deletions include/matioCpp/Vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ class matioCpp::Vector : public matioCpp::Variable

using const_reverse_iterator =std::reverse_iterator<const_iterator>; /** The const reverse iterator type. **/

using string_input_type = typename std::conditional<matioCpp::is_string16_compatible<T>::value, std::u16string,
typename std::conditional<matioCpp::is_string32_compatible<T>::value, std::u32string, std::string>::type>::type; /** The type of string that can be used as initialization. **/

using string_output_type = typename std::conditional<matioCpp::is_string_compatible<T>::value, std::string,
typename std::conditional<matioCpp::is_string16_compatible<T>::value, std::u16string,
typename std::conditional<matioCpp::is_string32_compatible<T>::value, std::u32string, void>::type>::type>::type; /** The output type of the conversion to string. **/

/**
* @brief Default Constructor
* @note The name is set to "unnamed_vector".
Expand Down Expand Up @@ -74,6 +81,8 @@ class matioCpp::Vector : public matioCpp::Variable
*/
template<typename in = element_type,
typename = typename std::enable_if<!std::is_same<element_type, const char>::value &&
!std::is_same<element_type, const char16_t>::value &&
!std::is_same<element_type, const char32_t>::value &&
!std::is_same<value_type, bool>::value>::type>
Vector(const std::string& name, Span<const element_type> inputVector);

Expand All @@ -82,7 +91,7 @@ class matioCpp::Vector : public matioCpp::Variable
* @param name The name of the Vector
* @param inputString The input string.
*/
Vector(const std::string& name, const std::string& inputString);
Vector(const std::string& name, const string_input_type &inputString);

/**
* @brief Constructor
Expand Down Expand Up @@ -220,7 +229,7 @@ class matioCpp::Vector : public matioCpp::Variable
* @return A string that copies the internal data.
* @note This is available only if the type is char.
*/
std::string operator()() const;
string_output_type operator()() const;

/**
* @brief Access specified element.
Expand Down
4 changes: 2 additions & 2 deletions include/matioCpp/impl/File.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ const input &matioCpp::File::getVariable(const std::pair<key, input>& it)
}

template <class iterator>
bool matioCpp::File::write(iterator begin, iterator end)
bool matioCpp::File::write(iterator begin, iterator end, Compression compression)
{
for (iterator it = begin; it != end; ++it)
{
if (!write(getVariable(*it)))
if (!write(getVariable(*it), compression))
{
return false;
}
Expand Down
16 changes: 11 additions & 5 deletions include/matioCpp/impl/Vector.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,12 @@ matioCpp::Vector<T>::Vector(const std::string& name, Span<const typename matioCp
}

template <typename T>
matioCpp::Vector<T>::Vector(const std::string &name, const std::string &inputString)
matioCpp::Vector<T>::Vector(const std::string &name, const string_input_type &inputString)
{
static_assert (std::is_same<T, char>::value,"The assignement operator from a string is available only if the type of the vector is char");
static_assert (matioCpp::is_string_compatible<T>::value ||
matioCpp::is_string16_compatible<T>::value ||
matioCpp::is_string32_compatible<T>::value,
"The assignement operator from a string is available only if the type of the vector is char, char16_t, char32_t, uint8_t, uint16_t or uint32_t.");
size_t dimensions[] = {1, static_cast<size_t>(inputString.size())};
initializeVariable(name, VariableType::Vector, matioCpp::get_type<T>::valueType(), dimensions, (void*)inputString.c_str());
}
Expand Down Expand Up @@ -274,10 +277,13 @@ typename matioCpp::Vector<T>::value_type matioCpp::Vector<T>::operator()(typenam
}

template<typename T>
std::string matioCpp::Vector<T>::operator()() const
typename matioCpp::Vector<T>::string_output_type matioCpp::Vector<T>::operator()() const
{
static_assert (std::is_same<T, char>::value,"The operator () to convert to a string is available only if the type of the vector is char");
return std::string(data(), size());
static_assert (matioCpp::is_string_compatible<T>::value ||
matioCpp::is_string16_compatible<T>::value ||
matioCpp::is_string32_compatible<T>::value,
"The operator () to convert to a string is available only if the type of the vector is a char type or uint type.");
return matioCpp::Vector<T>::string_output_type((typename matioCpp::Vector<T>::string_output_type::value_type*) data(), size());
}

template<typename T>
Expand Down
5 changes: 0 additions & 5 deletions src/ConversionUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,6 @@ bool matioCpp::get_types_from_matvart(const matvar_t *input, matioCpp::VariableT
else if ((input->rank == 2) && ((input->dims[0] == 1) || (input->dims[1] == 1)))
{
outputVariableType = matioCpp::VariableType::Vector;

if (input->class_type == matio_classes::MAT_C_CHAR) //If it is a vector and the class type is char, then it is a string
{
outputValueType = matioCpp::ValueType::UTF8;
}
}
else
{
Expand Down
49 changes: 46 additions & 3 deletions src/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* BSD-2-Clause license (https://opensource.org/licenses/BSD-2-Clause).
*/

#define _CRT_SECURE_NO_WARNINGS //to silence the warning about c_time being unsafe

#include <matioCpp/File.h>
#include <time.h>
Expand Down Expand Up @@ -39,7 +40,7 @@ class matioCpp::File::Impl

if (!newPtr)
{
mode = matioCpp::FileMode::ReadOnly;
fileMode = matioCpp::FileMode::ReadOnly;
}
}

Expand Down Expand Up @@ -283,14 +284,22 @@ matioCpp::Variable matioCpp::File::read(const std::string &name) const
return matioCpp::Variable();
}

#if defined(_MSC_VER) && MATIO_VERSION < 1519
if (version() == matioCpp::FileVersion::MAT7_3)
{
std::cerr << "[ERROR][matioCpp::File::read] Reading to a 7.3 file on Windows with a matio version previous to 1.5.19 causes segfaults. The output will be an invalid Variable." << std::endl;
return matioCpp::Variable();
}
#endif

matvar_t *matVar = Mat_VarRead(m_pimpl->mat_ptr, name.c_str());

matioCpp::Variable output((matioCpp::SharedMatvar(matVar)));

return output;
}

bool matioCpp::File::write(const Variable &variable)
bool matioCpp::File::write(const Variable &variable, Compression compression)
{
if (!isOpen())
{
Expand All @@ -313,7 +322,41 @@ bool matioCpp::File::write(const Variable &variable)

SharedMatvar shallowCopy = SharedMatvar::GetMatvarShallowDuplicate(variable.toMatio()); // Shallow copy to remove const

bool success = Mat_VarWrite(m_pimpl->mat_ptr, shallowCopy.get(), matio_compression::MAT_COMPRESSION_NONE) == 0;
matio_compression matioCompression =
(compression == matioCpp::Compression::zlib) ? matio_compression::MAT_COMPRESSION_ZLIB : matio_compression::MAT_COMPRESSION_NONE;

if (version() == matioCpp::FileVersion::MAT4)
{
switch (variable.variableType())
{
case matioCpp::VariableType::Element:
break;
case matioCpp::VariableType::Vector:
break;
case matioCpp::VariableType::MultiDimensionalArray:
if (variable.dimensions().size() > 2)
{
std::cerr << "[ERROR][matioCpp::File::write] A MAT4 version does not support arrays with number of dimensions greater than 2." << std::endl;
return false;
}
break;
default:
std::cerr << "[ERROR][matioCpp::File::write] A MAT4 supports only element, vectors or matrices." << std::endl;
return false;
}

matioCpp::ValueType valueType = variable.valueType();

if ((valueType != matioCpp::ValueType::DOUBLE) && (valueType != matioCpp::ValueType::SINGLE) && (valueType != matioCpp::ValueType::LOGICAL)
&& (valueType != matioCpp::ValueType::UINT8) && (valueType != matioCpp::ValueType::INT32)
&& (valueType != matioCpp::ValueType::INT16) && (valueType != matioCpp::ValueType::UINT16))
{
std::cerr << "[ERROR][matioCpp::File::write] A MAT4 supports only variables of type LOGICAL, DOUBLE, SINGLE, UINT8, UINT16, INT16 and INT32." << std::endl;
return false;
}
}

bool success = Mat_VarWrite(m_pimpl->mat_ptr, shallowCopy.get(), matioCompression) == 0;

if (!success)
{
Expand Down
20 changes: 20 additions & 0 deletions src/Variable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,23 @@ const matioCpp::String matioCpp::Variable::asString() const
{
return matioCpp::Vector<char>(*m_handler);
}

matioCpp::String16 matioCpp::Variable::asString16()
{
return matioCpp::Vector<char16_t>(*m_handler);
}

const matioCpp::String16 matioCpp::Variable::asString16() const
{
return matioCpp::Vector<char16_t>(*m_handler);
}

matioCpp::String32 matioCpp::Variable::asString32()
{
return matioCpp::Vector<char32_t>(*m_handler);
}

const matioCpp::String32 matioCpp::Variable::asString32() const
{
return matioCpp::Vector<char32_t>(*m_handler);
}
Loading

0 comments on commit 960ed1b

Please sign in to comment.