Remove element of Property::Map by the specified key.
[platform/core/uifw/dali-core.git] / dali / public-api / object / property-map.cpp
index 675d910..579ec48 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 namespace Dali
 {
-
 namespace
 {
-typedef std::vector< StringValuePair > StringValueContainer;
+typedef std::vector<StringValuePair> StringValueContainer;
 
-typedef std::pair< Property::Index, Property::Value > IndexValuePair;
-typedef std::vector< IndexValuePair > IndexValueContainer;
+using IndexValuePair      = std::pair<Property::Index, Property::Value>;
+using IndexValueContainer = std::vector<IndexValuePair>;
 
 }; // unnamed namespace
 
-
 struct Property::Map::Impl
 {
   StringValueContainer mStringValueContainer;
-  IndexValueContainer mIndexValueContainer;
+  IndexValueContainer  mIndexValueContainer;
 };
 
 Property::Map::Map()
-: mImpl( new Impl )
+: mImpl(new Impl)
+{
+}
+
+Property::Map::Map(const std::initializer_list<KeyValuePair>& values)
+: Map()
 {
+  for(auto&& value : values)
+  {
+    const auto& key = value.first;
+    switch(key.type)
+    {
+      case Property::Key::INDEX:
+      {
+        Property::Map::Insert(key.indexKey, value.second);
+        break;
+      }
+      case Property::Key::STRING:
+      {
+        Property::Map::Insert(key.stringKey, value.second);
+        break;
+      }
+    }
+  }
 }
 
-Property::Map::Map( const Property::Map& other )
-: mImpl( new Impl )
+Property::Map::Map(const Property::Map& other)
+: mImpl(new Impl)
 {
   mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
-  mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
+  mImpl->mIndexValueContainer  = other.mImpl->mIndexValueContainer;
+}
+
+Property::Map::Map(Property::Map&& other)
+: mImpl(other.mImpl)
+{
+  other.mImpl = nullptr;
 }
 
 Property::Map::~Map()
@@ -62,189 +88,227 @@ Property::Map::~Map()
 
 Property::Map::SizeType Property::Map::Count() const
 {
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
   return mImpl->mStringValueContainer.size() + mImpl->mIndexValueContainer.size();
 }
 
 bool Property::Map::Empty() const
 {
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
   return mImpl->mStringValueContainer.empty() && mImpl->mIndexValueContainer.empty();
 }
 
-void Property::Map::Insert( const char* key, const Value& value )
+void Property::Map::Insert(std::string key, Value value)
 {
-  mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) );
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+  mImpl->mStringValueContainer.push_back(std::make_pair(std::move(key), std::move(value)));
 }
 
-void Property::Map::Insert( const std::string& key, const Value& value )
+void Property::Map::Insert(Property::Index key, Value value)
 {
-  mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) );
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+  mImpl->mIndexValueContainer.push_back(std::make_pair(key, std::move(value)));
 }
 
-void Property::Map::Insert( Property::Index key, const Value& value )
-{
-  mImpl->mIndexValueContainer.push_back( std::make_pair( key, value ) );
-}
-
-Property::Value& Property::Map::GetValue( SizeType position ) const
+Property::Value& Property::Map::GetValue(SizeType position) const
 {
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
   SizeType numStringKeys = mImpl->mStringValueContainer.size();
   SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
-  DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
+  DALI_ASSERT_ALWAYS(position < (numStringKeys + numIndexKeys) && "position out-of-bounds");
 
-  if( position < numStringKeys )
+  if(position < numStringKeys)
   {
-    return mImpl->mStringValueContainer[ position ].second;
+    return mImpl->mStringValueContainer[position].second;
   }
   else
   {
-    return mImpl->mIndexValueContainer[ position-numStringKeys ].second;
+    return mImpl->mIndexValueContainer[position - numStringKeys].second;
   }
 }
 
-const std::string& Property::Map::GetKey( SizeType position ) const
+const std::string& Property::Map::GetKey(SizeType position) const
 {
-  DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetKey() is deprecated and will be removed from next release.\n" );
+  DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetKey() is deprecated and will be removed from next release.\n");
 
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
   SizeType numStringKeys = mImpl->mStringValueContainer.size();
-  DALI_ASSERT_ALWAYS( position < numStringKeys && "position out-of-bounds" );
+  DALI_ASSERT_ALWAYS(position < numStringKeys && "position out-of-bounds");
 
-  return mImpl->mStringValueContainer[ position ].first;
+  return mImpl->mStringValueContainer[position].first;
 }
 
-Property::Key Property::Map::GetKeyAt( SizeType position ) const
+Property::Key Property::Map::GetKeyAt(SizeType position) const
 {
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
   SizeType numStringKeys = mImpl->mStringValueContainer.size();
   SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
-  DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
+  DALI_ASSERT_ALWAYS(position < (numStringKeys + numIndexKeys) && "position out-of-bounds");
 
-  if( position < numStringKeys )
+  if(position < numStringKeys)
   {
-    Key key(mImpl->mStringValueContainer[ position ].first);
+    Key key(mImpl->mStringValueContainer[position].first);
     return key;
   }
   else
   {
-    Key key( mImpl->mIndexValueContainer[ position-numStringKeys ].first );
+    Key key(mImpl->mIndexValueContainer[position - numStringKeys].first);
     return key;
   }
 }
 
-StringValuePair& Property::Map::GetPair( SizeType position ) const
+StringValuePair& Property::Map::GetPair(SizeType position) const
 {
-  DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetPair() is deprecated and will be removed from next release.\n" );
+  DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetPair() is deprecated and will be removed from next release.\n");
+
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
 
   SizeType numStringKeys = mImpl->mStringValueContainer.size();
 
-  DALI_ASSERT_ALWAYS( position < ( numStringKeys ) && "position out-of-bounds" );
+  DALI_ASSERT_ALWAYS(position < (numStringKeys) && "position out-of-bounds");
 
-  return mImpl->mStringValueContainer[ position ];
+  return mImpl->mStringValueContainer[position];
 }
 
-KeyValuePair Property::Map::GetKeyValue( SizeType position ) const
+KeyValuePair Property::Map::GetKeyValue(SizeType position) const
 {
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
   SizeType numStringKeys = mImpl->mStringValueContainer.size();
   SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
 
-  DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
+  DALI_ASSERT_ALWAYS(position < (numStringKeys + numIndexKeys) && "position out-of-bounds");
 
-  if( position < numStringKeys )
+  if(position < numStringKeys)
   {
-    Key key(mImpl->mStringValueContainer[ position ].first);
-    KeyValuePair keyValue(key, mImpl->mStringValueContainer[ position ].second );
+    Key          key(mImpl->mStringValueContainer[position].first);
+    KeyValuePair keyValue(key, mImpl->mStringValueContainer[position].second);
     return keyValue;
   }
   else
   {
-    Key key( mImpl->mIndexValueContainer[ position-numStringKeys ].first );
-    KeyValuePair keyValue(key, mImpl->mIndexValueContainer[ position-numStringKeys ].second );
-    return keyValue;
+    return mImpl->mIndexValueContainer[position - numStringKeys];
   }
 }
 
-Property::Value* Property::Map::Find( const char* key ) const
+Property::Value* Property::Map::Find(std::string_view key) const
 {
-  for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  for(auto&& iter : mImpl->mStringValueContainer)
   {
-    if ( iter->first == key )
+    if(key == iter.first)
     {
-      return &iter->second;
+      return &iter.second;
     }
   }
-  return NULL; // Not found
+  return nullptr; // Not found
 }
 
-Property::Value* Property::Map::Find( const std::string& key ) const
+Property::Value* Property::Map::Find(Property::Index key) const
 {
-  return Find( key.c_str() );
-}
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
 
-Property::Value* Property::Map::Find( Property::Index key ) const
-{
-  for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
+  for(auto&& iter : mImpl->mIndexValueContainer)
   {
-    if ( iter->first == key )
+    if(iter.first == key)
     {
-      return &iter->second;
+      return &iter.second;
     }
   }
-  return NULL; // Not found
+  return nullptr; // Not found
 }
 
