Allow WTF::map to use any class that is iterable and has a size getter
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Sep 2017 00:57:40 +0000 (00:57 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Sep 2017 00:57:40 +0000 (00:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=177026

Patch by Youenn Fablet <youenn@apple.com> on 2017-09-19
Reviewed by Darin Adler.

Source/WebCore:

No change of behavior.
Using WTF::map to go from maps to vectors.

* loader/appcache/ApplicationCacheHost.cpp:
(WebCore::ApplicationCacheHost::resourceList):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::dispatchAllPendingUnloadEvents):

Source/WTF:

Computing the Item type given to the lambda using the iterator instead of ValueType which is specific to Vector.
Adding the possibility to pass a non const container reference and a lambda taking non const references as well.

* wtf/Vector.h:
(WTF::MapFunctionInspector::acceptsReference):
(WTF::Mapper::map):
(WTF::map):

Tools:

* TestWebKitAPI/Tests/WTF/Vector.cpp:
(TestWebKitAPI::TEST):

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

Source/WTF/ChangeLog
Source/WTF/wtf/Vector.h
Source/WebCore/ChangeLog
Source/WebCore/loader/appcache/ApplicationCacheHost.cpp
Source/WebCore/page/DOMWindow.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WTF/Vector.cpp

index c7144f6..a3e710b 100644 (file)
@@ -1,3 +1,18 @@
+2017-09-19  Youenn Fablet  <youenn@apple.com>
+
+        Allow WTF::map to use any class that is iterable and has a size getter
+        https://bugs.webkit.org/show_bug.cgi?id=177026
+
+        Reviewed by Darin Adler.
+
+        Computing the Item type given to the lambda using the iterator instead of ValueType which is specific to Vector.
+        Adding the possibility to pass a non const container reference and a lambda taking non const references as well. 
+
+        * wtf/Vector.h:
+        (WTF::MapFunctionInspector::acceptsReference):
+        (WTF::Mapper::map):
+        (WTF::map):
+
 2017-09-19  Jer Noble  <jer.noble@apple.com>
 
         [Cocoa] Add an ImageDecoder subclass backed by AVFoundation
index 2aebe71..4875051 100644 (file)
@@ -1562,34 +1562,49 @@ size_t removeRepeatedElements(Vector<T, inlineCapacity, OverflowHandler, minCapa
     return removeRepeatedElements(vector, [] (T& a, T& b) { return a == b; });
 }
 
-template<typename Transformer, typename SourceType> struct Mapper {
+template<typename MapFunction, typename SourceType>
+struct MapFunctionInspector {
     using RealSourceType = typename std::remove_reference<SourceType>::type;
-    using SourceItemType = typename RealSourceType::ValueType;
-    using DestinationItemType = typename std::result_of<Transformer(SourceItemType&&)>::type;
+    using IteratorType = decltype(std::begin(std::declval<RealSourceType>()));
+    using SourceItemType = typename std::iterator_traits<IteratorType>::value_type;
+};
+
+template<typename MapFunction, typename SourceType, typename Enable = void>
+struct Mapper {
+    using SourceItemType = typename MapFunctionInspector<MapFunction, SourceType>::SourceItemType;
+    using DestinationItemType = typename std::result_of<MapFunction(SourceItemType&)>::type;
 
-    static Vector<DestinationItemType> map(const RealSourceType& source, const Transformer& transformer)
+    static Vector<DestinationItemType> map(SourceType source, const MapFunction& mapFunction)
     {
         Vector<DestinationItemType> result;
+        // FIXME: Use std::size when available on all compilers.
         result.reserveInitialCapacity(source.size());
         for (auto& item : source)
-            result.uncheckedAppend(transformer(item));
+            result.uncheckedAppend(mapFunction(item));
         return result;
     }
+};
+
+template<typename MapFunction, typename SourceType>
+struct Mapper<MapFunction, SourceType, typename std::enable_if<std::is_rvalue_reference<SourceType&&>::value>::type> {
+    using SourceItemType = typename MapFunctionInspector<MapFunction, SourceType>::SourceItemType;
+    using DestinationItemType = typename std::result_of<MapFunction(SourceItemType&&)>::type;
 
-    static Vector<DestinationItemType> map(RealSourceType&& source, const Transformer& transformer)
+    static Vector<DestinationItemType> map(SourceType&& source, const MapFunction& mapFunction)
     {
         Vector<DestinationItemType> result;
+        // FIXME: Use std::size when available on all compilers.
         result.reserveInitialCapacity(source.size());
         for (auto& item : source)
-            result.uncheckedAppend(transformer(std::forward<SourceItemType>(item)));
+            result.uncheckedAppend(mapFunction(WTFMove(item)));
         return result;
     }
 };
 
-template<typename Transformer, typename VectorType>
-Vector<typename Mapper<Transformer, VectorType>::DestinationItemType> map(VectorType&& source, Transformer&& transformer)
+template<typename MapFunction, typename SourceType>
+Vector<typename Mapper<MapFunction, SourceType>::DestinationItemType> map(SourceType&& source, MapFunction&& mapFunction)
 {
-    return Mapper<Transformer, VectorType>::map(std::forward<VectorType>(source), std::forward<Transformer>(transformer));
+    return Mapper<MapFunction, SourceType>::map(std::forward<SourceType>(source), std::forward<MapFunction>(mapFunction));
 }
 
 } // namespace WTF
index ee71889..922c84b 100644 (file)
@@ -1,3 +1,18 @@
+2017-09-19  Youenn Fablet  <youenn@apple.com>
+
+        Allow WTF::map to use any class that is iterable and has a size getter
+        https://bugs.webkit.org/show_bug.cgi?id=177026
+
+        Reviewed by Darin Adler.
+
+        No change of behavior.
+        Using WTF::map to go from maps to vectors.
+
+        * loader/appcache/ApplicationCacheHost.cpp:
+        (WebCore::ApplicationCacheHost::resourceList):
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::dispatchAllPendingUnloadEvents):
+
 2017-09-19  Eric Carlson  <eric.carlson@apple.com>
 
         Quiet media player private logging
