1 /*
2  * Copyright 2008 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 
9 #ifndef SkPtrSet_DEFINED
10 #define SkPtrSet_DEFINED
11 
12 #include "SkRefCnt.h"
13 #include "SkFlattenable.h"
14 #include "SkTDArray.h"
15 
16 /**
17  *  Maintains a set of ptrs, assigning each a unique ID [1...N]. Duplicate ptrs
18  *  return the same ID (since its a set). Subclasses can override inPtr()
19  *  and decPtr(). incPtr() is called each time a unique ptr is added ot the
20  *  set. decPtr() is called on each ptr when the set is destroyed or reset.
21  */
22 class SkPtrSet : public SkRefCnt {
23 public:
24 
25 
26     /**
27      *  Search for the specified ptr in the set. If it is found, return its
28      *  32bit ID [1..N], or if not found, return 0. Always returns 0 for nullptr.
29      */
30     uint32_t find(void*) const;
31 
32     /**
33      *  Add the specified ptr to the set, returning a unique 32bit ID for it
34      *  [1...N]. Duplicate ptrs will return the same ID.
35      *
36      *  If the ptr is nullptr, it is not added, and 0 is returned.
37      */
38     uint32_t add(void*);
39 
40     /**
41      *  Return the number of (non-null) ptrs in the set.
42      */
count()43     int count() const { return fList.count(); }
44 
45     /**
46      *  Copy the ptrs in the set into the specified array (allocated by the
47      *  caller). The ptrs are assgined to the array based on their corresponding
48      *  ID. e.g. array[ptr.ID - 1] = ptr.
49      *
50      *  incPtr() and decPtr() are not called during this operation.
51      */
52     void copyToArray(void* array[]) const;
53 
54     /**
55      *  Call decPtr() on each ptr in the set, and the reset the size of the set
56      *  to 0.
57      */
58     void reset();
59 
60     /**
61      * Set iterator.
62      */
63     class Iter {
64     public:
Iter(const SkPtrSet & set)65         Iter(const SkPtrSet& set)
66             : fSet(set)
67             , fIndex(0) {}
68 
69         /**
70          * Return the next ptr in the set or null if the end was reached.
71          */
next()72         void* next() {
73             return fIndex < fSet.fList.count() ? fSet.fList[fIndex++].fPtr : nullptr;
74         }
75 
76     private:
77         const SkPtrSet& fSet;
78         int             fIndex;
79     };
80 
81 protected:
incPtr(void *)82     virtual void incPtr(void*) {}
decPtr(void *)83     virtual void decPtr(void*) {}
84 
85 private:
86     struct Pair {
87         void*       fPtr;   // never nullptr
88         uint32_t    fIndex; // 1...N
89     };
90 
91     // we store the ptrs in sorted-order (using Cmp) so that we can efficiently
92     // detect duplicates when add() is called. Hence we need to store the
93     // ptr and its ID/fIndex explicitly, since the ptr's position in the array
94     // is not related to its "index".
95     SkTDArray<Pair>  fList;
96 
97     static bool Less(const Pair& a, const Pair& b);
98 
99     typedef SkRefCnt INHERITED;
100 };
101 
102 /**
103  *  Templated wrapper for SkPtrSet, just meant to automate typecasting
104  *  parameters to and from void* (which the base class expects).
105  */
106 template <typename T> class SkTPtrSet : public SkPtrSet {
107 public:
find(T ptr)108     uint32_t find(T ptr) {
109         return this->INHERITED::find((void*)ptr);
110     }
add(T ptr)111     uint32_t add(T ptr) {
112         return this->INHERITED::add((void*)ptr);
113     }
114 
copyToArray(T * array)115     void copyToArray(T* array) const {
116         this->INHERITED::copyToArray((void**)array);
117     }
118 
119 private:
120     typedef SkPtrSet INHERITED;
121 };
122 
123 /**
124  *  Subclass of SkTPtrSet specialed to call ref() and unref() when the
125  *  base class's incPtr() and decPtr() are called. This makes it a valid owner
126  *  of each ptr, which is released when the set is reset or destroyed.
127  */
128 class SkRefCntSet : public SkTPtrSet<SkRefCnt*> {
129 public:
130     virtual ~SkRefCntSet();
131 
132 protected:
133     // overrides
134     virtual void incPtr(void*);
135     virtual void decPtr(void*);
136 };
137 
138 class SkFactorySet : public SkTPtrSet<SkFlattenable::Factory> {};
139 
140 /**
141  * Similar to SkFactorySet, but only allows Factorys that have registered names.
142  * Also has a function to return the next added Factory's name.
143  */
144 class SkNamedFactorySet : public SkRefCnt {
145 public:
146 
147 
148     SkNamedFactorySet();
149 
150     /**
151      * Find the specified Factory in the set. If it is not already in the set,
152      * and has registered its name, add it to the set, and return its index.
153      * If the Factory has no registered name, return 0.
154      */
155     uint32_t find(SkFlattenable::Factory);
156 
157     /**
158      * If new Factorys have been added to the set, return the name of the first
159      * Factory added after the Factory name returned by the last call to this
160      * function.
161      */
162     const char* getNextAddedFactoryName();
163 private:
164     int                    fNextAddedFactory;
165     SkFactorySet           fFactorySet;
166     SkTDArray<const char*> fNames;
167 
168     typedef SkRefCnt INHERITED;
169 };
170 
171 #endif
172