summaryrefslogtreecommitdiff
path: root/include/JSystem/JGadget/linklist.h
blob: 3c120788548f138558d2dae5f0a910bcb5058f67 (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#ifndef LINKLIST_H
#define LINKLIST_H

#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JGadget/define.h"
#include <iterator.h>

namespace JGadget {
struct TLinkListNode {
    TLinkListNode() {
        mNext = NULL;
        mPrev = NULL;
    }

    TLinkListNode* getNext() const { return mNext; }
    TLinkListNode* getPrev() const { return mPrev; }

public:
    /* 0x0 */ TLinkListNode* mNext;
    /* 0x4 */ TLinkListNode* mPrev;
};  // Size: 0x8

struct TNodeLinkList {
    struct iterator {
        iterator() { node = NULL; }
        explicit iterator(TLinkListNode* pNode) { node = pNode; }
        iterator& operator=(const iterator& other) { node = other.node; return *this; }

        iterator& operator++() { node = node->getNext(); return *this; }
        iterator& operator--() { node = node->getPrev(); return *this; }
        iterator operator++(int) { const iterator old(*this); (void)++*this; return old; }
        iterator operator--(int) { const iterator old(*this); (void)--*this; return old; }
        friend bool operator==(iterator a, iterator b) { return a.node == b.node; }
        friend bool operator!=(iterator a, iterator b) { return !(a == b); }

        TLinkListNode* operator->() const { return node; }
        TLinkListNode& operator*() const { return *node; }

    public:
        /* 0x00 */ TLinkListNode* node;
    };

    struct const_iterator {
        explicit const_iterator(TLinkListNode* pNode) { node = pNode; }
        explicit const_iterator(iterator it) { node = it.node; }

        const_iterator& operator++() { node = node->getNext(); return *this; }
        const_iterator& operator--() { node = node->getPrev(); return *this; }
        const_iterator operator++(int) { const const_iterator old(*this); (void)++*this; return old; }
        const_iterator operator--(int) { const const_iterator old(*this); (void)--*this; return old; }
        friend bool operator==(const_iterator a, const_iterator b) { return a.node == b.node; }
        friend bool operator!=(const_iterator a, const_iterator b) { return !(a == b); }

        friend bool operator==(const_iterator a, iterator b) { return a.node == b.node; }
        friend bool operator!=(const_iterator a, iterator b) { return !(a == b); }

        const TLinkListNode* operator->() const { return node; }
        const TLinkListNode& operator*() const { return *node; }

    public:
        /* 0x00 */ TLinkListNode* node;
    };

    TNodeLinkList() : ocObject_() { Initialize_(); }
    ~TNodeLinkList();

    void Initialize_() {
        count = 0;
        ocObject_.mNext = &ocObject_;
        ocObject_.mPrev = &ocObject_;
    }

    iterator begin() { return iterator(ocObject_.getNext()); }
    const_iterator begin() const { return const_iterator(ocObject_.getNext()); }
    iterator end() { return iterator(&ocObject_); }
    const_iterator end() const { return const_iterator((TLinkListNode*)(&ocObject_)); }
    u32 size() const { return count; }
    bool empty() const { return size() == 0; }
    iterator pop_front() { return erase(begin()); }

    iterator erase(JGadget::TNodeLinkList::iterator, JGadget::TNodeLinkList::iterator);
    iterator erase(JGadget::TNodeLinkList::iterator);
    void splice(JGadget::TNodeLinkList::iterator, JGadget::TNodeLinkList&,
                JGadget::TNodeLinkList::iterator);
    iterator Find(const JGadget::TLinkListNode*);
    iterator Insert(JGadget::TNodeLinkList::iterator, JGadget::TLinkListNode*);
    iterator Erase(JGadget::TLinkListNode*);
    void Remove(JGadget::TLinkListNode*);

    bool Iterator_isEnd_(const_iterator it) const { return it.node == &ocObject_; }
    template <typename Predicate>
    void Remove_if(Predicate predicate, TNodeLinkList& tList) {
        iterator it = begin();

        while (!Iterator_isEnd_(const_iterator(it))) {
            if (predicate(*it)) {
                iterator itPrev = it;
                ++it;
                tList.splice(tList.end(), *this, itPrev);
            } else {
                ++it;
            }
        }
    }

    template <typename Predicate>
    void remove_if(Predicate predicate) {
        TNodeLinkList list;
        Remove_if(predicate, list);
    }

public:
    /* 0x00 */ u32 count;
    /* 0x04 */ TLinkListNode ocObject_;
};  // Size: 0xC

template <typename T, int I>
struct TLinkList : public TNodeLinkList {
    TLinkList() : TNodeLinkList() {}

    struct iterator {
        iterator() {}
        explicit iterator(TNodeLinkList::iterator iter) : base(iter) {}

        iterator& operator++() {
            ++base;
            return *this;
        }
        iterator& operator--() {
            --base;
            return *this;
        }
        iterator operator++(int) {
            const iterator old(*this);
            ++*this;
            return old;
        }
        iterator operator--(int) {
            const iterator old(*this);
            --*this;
            return old;
        }
        friend bool operator==(iterator a, iterator b) { return a.base == b.base; }
        friend bool operator!=(iterator a, iterator b) { return !(a == b); }

        T* operator->() const { return Element_toValue(base.operator->()); }
        T& operator*() const { return *operator->(); }

        typedef s32 difference_type;
        typedef T value_type;
        typedef T* pointer;
        typedef T& reference;
        typedef std::bidirectional_iterator_tag iterator_category;

    public:
        /* 0x00 */ TNodeLinkList::iterator base;
    };

    struct const_iterator {
        explicit const_iterator(TNodeLinkList::const_iterator iter) : base(iter) {}
        explicit const_iterator(iterator iter) : base(iter.base) {}

        const_iterator& operator++() {
            ++base;
            return *this;
        }
        const_iterator& operator--() {
            --base;
            return *this;
        }
        const_iterator operator++(int) {
            const const_iterator old(*this);
            ++*this;
            return old;
        }
        const_iterator operator--(int) {
            const const_iterator old(*this);
            --*this;
            return old;
        }
        friend bool operator==(const_iterator a, const_iterator b) { return a.base == b.base; }
        friend bool operator!=(const_iterator a, const_iterator b) { return !(a == b); }

        const T* operator->() const { return Element_toValue(base.operator->()); }
        const T& operator*() const { return *operator->(); }

    public:
        /* 0x00 */ TNodeLinkList::const_iterator base;
    };

    static TLinkListNode* Element_toNode(T* p) {
        JUT_ASSERT_DEBUG(0x2F1, p!=0);
        return reinterpret_cast<TLinkListNode*>(reinterpret_cast<char*>(p) - I);
    }
    static const TLinkListNode* Element_toNode(const T* p) {
        JUT_ASSERT_DEBUG(0x2F6, p!=0);
        return reinterpret_cast<const TLinkListNode*>(reinterpret_cast<const char*>(p) - I);
    }
    static T* Element_toValue(TLinkListNode* p) {
        JUT_ASSERT_DEBUG(0x2FB, p!=0);
        return reinterpret_cast<T*>(reinterpret_cast<char*>(p) + I);
    }
    static const T* Element_toValue(const TLinkListNode* p) {
        JUT_ASSERT_DEBUG(0x300, p!=0);
        return reinterpret_cast<const T*>(reinterpret_cast<const char*>(p) + I);
    }

    iterator Insert(iterator iter, T* element) {
        return iterator(TNodeLinkList::Insert(iter.base, Element_toNode(element)));
    }
    iterator Erase(T* element) { return iterator(TNodeLinkList::Erase(Element_toNode(element))); }

    iterator begin() { return iterator(TNodeLinkList::begin()); }
    const_iterator begin() const { return const_iterator(const_cast<TLinkList*>(this)->begin()); }
    iterator end() { return iterator(TNodeLinkList::end()); }
    const_iterator end() const { return const_iterator(const_cast<TLinkList*>(this)->end()); }
    T& front() { return *begin(); }
    T& back() { return *--end(); }
    void pop_front() { erase(TNodeLinkList::begin()); }
    void Push_front(T* element) { Insert(begin(), element); }
    void Push_back(T* element) { Insert(end(), element); }
    iterator Find(const T* element) {
        return iterator(TNodeLinkList::Find(Element_toNode(element)));
    }
    void Remove(T* element) { TNodeLinkList::Remove(Element_toNode(element)); }
};

template <typename T, int I>
struct TLinkList_factory : public TLinkList<T, I> {
    inline virtual ~TLinkList_factory() = 0;
    virtual T* Do_create() = 0;
    virtual void Do_destroy(T*) = 0;

    void Clear_destroy() {
        while (!this->empty()) {
            T* item = &this->front();
            this->pop_front();
            Do_destroy(item);
        }
    }

    typename TLinkList<T, I>::iterator Erase_destroy(T* param_0) {
        typename TLinkList<T, I>::iterator spC(Erase(param_0));
        Do_destroy(param_0);
        return spC;
    }
};

template <typename T, int I>
TLinkList_factory<T, I>::~TLinkList_factory() {
    JGADGET_ASSERTWARN(934, empty());
}

template <typename T>
struct TEnumerator {
    inline TEnumerator(T _current, T _end)
        : current(_current), end(_end) {}

    bool isEnd() const { return current != end; }
    operator bool() const { return isEnd(); }
    T operator*() {
        T rv = current;
        ++current;
        return rv;
    }

    T current;
    T end;
};

// TEnumerator2 should be the same but there are two issues:
// 1. How to derive the iterator return type for operator* (the debug makes it seem like operator* is called
// so the return value should be what the iterator points to)
// 2. Calling the * operator seems to make functions using TEnumerator<T*> not work. See
// JStudio::TAdaptor::adaptor_setVariableValue_n
// Perhaps template specialization?
template <typename Iterator, typename T>
struct TEnumerator2 {
    inline TEnumerator2(Iterator _current, Iterator _end)
        : current(_current), end(_end) {}

    bool isEnd() const { return current != end; }
    operator bool() const { return isEnd(); }
    T& operator*() {
        T& rv = *current;
        ++current;
        return rv;
    }

    Iterator current;
    Iterator end;
};

template <typename T, int I>
struct TContainerEnumerator : public TEnumerator2<typename TLinkList<T, I>::iterator, T> {
    inline TContainerEnumerator(TLinkList<T, I>* param_0)
        : TEnumerator2<typename TLinkList<T, I>::iterator, T>(param_0->begin(), param_0->end()) {}
};


template <typename T, int I>
struct TContainerEnumerator_const : public TEnumerator2<typename TLinkList<T, I>::const_iterator, const T> {
    inline TContainerEnumerator_const(const TLinkList<T, I>* param_0)
        : TEnumerator2<typename TLinkList<T, I>::const_iterator, const T>(param_0->begin(), param_0->end()) {}
};

namespace {

template <typename T>
class TPRIsEqual_pointer_ {
public:
    TPRIsEqual_pointer_<T>(const T* p) { this->p_ = p; }

    bool operator()(const T& rSrc) const { return &rSrc == this->p_; }

private:
    const T* p_;
};

};  // namespace

};  // namespace JGadget

#endif /* LINKLIST_H */