-Property::Value* Property::Map::Find( Property::Index indexKey, const std::string& stringKey ) const
+Property::Value* Property::Map::Find(Property::Index indexKey, std::string_view stringKey) const
 {
-  Property::Value* valuePtr = Find( indexKey );
-  if( !valuePtr )
+  Property::Value* valuePtr = Find(indexKey);
+  if(!valuePtr)
   {
-    valuePtr = Find( stringKey );
+    valuePtr = Find(stringKey);
   }
   return valuePtr;
 }
 
-Property::Value* Property::Map::Find( const std::string& key, Property::Type type ) const
+Property::Value* Property::Map::Find(std::string_view key, Property::Type type) const
 {
-  for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  for(auto&& iter : mImpl->mStringValueContainer)
   {
-    if( (iter->second.GetType() == type) && (iter->first == key) )
+    if((iter.second.GetType() == type) && (key == iter.first))
     {
-      return &iter->second;
+      return &iter.second;
     }
   }
-  return NULL; // Not found
+  return nullptr; // Not found
 }
 
-Property::Value* Property::Map::Find( Property::Index key, Property::Type type ) const
+Property::Value* Property::Map::Find(Property::Index key, Property::Type type) const
 {
-  for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  for(auto&& iter : mImpl->mIndexValueContainer)
   {
-    if( (iter->second.GetType() == type) && (iter->first == key) )
+    if((iter.second.GetType() == type) && (iter.first == key))
     {
-      return &iter->second;
+      return &iter.second;
     }
   }
-  return NULL; // Not found
+  return nullptr; // Not found
 }
 
 void Property::Map::Clear()
 {
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
   mImpl->mStringValueContainer.clear();
   mImpl->mIndexValueContainer.clear();
 }
 
-void Property::Map::Merge( const Property::Map& from )
+bool Property::Map::Remove(Property::Index key)
 {
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  auto iter = std::find_if(mImpl->mIndexValueContainer.begin(), mImpl->mIndexValueContainer.end(), [key](const IndexValuePair& element) { return element.first == key; });
+  if(iter != mImpl->mIndexValueContainer.end())
+  {
+    mImpl->mIndexValueContainer.erase(iter);
+    return true;
+  }
+  return false;
+}
+
+bool Property::Map::Remove(std::string_view key)
+{
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  auto iter = std::find_if(mImpl->mStringValueContainer.begin(), mImpl->mStringValueContainer.end(), [key](const StringValuePair& element) { return element.first == key; });
+  if(iter != mImpl->mStringValueContainer.end())
+  {
+    mImpl->mStringValueContainer.erase(iter);
+    return true;
+  }
+  return false;
+}
+
+void Property::Map::Merge(const Property::Map& from)
+{
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
   // Ensure we're not attempting to merge with ourself
-  if ( this != &from )
+  if(this != &from)
   {
-    if ( Count() )
+    if(Count())
     {
-      for ( StringValueContainer::const_iterator iter = from.mImpl->mStringValueContainer.begin(), endIter = from.mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
+      for(auto&& iter : from.mImpl->mStringValueContainer)
       {
-        (*this)[iter->first] = iter->second;
+        (*this)[iter.first] = iter.second;
       }
 
-      for ( IndexValueContainer::const_iterator iter = from.mImpl->mIndexValueContainer.begin(), endIter = from.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
+      for(auto&& iter : from.mImpl->mIndexValueContainer)
       {
-        (*this)[iter->first] = iter->second;
+        (*this)[iter.first] = iter.second;
       }
     }
     else
@@ -255,97 +319,119 @@ void Property::Map::Merge( const Property::Map& from )
   }
 }
 
-const Property::Value& Property::Map::operator[]( const std::string& key ) const
+const Property::Value& Property::Map::operator[](std::string_view key) const
 {
-  for ( StringValueContainer::const_iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  for(auto&& iter : mImpl->mStringValueContainer)
   {
-    if ( iter->first == key )
+    if(iter.first == key)
     {
-      return iter->second;
+      return iter.second;
     }
   }
 
-  DALI_ASSERT_ALWAYS( ! "Invalid Key" );
+  DALI_ASSERT_ALWAYS(!"Invalid Key");
 }
 
-Property::Value& Property::Map::operator[]( const std::string& key )
+Property::Value& Property::Map::operator[](std::string_view key)
 {
-  for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  for(auto&& iter : mImpl->mStringValueContainer)
   {
-    if ( iter->first == key )
+    if(iter.first == key)
     {
-      return iter->second;
+      return iter.second;
     }
   }
 
   // Create and return reference to new value
-  mImpl->mStringValueContainer.push_back( std::make_pair( key, Property::Value() ) );
-  return (mImpl->mStringValueContainer.end() - 1)->second;
+  mImpl->mStringValueContainer.push_back(std::make_pair(std::string(key), Property::Value()));
+  return mImpl->mStringValueContainer.back().second;
 }
 
-const Property::Value& Property::Map::operator[]( Property::Index key ) const
+const Property::Value& Property::Map::operator[](Property::Index key) const
 {
-  for ( IndexValueContainer::const_iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  for(auto&& iter : mImpl->mIndexValueContainer)
   {
-    if ( iter->first == key )
+    if(iter.first == key)
     {
-      return iter->second;
+      return iter.second;
     }
   }
 
-  DALI_ASSERT_ALWAYS( ! "Invalid Key" );
+  DALI_ASSERT_ALWAYS(!"Invalid Key");
 }
 
-Property::Value& Property::Map::operator[]( Property::Index key )
+Property::Value& Property::Map::operator[](Property::Index key)
 {
-  for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  for(auto&& iter : mImpl->mIndexValueContainer)
   {
-    if ( iter->first == key )
+    if(iter.first == key)
     {
-      return iter->second;
+      return iter.second;
     }
   }
 
   // Create and return reference to new value
-  mImpl->mIndexValueContainer.push_back( std::make_pair( key, Property::Value() ) );
-  return (mImpl->mIndexValueContainer.end() - 1)->second;
+  mImpl->mIndexValueContainer.push_back(std::make_pair(key, Property::Value()));
+  return mImpl->mIndexValueContainer.back().second;
 }
 
-Property::Map& Property::Map::operator=( const Property::Map& other )
+Property::Map& Property::Map::operator=(const Property::Map& other)
 {
-  if( this != &other )
+  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
+
+  if(this != &other)
   {
-    delete mImpl;
-    mImpl = new Impl;
     mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
-    mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
+    mImpl->mIndexValueContainer  = other.mImpl->mIndexValueContainer;
   }
   return *this;
 }
 
-std::ostream& operator<<( std::ostream& stream, const Property::Map& map )
+Property::Map& Property::Map::operator=(Property::Map&& other)
+{
+  if(this != &other)
+  {
+    delete mImpl;
+    mImpl       = other.mImpl;
+    other.mImpl = nullptr;
+  }
+  return *this;
+}
+
+std::ostream& operator<<(std::ostream& stream, const Property::Map& map)
 {
   stream << "Map(" << map.Count() << ") = {";
 
-  int32_t count = 0;
-  // Output the String-Value pairs
-  for ( StringValueContainer::iterator iter = map.mImpl->mStringValueContainer.begin(), endIter = map.mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
+  if(map.mImpl)
   {
-    if( count++ > 0 )
+    int32_t count = 0;
+    // Output the String-Value pairs
+    for(auto&& iter : map.mImpl->mStringValueContainer)
     {
-      stream<<", ";
+      if(count++ > 0)
+      {
+        stream << ", ";
+      }
+      stream << iter.first << ":" << iter.second;
     }
-    stream<< iter->first << ":"<<iter->second;
-  }
 
-  // Output the Index-Value pairs
-  for ( IndexValueContainer::iterator iter = map.mImpl->mIndexValueContainer.begin(), endIter = map.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
-  {
-    if( count++ > 0 )
+    // Output the Index-Value pairs
+    for(auto&& iter : map.mImpl->mIndexValueContainer)
     {
-      stream<<", ";
+      if(count++ > 0)
+      {
+        stream << ", ";
+      }
+      stream << iter.first << ":" << iter.second;
     }
-    stream<< iter->first << ":"<<iter->second;
   }
 
   stream << "}";