Skip to content

Commit

Permalink
Merge pull request #708 from dartsim/grey/cloneable_merging
Browse files Browse the repository at this point in the history
merge(~) feature for Composite State and Properties
  • Loading branch information
jslee02 committed Apr 28, 2016
2 parents 7e6c58c + 29f5fcb commit 716bc85
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 20 deletions.
26 changes: 21 additions & 5 deletions dart/common/Cloneable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,27 @@ class CloneableMap
/// Map-based move assignment operator
CloneableMap& operator=(MapType&& otherMap);

/// Copy the contents of another cloneable map into this one.
void copy(const CloneableMap& otherMap);

/// Copy the contents of a map into this one.
void copy(const MapType& otherMap);
/// Copy the contents of another cloneable map into this one. If merge is set
/// to false, then any fields in this map which are not present in the other
/// map will be erased; otherwise they will be kept. Setting merge to false
/// will make the contents of this map an exact duplicate of the other map.
void copy(const CloneableMap& otherMap, bool merge=false);

/// Copy the contents of a map into this one. If merge is set to false, then
/// any fields in this map which are not present in the other map will be
/// erased; otherwise they will be kept. Setting merge to false will make the
/// contents of this map an exact duplicate of the other map.
void copy(const MapType& otherMap, bool merge=false);

/// Merge the contents of another cloneable map into this one. If there are
/// any entries which both maps have, then the contents of otherMap will take
/// precedence. This is the same as calling copy(otherMap, true).
void merge(const CloneableMap& otherMap);

/// Merge the contents of another map into this one. If there are any entries
/// which both maps have, then the contents of otherMap will take precedence.
/// This is the same as calling copy(otherMap, true).
void merge(const MapType& otherMap);

/// Get the map that is being held
MapType& getMap();
Expand Down
65 changes: 50 additions & 15 deletions dart/common/detail/Cloneable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,14 +426,14 @@ CloneableMap<MapType>& CloneableMap<MapType>::operator=(

//==============================================================================
template <typename MapType>
void CloneableMap<MapType>::copy(const CloneableMap& otherMap)
void CloneableMap<MapType>::copy(const CloneableMap& otherMap, bool merge)
{
copy(otherMap.getMap());
copy(otherMap.getMap(), merge);
}

//==============================================================================
template <typename MapType>
void CloneableMap<MapType>::copy(const MapType& otherMap)
void CloneableMap<MapType>::copy(const MapType& otherMap, bool merge)
{
typename MapType::iterator receiver = mMap.begin();
typename MapType::const_iterator sender = otherMap.begin();
Expand All @@ -449,36 +449,71 @@ void CloneableMap<MapType>::copy(const MapType& otherMap)
}
else if( receiver->first == sender->first )
{
// We should copy the incoming object when possible so we can avoid the
// memory allocation overhead of cloning.
if(receiver->second)
receiver->second->copy(*sender->second);
else
receiver->second = sender->second->clone();
if(sender->second)
{
// If the sender has an object, we should copy it.
if(receiver->second)
// We should copy instead of cloning the incoming object when possible
// so we can avoid the memory allocation overhead of cloning.
receiver->second->copy(*sender->second);
else
receiver->second = sender->second->clone();
}
else if(!merge)
{
// If the sender has no object, we should clear this one.
receiver->second = nullptr;
}

++receiver;
++sender;
}
else if( receiver->first < sender->first )
{
// Clear this entry in the map, because it does not have an analog in the
// map that we are copying
receiver->second = nullptr;
if(!merge)
{
// Clear this entry in the map, because it does not have an analog in
// the map that we are copying
receiver->second = nullptr;
}
++receiver;
}
else
{
mMap[sender->first] = sender->second->clone();
if(sender->second)
{
// If receiver has a higher value, then the receiving map does not
// contain an entry for this entry of the sending map, and therefore the
// entry must be created.
mMap[sender->first] = sender->second->clone();
}
++sender;
}
}

while( mMap.end() != receiver )
if(!merge)
{
mMap.erase(receiver++);
while( mMap.end() != receiver )
{
mMap.erase(receiver++);
}
}
}

//==============================================================================
template <typename MapType>
void CloneableMap<MapType>::merge(const CloneableMap& otherMap)
{
copy(otherMap, true);
}

//==============================================================================
template <typename MapType>
void CloneableMap<MapType>::merge(const MapType& otherMap)
{
copy(otherMap, true);
}

//==============================================================================
template <typename MapType>
MapType& CloneableMap<MapType>::getMap()
Expand Down
5 changes: 5 additions & 0 deletions dart/common/detail/CompositeData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ class CompositeData : public CloneableMap<MapType>
return static_cast<Data&>(*it.first);
}

template <class AspectT>
bool has() const
{
return (get<AspectT>() != nullptr);
}
};

//==============================================================================
Expand Down
14 changes: 14 additions & 0 deletions unittests/testAspect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,20 @@ TEST(Aspect, StateAndProperties)
// The constructor arguments should match the type order
Composite::MakeState<DoubleAspect, IntAspect, CharAspect, FloatAspect>(
doubleState, intState, charState, floatState);

// ---- Test copying and merging ----
Composite::Properties c_properties_1(properties);
EXPECT_FALSE(c_properties_1.has<IntAspect>());

Composite::Properties c_properties_2;
c_properties_2.create<IntAspect>();
EXPECT_TRUE(c_properties_2.has<IntAspect>());

c_properties_2.merge(c_properties_1);
EXPECT_TRUE(c_properties_2.has<IntAspect>());

c_properties_2.copy(c_properties_1);
EXPECT_FALSE(c_properties_2.has<IntAspect>());
}

TEST(Aspect, Construction)
Expand Down

0 comments on commit 716bc85

Please sign in to comment.