Add Vector::removeFirstMatching() / removeAllMatching() methods taking lambda functions
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 8 Feb 2015 02:28:48 +0000 (02:28 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 8 Feb 2015 02:28:48 +0000 (02:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=141321

Reviewed by Darin Adler.

Source/JavaScriptCore:

Use new Vector::removeFirstMatching() / removeAllMatching() methods.

Source/WebCore:

Use new Vector::removeFirstMatching() / removeAllMatching() methods.

Source/WebKit/win:

Use new Vector::removeFirstMatching() / removeAllMatching() methods.

Source/WebKit2:

Use new Vector::removeFirstMatching() / removeAllMatching() methods.

Source/WTF:

Add Vector::removeFirstMatching() / removeAllMatching() methods taking
lambda functions to match the element(s) to remove. This simplifies the
code a bit. Vector::removeAllMatching() is also more efficient than the
manual removal alternative.

* wtf/Vector.h:

Tools:

Use new Vector::removeFirstMatching() / removeAllMatching() methods.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@179791 268f45cc-cd09-0410-ab3c-d52691b4dbfc

23 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/profiler/ProfileNode.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/Vector.h
Source/WebCore/ChangeLog
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSValueList.cpp
Source/WebCore/css/MediaList.cpp
Source/WebCore/css/MediaQueryMatcher.cpp
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/EventListenerMap.cpp
Source/WebCore/dom/Node.cpp
Source/WebCore/html/parser/HTMLTreeBuilder.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp
Source/WebCore/svg/animation/SVGSMILElement.cpp
Source/WebKit/win/ChangeLog
Source/WebKit/win/WebNotificationCenter.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp

index de0b699..983628b 100644 (file)
@@ -1,3 +1,12 @@
+2015-02-07  Chris Dumez  <cdumez@apple.com>
+
+        Add Vector::removeFirstMatching() / removeAllMatching() methods taking lambda functions
+        https://bugs.webkit.org/show_bug.cgi?id=141321
+
+        Reviewed by Darin Adler.
+
+        Use new Vector::removeFirstMatching() / removeAllMatching() methods.
+
 2015-02-06  Filip Pizlo  <fpizlo@apple.com>
 
         DFG SSA shouldn't have SetArgument nodes
index 265cddd..9bcf375 100644 (file)
@@ -75,12 +75,9 @@ void ProfileNode::removeChild(ProfileNode* node)
     if (!node)
         return;
 
-    for (size_t i = 0; i < m_children.size(); ++i) {
-        if (*node == m_children[i].get()) {
-            m_children.remove(i);
-            break;
-        }
-    }
+    m_children.removeFirstMatching([node] (const RefPtr<ProfileNode>& current) {
+        return *node == current.get();
+    });
 
 #ifndef NDEBUG
     size_t size = m_children.size();
index ee50a37..83bb6e7 100644 (file)
@@ -1,3 +1,17 @@
+2015-02-07  Chris Dumez  <cdumez@apple.com>
+
+        Add Vector::removeFirstMatching() / removeAllMatching() methods taking lambda functions
+        https://bugs.webkit.org/show_bug.cgi?id=141321
+
+        Reviewed by Darin Adler.
+
+        Add Vector::removeFirstMatching() / removeAllMatching() methods taking
+        lambda functions to match the element(s) to remove. This simplifies the
+        code a bit. Vector::removeAllMatching() is also more efficient than the
+        manual removal alternative.
+
+        * wtf/Vector.h:
+
 2015-02-06  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r179743.
index a4c4359..7d842a8 100644 (file)
@@ -736,7 +736,9 @@ public:
     void remove(size_t position);
     void remove(size_t position, size_t length);
     template<typename U> bool removeFirst(const U&);
+    template<typename MatchFunction> bool removeFirstMatching(const MatchFunction&);
     template<typename U> unsigned removeAll(const U&);
+    template<typename MatchFunction> unsigned removeAllMatching(const MatchFunction&);
 
     void removeLast() 
     {
@@ -1314,10 +1316,20 @@ template<typename T, size_t inlineCapacity, typename OverflowHandler>
 template<typename U>
 inline bool Vector<T, inlineCapacity, OverflowHandler>::removeFirst(const U& value)
 {
-    size_t index = find(value);
-    if (index != notFound) {
-        remove(index);
-        return true;
+    return removeFirstMatching([&value] (const T& current) {
+        return current == value;
+    });
+}
+
+template<typename T, size_t inlineCapacity, typename OverflowHandler>
+template<typename MatchFunction>
+inline bool Vector<T, inlineCapacity, OverflowHandler>::removeFirstMatching(const MatchFunction& matches)
+{
+    for (size_t i = 0; i < size(); ++i) {
+        if (matches(at(i))) {
+            remove(i);
+            return true;
+        }
     }
     return false;
 }
@@ -1326,11 +1338,20 @@ template<typename T, size_t inlineCapacity, typename OverflowHandler>
 template<typename U>
 inline unsigned Vector<T, inlineCapacity, OverflowHandler>::removeAll(const U& value)
 {
+    return removeAllMatching([&value] (const T& current) {
+        return current == value;
+    });
+}
+
+template<typename T, size_t inlineCapacity, typename OverflowHandler>
+template<typename MatchFunction>
+inline unsigned Vector<T, inlineCapacity, OverflowHandler>::removeAllMatching(const MatchFunction& matches)
+{
     iterator holeBegin = end();
     iterator holeEnd = end();
     unsigned matchCount = 0;
     for (auto it = begin(), itEnd = end(); it != itEnd; ++it) {
-        if (*it == value) {
+        if (matches(*it)) {
             if (holeBegin == end())
                 holeBegin = it;
             else if (holeEnd != it) {
index a080194..37fbe50 100644 (file)
@@ -1,3 +1,12 @@
+2015-02-07  Chris Dumez  <cdumez@apple.com>
+
+        Add Vector::removeFirstMatching() / removeAllMatching() methods taking lambda functions
+        https://bugs.webkit.org/show_bug.cgi?id=141321
+
+        Reviewed by Darin Adler.
+
+        Use new Vector::removeFirstMatching() / removeAllMatching() methods.
+
 2015-02-07  Darin Adler  <darin@apple.com>
 
         Stop dispatching events to with SVGElementInstance objects as their targets
index 48a6673..62b8790 100644 (file)
@@ -12077,14 +12077,9 @@ void CSSParser::endDeclarationsForMarginBox()
 void CSSParser::deleteFontFaceOnlyValues()
 {
     ASSERT(m_hasFontFaceOnlyValues);
-    for (unsigned i = 0; i < m_parsedProperties.size();) {
-        CSSProperty& property = m_parsedProperties[i];
-        if (property.id() == CSSPropertyFontVariant && property.value()->isValueList()) {
-            m_parsedProperties.remove(i);
-            continue;
-        }
-        ++i;
-    }
+    m_parsedProperties.removeAllMatching([] (const CSSProperty& property) {
+        return property.id() == CSSPropertyFontVariant && property.value()->isValueList();
+    });
 }
 
 PassRefPtr<StyleKeyframe> CSSParser::createKeyframe(CSSParserValueList& keys)
index 911844e..8ce69ca 100644 (file)
@@ -50,21 +50,15 @@ CSSValueList::CSSValueList(CSSParserValueList& parserValues)
     }
 }
 
-bool CSSValueList::removeAll(CSSValue* val)
+bool CSSValueList::removeAll(CSSValue* value)
 {
     // FIXME: Why even take a pointer?
-    if (!val)
+    if (!value)
         return false;
 
-    bool found = false;
-    for (unsigned i = 0; i < m_values.size(); ++i) {
-        if (m_values[i].get().equals(*val)) {
-            m_values.remove(i);
-            found = true;
-        }
-    }
-
-    return found;
+    return m_values.removeAllMatching([value] (const Ref<CSSValue>& current) {
+        return current->equals(*value);
+    }) > 0;
 }
 
 bool CSSValueList::hasValue(CSSValue* val) const
index ee66712..37627da 100644 (file)
@@ -185,14 +185,9 @@ bool MediaQuerySet::remove(const String& queryStringToRemove)
     if (!parsedQuery)
         return false;
     
-    for (size_t i = 0; i < m_queries.size(); ++i) {
-        MediaQuery* query = m_queries[i].get();
-        if (*query == *parsedQuery) {
-            m_queries.remove(i);
-            return true;
-        }
-    }
-    return false;
+    return m_queries.removeFirstMatching([&parsedQuery] (const std::unique_ptr<MediaQuery>& query) {
+        return *query == *parsedQuery;
+    });
 }
 
 void MediaQuerySet::addMediaQuery(std::unique_ptr<MediaQuery> mediaQuery)
index db6bfb7..eda1d2f 100644 (file)
@@ -130,12 +130,9 @@ void MediaQueryMatcher::removeListener(MediaQueryListListener* listener, MediaQu
     if (!m_document)
         return;
 
-    for (size_t i = 0; i < m_listeners.size(); ++i) {
-        if (*m_listeners[i]->listener() == *listener && m_listeners[i]->query() == query) {
-            m_listeners.remove(i);
-            return;
-        }
-    }
+    m_listeners.removeFirstMatching([listener, query] (const std::unique_ptr<Listener>& current) {
+        return *current->listener() == *listener && current->query() == query;
+    });
 }
 
 void MediaQueryMatcher::styleResolverChanged()
index 23f34e5..113691e 100644 (file)
@@ -1191,10 +1191,9 @@ void StyleResolver::adjustStyleForMaskImages()
         }
 
         Vector<RefPtr<MaskImageOperation>>& pendingResources = m_state.maskImagesWithPendingSVGDocuments();
-        for (int i = pendingResources.size() - 1; i >= 0; i--) {
-            if (removedExternalResources.contains(pendingResources[i]))
-                pendingResources.remove(i);
-        }
+        pendingResources.removeAllMatching([&removedExternalResources] (const RefPtr<MaskImageOperation>& resource) {
+            return removedExternalResources.contains(resource);
+        });
     }
 }
 
index 3c0dbd1..64fd795 100644 (file)
@@ -2965,16 +2965,13 @@ void Element::detachAttrNodeFromElementWithValue(Attr* attrNode, const AtomicStr
     ASSERT(hasSyntheticAttrChildNodes());
     attrNode->detachFromElementWithValue(value);
 
-    auto* attrNodeList = attrNodeListForElement(*this);
-    for (unsigned i = 0; i < attrNodeList->size(); ++i) {
-        if (attrNodeList->at(i)->qualifiedName() == attrNode->qualifiedName()) {
-            attrNodeList->remove(i);
-            if (attrNodeList->isEmpty())
-                removeAttrNodeListForElement(*this);
-            return;
-        }
-    }
-    ASSERT_NOT_REACHED();
+    auto& attrNodeList = *attrNodeListForElement(*this);
+    bool found = attrNodeList.removeFirstMatching([attrNode] (const RefPtr<Attr>& attribute) {
+        return attribute->qualifiedName() == attrNode->qualifiedName();
+    });
+    ASSERT_UNUSED(found, found);
+    if (attrNodeList.isEmpty())
+        removeAttrNodeListForElement(*this);
 }
 
 void Element::detachAllAttrNodesFromElement()
index b60535b..f09abbe 100644 (file)
@@ -156,21 +156,14 @@ EventListenerVector* EventListenerMap::find(const AtomicString& eventType)
             return m_entries[i].second.get();
     }
 
-    return 0;
+    return nullptr;
 }
 
-static void removeFirstListenerCreatedFromMarkup(EventListenerVector* listenerVector)
+static void removeFirstListenerCreatedFromMarkup(EventListenerVector& listenerVector)
 {
-    bool foundListener = false;
-
-    for (size_t i = 0; i < listenerVector->size(); ++i) {
-        if (!listenerVector->at(i).listener->wasCreatedFromMarkup())
-            continue;
-        foundListener = true;
-        listenerVector->remove(i);
-        break;
-    }
-
+    bool foundListener = listenerVector.removeFirstMatching([] (const RegisteredEventListener& listener) {
+        return listener.listener->wasCreatedFromMarkup();
+    });
     ASSERT_UNUSED(foundListener, foundListener);
 }
 
@@ -180,7 +173,7 @@ void EventListenerMap::removeFirstEventListenerCreatedFromMarkup(const AtomicStr
 
     for (unsigned i = 0; i < m_entries.size(); ++i) {
         if (m_entries[i].first == eventType) {
-            removeFirstListenerCreatedFromMarkup(m_entries[i].second.get());
+            removeFirstListenerCreatedFromMarkup(*m_entries[i].second);
             if (m_entries[i].second->isEmpty())
                 m_entries.remove(i);
             return;
index 9cc3abe..ebf4618 100644 (file)
@@ -1952,12 +1952,9 @@ void Node::unregisterMutationObserver(MutationObserverRegistration* registration
     if (!registry)
         return;
 
-    for (size_t i = 0; i < registry->size(); ++i) {
-        if (registry->at(i).get() == registration) {
-            registry->remove(i);
-            return;
-        }
-    }
+    registry->removeFirstMatching([registration] (const std::unique_ptr<MutationObserverRegistration>& current) {
+        return current.get() == registration;
+    });
 }
 
 void Node::registerTransientMutationObserver(MutationObserverRegistration* registration)
index 042ca0e..63b2c37 100644 (file)
@@ -441,11 +441,10 @@ void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope()
 Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken& token)
 {
     Vector<Attribute> attributes = token.attributes();
-    for (int i = attributes.size() - 1; i >= 0; --i) {
-        const QualifiedName& name = attributes.at(i).name();
-        if (name.matches(nameAttr) || name.matches(actionAttr) || name.matches(promptAttr))
-            attributes.remove(i);
-    }
+    attributes.removeAllMatching([] (const Attribute& attribute) {
+        const QualifiedName& name = attribute.name();
+        return name.matches(nameAttr) || name.matches(actionAttr) || name.matches(promptAttr);
+    });
 
     attributes.append(Attribute(nameAttr, isindexTag.localName()));
     return attributes;
index c144d05..fb4a639 100644 (file)
@@ -365,18 +365,16 @@ void TextureMapperAnimations::resume()
 
 void TextureMapperAnimations::remove(const String& name)
 {
-    for (int i = m_animations.size() - 1; i >= 0; --i) {
-        if (m_animations[i].name() == name)
-            m_animations.remove(i);
-    }
+    m_animations.removeAllMatching([&name] (const TextureMapperAnimation& animation) {
+        return animation.name() == name;
+    });
 }
 
 void TextureMapperAnimations::remove(const String& name, AnimatedPropertyID property)
 {
-    for (int i = m_animations.size() - 1; i >= 0; --i) {
-        if (m_animations[i].name() == name && m_animations[i].property() == property)
-            m_animations.remove(i);
-    }
+    m_animations.removeAllMatching([&name, property] (const TextureMapperAnimation& animation) {
+        return animation.name() == name && animation.property() == property;
+    });
 }
 
 void TextureMapperAnimations::apply(TextureMapperAnimation::Client* client)
index bd14a7b..d5a383c 100644 (file)
@@ -214,10 +214,9 @@ static inline QualifiedName constructQualifiedName(const SVGElement* svgElement,
 
 static inline void clearTimesWithDynamicOrigins(Vector<SMILTimeWithOrigin>& timeList)
 {
-    for (int i = timeList.size() - 1; i >= 0; --i) {
-        if (timeList[i].originIsScript())
-            timeList.remove(i);
-    }
+    timeList.removeAllMatching([] (const SMILTimeWithOrigin& time) {
+        return time.originIsScript();
+    });
 }
 
 void SVGSMILElement::reset()
index 84a088a..87b539f 100644 (file)
@@ -1,3 +1,12 @@
+2015-02-07  Chris Dumez  <cdumez@apple.com>
+
+        Add Vector::removeFirstMatching() / removeAllMatching() methods taking lambda functions
+        https://bugs.webkit.org/show_bug.cgi?id=141321
+
+        Reviewed by Darin Adler.
+
+        Use new Vector::removeFirstMatching() / removeAllMatching() methods.
+
 2015-02-02  Chris Dumez  <cdumez@apple.com>
 
         Access MemoryCache singleton using MemoryCache::singleton()
index 8f8576f..c656a0b 100644 (file)
@@ -200,15 +200,11 @@ HRESULT STDMETHODCALLTYPE WebNotificationCenter::removeObserver(
     ObjectObserverList& observerList = it->value;
     ObserverListIterator end = observerList.end();
 
-    int i = 0;
-    for (ObserverListIterator it2 = observerList.begin(); it2 != end; ++it2, ++i) {
-        IUnknown* observedObject = it2->first.get();
-        IWebNotificationObserver* observer = it2->second.get();
-        if (observer == anObserver && (!anObject || anObject == observedObject)) {
-            observerList.remove(i);
-            break;
-        }
-    }
+    observerList.removeFirstMatching([anObject, anObserver] (const ObjectObserverPair& pair) {
+        IUnknown* observedObject = pair.first.get();
+        IWebNotificationObserver* observer = pair.second.get();
+        return observer == anObserver && (!anObject || anObject == observedObject);
+    });
 
     if (observerList.isEmpty())
         d->m_mappedObservers.remove(name);
index 9490f1a..9488e69 100644 (file)
@@ -1,3 +1,12 @@
+2015-02-07  Chris Dumez  <cdumez@apple.com>
+
+        Add Vector::removeFirstMatching() / removeAllMatching() methods taking lambda functions
+        https://bugs.webkit.org/show_bug.cgi?id=141321
+
+        Reviewed by Darin Adler.
+
+        Use new Vector::removeFirstMatching() / removeAllMatching() methods.
+
 2015-02-07  Tim Horton  <timothy_horton@apple.com>
 
         Add API::HistoryClient and split some things out of API::NavigationClient
index 8b0da3a..9c47040 100644 (file)
@@ -350,12 +350,9 @@ void PlatformCALayerRemote::addAnimationForKey(const String& key, PlatformCAAnim
 void PlatformCALayerRemote::removeAnimationForKey(const String& key)
 {
     if (m_animations.remove(key)) {
-        for (size_t i = 0; i < m_properties.addedAnimations.size(); ++i) {
-            if (m_properties.addedAnimations[i].first == key) {
-                m_properties.addedAnimations.remove(i);
-                break;
-            }
-        }
+        m_properties.addedAnimations.removeFirstMatching([&key] (const std::pair<String, PlatformCAAnimationRemote::Properties>& pair) {
+            return pair.first == key;
+        });
     }
     m_properties.keyPathsOfAnimationsToRemove.add(key);
     m_properties.notePropertiesChanged(RemoteLayerTreeTransaction::AnimationsChanged);
index 8d79e9b..19e797d 100644 (file)
@@ -1,3 +1,12 @@
+2015-02-07  Chris Dumez  <cdumez@apple.com>
+
+        Add Vector::removeFirstMatching() / removeAllMatching() methods taking lambda functions
+        https://bugs.webkit.org/show_bug.cgi?id=141321
+
+        Reviewed by Darin Adler.
+
+        Use new Vector::removeFirstMatching() / removeAllMatching() methods.
+
 2015-02-07  David Kilzer  <ddkilzer@apple.com>
 
         [iOS] Make Simulator class testable
index 67596ac..2622d09 100644 (file)
@@ -463,4 +463,58 @@ TEST(WTF_Vector, RemoveAll)
     EXPECT_TRUE(v2 == vExpected);
 }
 
+TEST(WTF_Vector, RemoveFirstMatching)
+{
+    Vector<int> v;
+    EXPECT_TRUE(v.isEmpty());
+    EXPECT_FALSE(v.removeFirstMatching([] (int value) { return value > 0; }));
+    EXPECT_FALSE(v.removeFirstMatching([] (int) { return true; }));
+    EXPECT_FALSE(v.removeFirstMatching([] (int) { return false; }));
+
+    v = {3, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3};
+    EXPECT_EQ(12U, v.size());
+    EXPECT_FALSE(v.removeFirstMatching([] (int) { return false; }));
+    EXPECT_EQ(12U, v.size());
+    EXPECT_FALSE(v.removeFirstMatching([] (int value) { return value < 0; }));
+    EXPECT_EQ(12U, v.size());
+    EXPECT_TRUE(v.removeFirstMatching([] (int value) { return value < 3; }));
+    EXPECT_EQ(11U, v.size());
+    EXPECT_TRUE(v == Vector<int>({3, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3}));
+    EXPECT_TRUE(v.removeFirstMatching([] (int value) { return value > 2; }));
+    EXPECT_EQ(10U, v.size());
+    EXPECT_TRUE(v == Vector<int>({2, 1, 2, 1, 2, 2, 1, 1, 1, 3}));
+    EXPECT_TRUE(v.removeFirstMatching([] (int value) { return value > 2; }));
+    EXPECT_EQ(9U, v.size());
+    EXPECT_TRUE(v == Vector<int>({2, 1, 2, 1, 2, 2, 1, 1, 1}));
+}
+
+TEST(WTF_Vector, RemoveAllMatching)
+{
+    Vector<int> v;
+    EXPECT_TRUE(v.isEmpty());
+    EXPECT_FALSE(v.removeAllMatching([] (int value) { return value > 0; }));
+    EXPECT_FALSE(v.removeAllMatching([] (int) { return true; }));
+    EXPECT_FALSE(v.removeAllMatching([] (int) { return false; }));
+
+    v = {3, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3};
+    EXPECT_EQ(12U, v.size());
+    EXPECT_EQ(0U, v.removeAllMatching([] (int) { return false; }));
+    EXPECT_EQ(12U, v.size());
+    EXPECT_EQ(0U, v.removeAllMatching([] (int value) { return value < 0; }));
+    EXPECT_EQ(12U, v.size());
+    EXPECT_EQ(12U, v.removeAllMatching([] (int value) { return value > 0; }));
+    EXPECT_TRUE(v.isEmpty());
+
+    v = {3, 1, 2, 1, 2, 1, 3, 2, 2, 1, 1, 1, 3};
+    EXPECT_EQ(13U, v.size());
+    EXPECT_EQ(3U, v.removeAllMatching([] (int value) { return value > 2; }));
+    EXPECT_EQ(10U, v.size());
+    EXPECT_TRUE(v == Vector<int>({1, 2, 1, 2, 1, 2, 2, 1, 1, 1}));
+    EXPECT_EQ(6U, v.removeAllMatching([] (int value) { return value != 2; }));
+    EXPECT_EQ(4U, v.size());
+    EXPECT_TRUE(v == Vector<int>({2, 2, 2, 2}));
+    EXPECT_EQ(4U, v.removeAllMatching([] (int value) { return value == 2; }));
+    EXPECT_TRUE(v.isEmpty());
+}
+
 } // namespace TestWebKitAPI
index 44ea391..f09aa26 100644 (file)
@@ -109,13 +109,9 @@ void InjectedBundle::didCreatePage(WKBundlePageRef page)
 
 void InjectedBundle::willDestroyPage(WKBundlePageRef page)
 {
-    size_t size = m_pages.size();
-    for (size_t i = 0; i < size; ++i) {
-        if (m_pages[i]->page() == page) {
-            m_pages.remove(i);
-            break;
-        }
-    }
+    m_pages.removeFirstMatching([page] (const std::unique_ptr<InjectedBundlePage>& current) {
+        return current->page() == page;
+    });
 }
 
 void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup)