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 */
23class SkPtrSet : public SkRefCnt {
24public:
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     */
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:
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         */
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
82protected:
83    virtual void incPtr(void*) {}
84    virtual void decPtr(void*) {}
85
86private:
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 */
107template <typename T> class SkTPtrSet : public SkPtrSet {
108public:
109    uint32_t find(T ptr) {
110        return this->INHERITED::find((void*)ptr);
111    }
112    uint32_t add(T ptr) {
113        return this->INHERITED::add((void*)ptr);
114    }
115
116    void copyToArray(T* array) const {
117        this->INHERITED::copyToArray((void**)array);
118    }
119
120private:
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 */
129class SkRefCntSet : public SkTPtrSet<SkRefCnt*> {
130public:
131    virtual ~SkRefCntSet();
132
133protected:
134    // overrides
135    virtual void incPtr(void*);
136    virtual void decPtr(void*);
137};
138
139class 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 */
145class SkNamedFactorySet : public SkRefCnt {
146public:
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();
164private:
165    int                    fNextAddedFactory;
166    SkFactorySet           fFactorySet;
167    SkTDArray<const char*> fNames;
168
169    typedef SkRefCnt INHERITED;
170};
171
172#endif
173