sk_tool::Registry: make an iterator.

Change-Id: Icf4e31b50bbd91b7ea330a1300f736d6dfd0a41c
Reviewed-on: https://skia-review.googlesource.com/144500
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
Auto-Submit: Hal Canary <halcanary@google.com>
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 68923d1..afe7b71 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -712,7 +712,7 @@
 
     Benchmark* rawNext() {
         if (fBenches) {
-            Benchmark* bench = fBenches->factory()(nullptr);
+            Benchmark* bench = fBenches->get()(nullptr);
             fBenches = fBenches->next();
             fSourceType = "bench";
             fBenchType  = "micro";
@@ -720,7 +720,7 @@
         }
 
         while (fGMs) {
-            std::unique_ptr<skiagm::GM> gm(fGMs->factory()(nullptr));
+            std::unique_ptr<skiagm::GM> gm(fGMs->get()(nullptr));
             fGMs = fGMs->next();
             if (gm->runAsBench()) {
                 fSourceType = "gm";
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 4d62421..d86db82 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -783,8 +783,8 @@
 }
 
 static bool gather_srcs() {
-    for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) {
-        push_src("gm", "", new GMSrc(r->factory()));
+    for (skiagm::GMFactory f : skiagm::GMRegistry::Range()) {
+        push_src("gm", "", new GMSrc(f));
     }
 
     gather_file_srcs<SKPSrc>(FLAGS_skps, "skp");
@@ -1261,13 +1261,10 @@
     if (!FLAGS_src.contains("tests")) {
         return;
     }
-    for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
+    for (const skiatest::Test& test : skiatest::TestRegistry::Range()) {
         if (!in_shard()) {
             continue;
         }
-        // Despite its name, factory() is returning a reference to
-        // link-time static const POD data.
-        const skiatest::Test& test = r->factory();
         if (SkCommandLineFlags::ShouldSkip(FLAGS_match, test.name)) {
             continue;
         }
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 2a0925e..5667f41 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -88,7 +88,7 @@
 
 namespace DM {
 
-GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
+GMSrc::GMSrc(skiagm::GMFactory factory) : fFactory(factory) {}
 
 Error GMSrc::draw(SkCanvas* canvas) const {
     std::unique_ptr<skiagm::GM> gm(fFactory(nullptr));
diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h
index 257ca8b..a97b077 100644
--- a/dm/DMSrcSink.h
+++ b/dm/DMSrcSink.h
@@ -100,7 +100,7 @@
 
 class GMSrc : public Src {
 public:
-    explicit GMSrc(skiagm::GMRegistry::Factory);
+    explicit GMSrc(skiagm::GMFactory);
 
     Error draw(SkCanvas*) const override;
     SkISize size() const override;
@@ -108,7 +108,7 @@
     void modifyGrContextOptions(GrContextOptions* options) const override;
 
 private:
-    skiagm::GMRegistry::Factory fFactory;
+    skiagm::GMFactory fFactory;
 };
 
 class CodecSrc : public Src {
diff --git a/fuzz/fuzz.cpp b/fuzz/fuzz.cpp
index 13b49b8..760ebda 100644
--- a/fuzz/fuzz.cpp
+++ b/fuzz/fuzz.cpp
@@ -304,15 +304,13 @@
 
 static void print_api_names(){
     SkDebugf("When using --type api, please choose an API to fuzz with --name/-n:\n");
-    for (auto r = sk_tools::Registry<Fuzzable>::Head(); r; r = r->next()) {
-        auto fuzzable = r->factory();
+    for (const Fuzzable& fuzzable : sk_tools::Registry<Fuzzable>::Range()) {
         SkDebugf("\t%s\n", fuzzable.name);
     }
 }
 
 static void fuzz_api(sk_sp<SkData> bytes, SkString name) {
-    for (auto r = sk_tools::Registry<Fuzzable>::Head(); r; r = r->next()) {
-        auto fuzzable = r->factory();
+    for (const Fuzzable& fuzzable : sk_tools::Registry<Fuzzable>::Range()) {
         if (name.equals(fuzzable.name)) {
             SkDebugf("Fuzzing %s...\n", fuzzable.name);
             Fuzz fuzz(std::move(bytes));
diff --git a/gm/gm.h b/gm/gm.h
index c799532..8536709 100644
--- a/gm/gm.h
+++ b/gm/gm.h
@@ -119,7 +119,8 @@
         bool     fHaveCalledOnceBeforeDraw;
     };
 
-    typedef sk_tools::Registry<GM*(*)(void*)> GMRegistry;
+    typedef GM*(*GMFactory)(void*) ;
+    typedef sk_tools::Registry<GMFactory> GMRegistry;
 
     class SimpleGM : public skiagm::GM {
     public:
diff --git a/tests/skia_test.cpp b/tests/skia_test.cpp
index 834585f..a2fbf2f 100644
--- a/tests/skia_test.cpp
+++ b/tests/skia_test.cpp
@@ -195,9 +195,7 @@
     int total = 0;
     int toRun = 0;
 
-    for (const TestRegistry* iter = TestRegistry::Head(); iter;
-         iter = iter->next()) {
-        const Test& test = iter->factory();
+    for (const Test& test : TestRegistry::Range()) {
         if (should_run(test.name, test.needsGpu)) {
             toRun++;
         }
@@ -212,9 +210,8 @@
     SkTArray<const Test*> gpuTests;
 
     Status status(toRun);
-    for (const TestRegistry* iter = TestRegistry::Head(); iter;
-         iter = iter->next()) {
-        const Test& test = iter->factory();
+
+    for (const Test& test : TestRegistry::Range()) {
         if (!should_run(test.name, test.needsGpu)) {
             ++skipCount;
         } else if (test.needsGpu) {
diff --git a/tools/Registry.h b/tools/Registry.h
index 4184e49..6c35578 100644
--- a/tools/Registry.h
+++ b/tools/Registry.h
@@ -19,9 +19,7 @@
  */
 template <typename T> class Registry : SkNoncopyable {
 public:
-    typedef T Factory;
-
-    explicit Registry(T fact) : fFact(fact) {
+    explicit Registry(T value) : fValue(value) {
 #ifdef SK_BUILD_FOR_ANDROID
         // work-around for double-initialization bug
         {
@@ -41,10 +39,22 @@
     static const Registry* Head() { return gHead; }
 
     const Registry* next() const { return fChain; }
-    const Factory& factory() const { return fFact; }
+    const T& get() const { return fValue; }
+
+    // for (const T& t : sk_tools::Registry<T>::Range()) { process(t); }
+    struct Range {
+        struct Iterator {
+            const Registry* fPtr;
+            const T& operator*() { return SkASSERT(fPtr), fPtr->get(); }
+            void operator++() { if (fPtr) { fPtr = fPtr->next(); } }
+            bool operator!=(const Iterator& other) const { return fPtr != other.fPtr; }
+        };
+        Iterator begin() const { return Iterator{Registry::Head()}; }
+        Iterator end() const { return Iterator{nullptr}; }
+    };
 
 private:
-    Factory   fFact;
+    T fValue;
     Registry* fChain;
 
     static Registry* gHead;
diff --git a/tools/list_gms.cpp b/tools/list_gms.cpp
index dde7f47..666f84b 100644
--- a/tools/list_gms.cpp
+++ b/tools/list_gms.cpp
@@ -14,8 +14,8 @@
 
 int main() {
     std::vector<std::string> gms;
-    for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) {
-        std::unique_ptr<skiagm::GM> gm(r->factory()(nullptr));
+    for (skiagm::GMFactory factory : skiagm::GMRegistry::Range()) {
+        std::unique_ptr<skiagm::GM> gm(factory(nullptr));
         gms.push_back(std::string(gm->getName()));
     }
     std::sort(gms.begin(), gms.end());
diff --git a/tools/list_gpu_unit_tests.cpp b/tools/list_gpu_unit_tests.cpp
index 18127b6..72c2497 100644
--- a/tools/list_gpu_unit_tests.cpp
+++ b/tools/list_gpu_unit_tests.cpp
@@ -14,8 +14,7 @@
 
 int main() {
     std::vector<std::string> tests;
-    for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
-        const skiatest::Test& test = r->factory();
+    for (const skiatest::Test& test : skiatest::TestRegistry::Range()) {
         if (test.needsGpu) {
             tests.push_back(std::string(test.name));
         }
diff --git a/tools/skqp/gm_runner.cpp b/tools/skqp/gm_runner.cpp
index 778c2bc..0cd031c 100644
--- a/tools/skqp/gm_runner.cpp
+++ b/tools/skqp/gm_runner.cpp
@@ -98,8 +98,7 @@
 
 std::vector<UnitTest> GetUnitTests() {
     std::vector<UnitTest> tests;
-    for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
-        const skiatest::Test& test = r->factory();
+    for (const skiatest::Test& test : skiatest::TestRegistry::Range()) {
         if ((is_empty(gKnownGpuUnitTests) || in_set(test.name, gKnownGpuUnitTests))
             && test.needsGpu) {
             tests.push_back(&test);
@@ -255,8 +254,7 @@
 
 std::vector<GMFactory> GetGMFactories(skqp::AssetManager* assetManager) {
     std::vector<GMFactory> result;
-    for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) {
-        GMFactory f = r->factory();
+    for (const GMFactory& f : skiagm::GMRegistry::Range()) {
         SkASSERT(f);
         auto name = GetGMName(f);
         if ((is_empty(gKnownGMs) || in_set(name.c_str(), gKnownGMs)) &&
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 17277fc..f88dfbb 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -594,16 +594,12 @@
 
     // GMs
     int firstGM = fSlides.count();
-    const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head());
-    while (gms) {
-        std::unique_ptr<skiagm::GM> gm(gms->factory()(nullptr));
-
+    for (skiagm::GMFactory gmFactory : skiagm::GMRegistry::Range()) {
+        std::unique_ptr<skiagm::GM> gm(gmFactory(nullptr));
         if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) {
             sk_sp<Slide> slide(new GMSlide(gm.release()));
             fSlides.push_back(std::move(slide));
         }
-
-        gms = gms->next();
     }
     // reverse gms
     int numGMs = fSlides.count() - firstGM;