blob: b6ac23bee03f0acb6d61a7b2a65c8608a2c7875c [file] [log] [blame]
reed@android.com00bf85a2009-01-22 13:04:56 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2009 The Android Open Source Project
reed@android.com00bf85a2009-01-22 13:04:56 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com00bf85a2009-01-22 13:04:56 +00006 */
7
Mike Reedab273fa2017-01-11 13:58:55 -05008#ifndef sk_tools_Registry_DEFINED
9#define sk_tools_Registry_DEFINED
reed@android.com00bf85a2009-01-22 13:04:56 +000010
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkTypes.h"
Kevin Lubick1b3aa8b2023-01-19 14:03:31 -050012#include "include/private/base/SkNoncopyable.h"
reed@android.com00bf85a2009-01-22 13:04:56 +000013
Mike Reedab273fa2017-01-11 13:58:55 -050014namespace sk_tools {
15
John Stiles5e9388d2022-03-07 17:54:21 -050016/**
17 * Template class that registers itself (in the constructor) into a linked-list
18 * and provides a function-pointer. This can be used to auto-register a set of
19 * services, e.g. a set of image codecs.
reed@android.com00bf85a2009-01-22 13:04:56 +000020 */
Mike Reedab273fa2017-01-11 13:58:55 -050021template <typename T> class Registry : SkNoncopyable {
reed@android.com00bf85a2009-01-22 13:04:56 +000022public:
John Stiles5e9388d2022-03-07 17:54:21 -050023 explicit Registry(T value, bool condition = true) : fValue(value) {
24 if (condition) {
25 this->linkToRegistryHead();
reed@android.com57b799e2009-04-01 20:26:42 +000026 }
reed@android.com00bf85a2009-01-22 13:04:56 +000027 }
28
Mike Reedab273fa2017-01-11 13:58:55 -050029 static const Registry* Head() { return gHead; }
reed@android.com00bf85a2009-01-22 13:04:56 +000030
Mike Reedab273fa2017-01-11 13:58:55 -050031 const Registry* next() const { return fChain; }
Hal Canary972eba32018-07-30 17:07:07 -040032 const T& get() const { return fValue; }
33
34 // for (const T& t : sk_tools::Registry<T>::Range()) { process(t); }
35 struct Range {
36 struct Iterator {
37 const Registry* fPtr;
38 const T& operator*() { return SkASSERT(fPtr), fPtr->get(); }
39 void operator++() { if (fPtr) { fPtr = fPtr->next(); } }
40 bool operator!=(const Iterator& other) const { return fPtr != other.fPtr; }
41 };
42 Iterator begin() const { return Iterator{Registry::Head()}; }
43 Iterator end() const { return Iterator{nullptr}; }
44 };
reed@android.com00bf85a2009-01-22 13:04:56 +000045
46private:
John Stiles5e9388d2022-03-07 17:54:21 -050047 void linkToRegistryHead() {
John Stiles5e9388d2022-03-07 17:54:21 -050048 fChain = gHead;
49 gHead = this;
50 }
51
Hal Canary972eba32018-07-30 17:07:07 -040052 T fValue;
Mike Reedab273fa2017-01-11 13:58:55 -050053 Registry* fChain;
reed@android.com00bf85a2009-01-22 13:04:56 +000054
Mike Reedab273fa2017-01-11 13:58:55 -050055 static Registry* gHead;
reed@android.com00bf85a2009-01-22 13:04:56 +000056};
57
reed@android.comf523e252009-01-26 23:15:37 +000058// The caller still needs to declare an instance of this somewhere
Mike Reedab273fa2017-01-11 13:58:55 -050059template <typename T> Registry<T>* Registry<T>::gHead;
60
61} // namespace sk_tools
reed@android.com00bf85a2009-01-22 13:04:56 +000062
63#endif