aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkDeque.h
blob: 3bf0bdd89d7b44aeab687de1dd928ae39b1c0c37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#ifndef SkDeque_DEFINED
#define SkDeque_DEFINED

#include "SkTypes.h"

class SK_API SkDeque : SkNoncopyable {
public:
    /**
     * elemSize specifies the size of each individual element in the deque
     * allocCount specifies how many elements are to be allocated as a block
     */
    explicit SkDeque(size_t elemSize, int allocCount = 1);
    SkDeque(size_t elemSize, void* storage, size_t storageSize, int allocCount = 1);
    ~SkDeque();

    bool    empty() const { return 0 == fCount; }
    int     count() const { return fCount; }
    size_t  elemSize() const { return fElemSize; }

    const void* front() const;
    const void* back() const;

    void* front() {
        return (void*)((const SkDeque*)this)->front();
    }

    void* back() {
        return (void*)((const SkDeque*)this)->back();
    }

    void* push_front();
    void* push_back();

    void pop_front();
    void pop_back();

private:
    struct Block;

public:
    class Iter {
    public:
        enum IterStart {
            kFront_IterStart,
            kBack_IterStart
        };

        /**
         * Creates an uninitialized iterator. Must be reset()
         */
        Iter();

        Iter(const SkDeque& d, IterStart startLoc);
        void* next();
        void* prev();

        void reset(const SkDeque& d, IterStart startLoc);

    private:
        SkDeque::Block*  fCurBlock;
        char*           fPos;
        size_t          fElemSize;
    };
    
    // Inherit privately from Iter to prevent access to reverse iteration
    class F2BIter : private Iter {
    public:
        F2BIter() {}

        /**
         * Wrap Iter's 2 parameter ctor to force initialization to the 
         * beginning of the deque
         */
        F2BIter(const SkDeque& d) : INHERITED(d, kFront_IterStart) {}

        using Iter::next;

        /** 
         * Wrap Iter::reset to force initialization to the beginning of the 
         * deque
         */
        void reset(const SkDeque& d) {
            this->INHERITED::reset(d, kFront_IterStart);
        }

    private:
        typedef Iter INHERITED;
    };

private:
    // allow unit test to call numBlocksAllocated
    friend class DequeUnitTestHelper; 

    Block*  fFront;
    Block*  fBack;
    size_t  fElemSize;
    void*   fInitialStorage;
    int     fCount;             // number of elements in the deque
    int     fAllocCount;        // number of elements to allocate per block

    Block*  allocateBlock(int allocCount);
    void    freeBlock(Block* block);

    /**
     * This returns the number of chunk blocks allocated by the deque. It
     * can be used to gauge the effectiveness of the selected allocCount.
     */
    int  numBlocksAllocated() const;
};

#endif