index d08c3f1..d2b04ff 100644 (file)
@@ -327,15 +327,11 @@ void ApplicationCacheHost::stopDeferringEvents()
 
 Vector<ApplicationCacheHost::ResourceInfo> ApplicationCacheHost::resourceList()
 {
-    Vector<ResourceInfo> result;
-
     auto* cache = applicationCache();
     if (!cache || !cache->isComplete())
-        return result;
-
-    result.reserveInitialCapacity(cache->resources().size());
+        return { };
 
-    for (auto& urlAndResource : cache->resources()) {
+    return WTF::map(cache->resources(), [] (auto& urlAndResource) -> ApplicationCacheHost::ResourceInfo {
         ASSERT(urlAndResource.value);
         auto& resource = *urlAndResource.value;
 
@@ -346,10 +342,8 @@ Vector<ApplicationCacheHost::ResourceInfo> ApplicationCacheHost::resourceList()
         bool isForeign = type & ApplicationCacheResource::Foreign;
         bool isFallback = type & ApplicationCacheResource::Fallback;
 
-        result.uncheckedAppend({ resource.url(), isMaster, isManifest, isFallback, isForeign, isExplicit, resource.estimatedSizeInStorage() });
-    }
-
-    return result;
+        return { resource.url(), isMaster, isManifest, isFallback, isForeign, isExplicit, resource.estimatedSizeInStorage() };
+    });
 }
 
 ApplicationCacheHost::CacheInfo ApplicationCacheHost::applicationCacheInfo()
index cb16398..58353fd 100644 (file)
@@ -297,10 +297,9 @@ void DOMWindow::dispatchAllPendingUnloadEvents()
     if (alreadyDispatched)
         return;
 
-    Vector<Ref<DOMWindow>> windows;
-    windows.reserveInitialCapacity(set.size());
-    for (auto& keyValue : set)
-        windows.uncheckedAppend(*keyValue.key);
+    auto windows = WTF::map(set, [] (auto& keyValue) {
+        return Ref<DOMWindow>(*(keyValue.key));
+    });
 
     for (auto& window : windows) {
         if (!set.contains(window.ptr()))
index 79d9eb9..3a52d74 100644 (file)
@@ -1,3 +1,13 @@
+2017-09-19  Youenn Fablet  <youenn@apple.com>
+
+        Allow WTF::map to use any class that is iterable and has a size getter
+        https://bugs.webkit.org/show_bug.cgi?id=177026
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WTF/Vector.cpp:
+        (TestWebKitAPI::TEST):
+
 2017-09-19  Ryan Haddad  <ryanhaddad@apple.com>
 
         Update bot configuration for iOS 11.
index 27200db..bc3525b 100644 (file)
 #include "config.h"
 
 #include "MoveOnly.h"
+#include <wtf/HashMap.h>
 #include <wtf/Vector.h>
-#include <wtf/text/CString.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
 
 namespace TestWebKitAPI {
 
@@ -726,4 +728,51 @@ TEST(WTF_Vector, MapLambdaMove)
     EXPECT_EQ(5U, mapped[2].value());
 }
 
+TEST(WTF_Vector, MapFromHashMap)
+{
+    HashMap<String, String> map;
+    map.set(String { "k1" }, String { "v1" });
+    map.set(String { "k2" }, String { "v2" });
+    map.set(String { "k3" }, String { "v3" });
+
+    auto mapped = WTF::map(map, [&] (KeyValuePair<String, String>& pair) -> String {
+        return pair.value;
+    });
+    std::sort(mapped.begin(), mapped.end(), WTF::codePointCompareLessThan);
+
+    EXPECT_EQ(3U, mapped.size());
+    EXPECT_TRUE(mapped[0] == "v1");
+    EXPECT_TRUE(mapped[1] == "v2");
+    EXPECT_TRUE(mapped[2] == "v3");
+
+    mapped = WTF::map(map, [&] (const auto& pair) -> String {
+        return pair.key;
+    });
+    std::sort(mapped.begin(), mapped.end(), WTF::codePointCompareLessThan);
+
+    EXPECT_EQ(3U, mapped.size());
+    EXPECT_TRUE(mapped[0] == "k1");
+    EXPECT_TRUE(mapped[1] == "k2");
+    EXPECT_TRUE(mapped[2] == "k3");
+
+    mapped = WTF::map(WTFMove(map), [&] (KeyValuePair<String, String>&& pair) -> String {
+        return WTFMove(pair.value);
+    });
+    std::sort(mapped.begin(), mapped.end(), WTF::codePointCompareLessThan);
+
+    EXPECT_EQ(3U, mapped.size());
+    EXPECT_TRUE(mapped[0] == "v1");
+    EXPECT_TRUE(mapped[1] == "v2");
+    EXPECT_TRUE(mapped[2] == "v3");
+
+    EXPECT_TRUE(map.contains("k1"));
+    EXPECT_TRUE(map.contains("k2"));
+    EXPECT_TRUE(map.contains("k3"));
+
+    EXPECT_TRUE(map.get("k1").isNull());
+    EXPECT_TRUE(map.get("k2").isNull());
+    EXPECT_TRUE(map.get("k3").isNull());
+
+}
+
 } // namespace TestWebKitAPI