Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 30 additions & 0 deletions Modules/Core/Common/include/itkMetaDataDictionary.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define itkMetaDataDictionary_h

#include "itkMetaDataObjectBase.h"
#include <algorithm> // For std::equal
#include <vector>
#include <map>
#include <string>
Expand Down Expand Up @@ -81,6 +82,35 @@ class ITKCommon_EXPORT MetaDataDictionary
// Destructor
virtual ~MetaDataDictionary();

/** Returns (metaDataDictionary1 == metaDataDictionary2). */
friend bool
operator==(const Self & lhs, const Self & rhs)
{
using KeyValuePair = MetaDataDictionaryMapType::value_type;

return (lhs.m_Dictionary == rhs.m_Dictionary) ||
((lhs.m_Dictionary != nullptr) && (rhs.m_Dictionary != nullptr) &&
(lhs.m_Dictionary->size() == rhs.m_Dictionary->size()) &&
std::equal(lhs.m_Dictionary->cbegin(),
lhs.m_Dictionary->cend(),
rhs.m_Dictionary->cbegin(),
[](const KeyValuePair & keyValuePair1, const KeyValuePair & keyValuePair2) {
const auto & value1 = keyValuePair1.second;
const auto & value2 = keyValuePair2.second;
return (keyValuePair1.first == keyValuePair2.first) &&
((value1 == value2) ||
((value1 != nullptr) && (value2 != nullptr) && (*value1 == *value2)));
}));
}

/** Returns (metaDataDictionary1 != metaDataDictionary2). */
friend bool
operator!=(const Self & lhs, const Self & rhs)
{
return !(lhs == rhs);
}


/** Returns a vector of keys to the key/value entries in the
* dictionary. Iterate through the dictionary using these keys.
*/
Expand Down
22 changes: 22 additions & 0 deletions Modules/Core/Common/include/itkMetaDataObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,33 @@ class ITK_TEMPLATE_EXPORT MetaDataObject : public MetaDataObjectBase
void
Print(std::ostream & os) const override;

/** Returns (metaDataObject1 == metaDataObject2). */
friend bool
operator==(const Self & lhs, const Self & rhs)
{
return lhs.m_MetaDataObjectValue == rhs.m_MetaDataObjectValue;
}

/** Returns (metaDataObject1 != metaDataObject2). */
friend bool
operator!=(const Self & lhs, const Self & rhs)
{
return !(lhs == rhs);
}

protected:
MetaDataObject() = default;
~MetaDataObject() override = default;

private:
/** Internal helper function used to implement operator== for MetaDataObjectBase. */
bool
Equal(const MetaDataObjectBase & metaDataObjectBase) const override
{
const auto metaDataObject = dynamic_cast<const Self *>(&metaDataObjectBase);
return (metaDataObject != nullptr) && (*this == *metaDataObject);
}

/**
* A variable to store this derived type.
* \author Hans J. Johnson
Expand Down
19 changes: 19 additions & 0 deletions Modules/Core/Common/include/itkMetaDataObjectBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ class ITKCommon_EXPORT MetaDataObjectBase : public LightObject
virtual const std::type_info &
GetMetaDataObjectTypeInfo() const;

/** Returns (metaDataBase1 == metaDataBase2). */
friend bool
operator==(const Self & lhs, const Self & rhs)
{
return lhs.Equal(rhs);
}

/** Returns (metaDataBase1 != metaDataBase2). */
friend bool
operator!=(const Self & lhs, const Self & rhs)
{
return !(lhs == rhs);
}


/**
* Defines the default behavior for printing out this element
* \param os An output stream
Expand All @@ -82,6 +97,10 @@ class ITKCommon_EXPORT MetaDataObjectBase : public LightObject
protected:
MetaDataObjectBase();
~MetaDataObjectBase() override;

private:
virtual bool
Equal(const MetaDataObjectBase &) const = 0;
};
} // namespace itk

Expand Down
50 changes: 50 additions & 0 deletions Modules/Core/Common/test/itkMetaDataDictionaryGTest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,53 @@ TEST(MetaDataDictionary, CopyOnWrite)
EXPECT_EQ(f, 1.0f);
}
}


TEST(MetaDataDictionary, Equal)
{
const auto expectEqual = [](const itk::MetaDataDictionary & object1, const itk::MetaDataDictionary & object2) {
// Test that equal objects can be used as arguments to GoogleTest EXPECT_EQ.
EXPECT_EQ(object1, object2);
EXPECT_EQ(object2, object1);

// Test symmetry, as well as consistency between equal and unequal.
EXPECT_TRUE(object1 == object2);
EXPECT_TRUE(object2 == object1);
EXPECT_FALSE(object1 != object2);
EXPECT_FALSE(object2 != object1);
};

const auto expectUnequal = [](const itk::MetaDataDictionary & object1, const itk::MetaDataDictionary & object2) {
// Test that unequal objects can be used as arguments to GoogleTest EXPECT_NE.
EXPECT_NE(object1, object2);
EXPECT_NE(object2, object1);

// Test symmetry, as well as consistency between equal and unequal.
EXPECT_TRUE(object1 != object2);
EXPECT_TRUE(object2 != object1);
EXPECT_FALSE(object1 == object2);
EXPECT_FALSE(object2 == object1);
};

const itk::MetaDataDictionary defaultMetaDataDictionary{};

expectEqual(defaultMetaDataDictionary, {});

const auto createMetaDataDictionary = [](const int value) {
itk::MetaDataDictionary metaDataDictionary;
itk::EncapsulateMetaData(metaDataDictionary, "key", value);
return metaDataDictionary;
};

const auto metaDataDictionary1 = createMetaDataDictionary(1);
const auto metaDataDictionary2 = createMetaDataDictionary(2);

expectEqual(metaDataDictionary1, metaDataDictionary1);
expectEqual(metaDataDictionary2, metaDataDictionary2);
expectEqual(metaDataDictionary1, createMetaDataDictionary(1));
expectEqual(metaDataDictionary2, createMetaDataDictionary(2));

expectUnequal(metaDataDictionary1, metaDataDictionary2);
expectUnequal(metaDataDictionary1, defaultMetaDataDictionary);
expectUnequal(metaDataDictionary2, defaultMetaDataDictionary);
}