Home | History | Annotate | Download | only in core
      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      */
     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 
     82 protected:
     83     virtual void incPtr(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:
    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 
    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