Home | History | Annotate | Download | only in core
      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      */
     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:
     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          */
     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:
     82     virtual void incPtr(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:
    108     uint32_t find(T ptr) {
    109         return this->INHERITED::find((void*)ptr);
    110     }
    111     uint32_t add(T ptr) {
    112         return this->INHERITED::add((void*)ptr);
    113     }
    114 
    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