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