• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef MAPLE_UTIL_INCLUDE_PTR_LIST_REF_H
17 #define MAPLE_UTIL_INCLUDE_PTR_LIST_REF_H
18 #include <iterator>
19 
20 #include "mpl_logging.h"
21 
22 namespace maple {
23 template <typename T>
24 class PtrListNodeBase {
25 public:
26     PtrListNodeBase() = default;
27     ~PtrListNodeBase() = default;
GetPrev()28     T *GetPrev() const
29     {
30         return prev;
31     }
32 
GetNext()33     T *GetNext() const
34     {
35         return next;
36     }
37 
SetPrev(T * ptr)38     void SetPrev(T *ptr)
39     {
40         prev = ptr;
41     }
42 
SetNext(T * ptr)43     void SetNext(T *ptr)
44     {
45         next = ptr;
46     }
47 
48 private:
49     T *prev = nullptr;
50     T *next = nullptr;
51 };
52 
53 // wrap iterator to run it backwards
54 template <typename T>
55 class ReversePtrListRefIterator {
56 public:
57     using iterator_category = typename std::iterator_traits<T>::iterator_category;
58     using value_type = typename std::iterator_traits<T>::value_type;
59     using difference_type = typename std::iterator_traits<T>::difference_type;
60     using pointer = typename std::iterator_traits<T>::pointer;
61     using reference = typename std::iterator_traits<T>::reference;
62 
63     using iterator_type = T;
64 
ReversePtrListRefIterator()65     ReversePtrListRefIterator() : current() {}
66 
ReversePtrListRefIterator(T right)67     explicit ReversePtrListRefIterator(T right) : current(right) {}
68 
69     template <class Other>
ReversePtrListRefIterator(const ReversePtrListRefIterator<Other> & right)70     ReversePtrListRefIterator(const ReversePtrListRefIterator<Other> &right) : current(right.base())
71     {
72     }
73 
74     template <class Other>
75     ReversePtrListRefIterator &operator=(const ReversePtrListRefIterator<Other> &right)
76     {
77         current = right.base();
78         return (*this);
79     }
80 
81     ~ReversePtrListRefIterator() = default;
82 
base()83     T base() const
84     {
85         return current;
86     }
87 
88     reference operator*() const
89     {
90         return *current;
91     }
92 
93     pointer operator->() const
94     {
95         return &(operator*());
96     }
97 
98     ReversePtrListRefIterator &operator++()
99     {
100         --current;
101         return (*this);
102     }
103 
104     ReversePtrListRefIterator operator++(int)
105     {
106         ReversePtrListRefIterator tmp = *this;
107         --current;
108         return (tmp);
109     }
110 
111     ReversePtrListRefIterator &operator--()
112     {
113         ++current;
114         return (*this);
115     }
116 
117     ReversePtrListRefIterator operator--(int)
118     {
119         ReversePtrListRefIterator tmp = *this;
120         ++current;
121         return (tmp);
122     }
123 
124     bool operator==(const ReversePtrListRefIterator &Iterator) const
125     {
126         return this->base() == Iterator.base();
127     }
128 
129     bool operator!=(const ReversePtrListRefIterator &Iterator) const
130     {
131         return !(*this == Iterator);
132     }
133 
134 protected:
135     T current;
136 };
137 
138 template <typename T>
139 class PtrListRefIterator {
140 public:
141     using iterator_category = std::bidirectional_iterator_tag;
142     using value_type = T;
143     using difference_type = std::ptrdiff_t;
144     using pointer = T *;
145     using reference = T &;
146     using const_pointer = const T *;
147     using const_reference = const T &;
148 
149     PtrListRefIterator() = default;
150 
PtrListRefIterator(pointer ptr)151     explicit PtrListRefIterator(pointer ptr) : ptr(ptr) {}
152 
153     template <typename U, typename = std::enable_if_t<std::is_same<U, std::remove_const_t<T>>::value>>
PtrListRefIterator(const PtrListRefIterator<U> & iter)154     PtrListRefIterator(const PtrListRefIterator<U> &iter) : ptr(iter.d())
155     {
156     }
157 
158     ~PtrListRefIterator() = default;
159 
d()160     pointer d() const
161     {
162         return ptr;
163     }
164 
165     reference operator*() const
166     {
167         return *ptr;
168     }
169 
170     pointer operator->() const
171     {
172         return ptr;
173     }
174 
175     PtrListRefIterator &operator++()
176     {
177         this->ptr = this->ptr->GetNext();
178         return *this;
179     }
180 
181     PtrListRefIterator &operator--()
182     {
183         this->ptr = this->ptr->GetPrev();
184         return *this;
185     }
186 
187     PtrListRefIterator operator++(int)
188     {
189         PtrListRefIterator it = *this;
190         ++(*this);
191         return it;
192     }
193 
194     PtrListRefIterator operator--(int)
195     {
196         PtrListRefIterator it = *this;
197         --(*this);
198         return it;
199     }
200 
201     bool operator==(const PtrListRefIterator &Iterator) const
202     {
203         return this->ptr == Iterator.ptr;
204     }
205 
206     bool operator!=(const PtrListRefIterator &Iterator) const
207     {
208         return !(*this == Iterator);
209     }
210 
211 private:
212     pointer ptr = nullptr;
213 };
214 
215 template <typename T>
216 class PtrListRef {
217 public:
218     using value_type = T;
219     using size_type = size_t;
220     using difference_type = std::ptrdiff_t;
221     using pointer = T *;
222     using const_pointer = const T *;
223     using reference = T &;
224     using const_reference = const T &;
225 
226     using iterator = PtrListRefIterator<T>;
227     using const_iterator = PtrListRefIterator<const T>;
228     using reverse_iterator = ReversePtrListRefIterator<iterator>;
229     using const_reverse_iterator = ReversePtrListRefIterator<const_iterator>;
230 
231     PtrListRef() = default;
PtrListRef(pointer value)232     explicit PtrListRef(pointer value) : first(value), last(value) {}
233 
PtrListRef(pointer first,pointer last)234     PtrListRef(pointer first, pointer last) : first(first), last(last == nullptr ? first : last) {}
235 
236     ~PtrListRef() = default;
237 
begin()238     iterator begin()
239     {
240         return iterator(this->first);
241     }
242 
begin()243     const_iterator begin() const
244     {
245         return const_iterator(this->first);
246     }
247 
cbegin()248     const_iterator cbegin() const
249     {
250         return const_iterator(this->first);
251     }
252 
end()253     iterator end()
254     {
255         return iterator(this->last == nullptr ? nullptr : this->last->GetNext());
256     }
257 
end()258     const_iterator end() const
259     {
260         return const_iterator(this->last == nullptr ? nullptr : this->last->GetNext());
261     }
262 
cend()263     const_iterator cend() const
264     {
265         return const_iterator(this->last == nullptr ? nullptr : this->last->GetNext());
266     }
267 
rbegin()268     reverse_iterator rbegin()
269     {
270         return reverse_iterator(iterator(this->last));
271     }
272 
rbegin()273     const_reverse_iterator rbegin() const
274     {
275         return const_reverse_iterator(const_iterator(this->last));
276     }
277 
crbegin()278     const_reverse_iterator crbegin() const
279     {
280         return const_reverse_iterator(const_iterator(this->last));
281     }
282 
rend()283     reverse_iterator rend()
284     {
285         return reverse_iterator(iterator(this->first == nullptr ? nullptr : this->first->GetPrev()));
286     }
287 
rend()288     const_reverse_iterator rend() const
289     {
290         return const_reverse_iterator(const_iterator(this->first == nullptr ? nullptr : this->first->GetPrev()));
291     }
292 
crend()293     const_reverse_iterator crend() const
294     {
295         return const_reverse_iterator(const_iterator(this->first == nullptr ? nullptr : this->first->GetPrev()));
296     }
297 
front()298     reference front()
299     {
300         return *(this->first);
301     }
302 
back()303     reference back()
304     {
305         return *(this->last);
306     }
307 
front()308     const_reference front() const
309     {
310         return *(this->first);
311     }
312 
back()313     const_reference back() const
314     {
315         return *(this->last);
316     }
317 
empty()318     bool empty() const
319     {
320         return first == nullptr;
321     }
322 
update_front(pointer value)323     void update_front(pointer value)
324     {
325         if (value != nullptr) {
326             value->SetPrev(nullptr);
327         }
328         this->first = value;
329     }
330 
push_front(pointer value)331     void push_front(pointer value)
332     {
333         if (this->last == nullptr) {
334             this->first = value;
335             this->last = value;
336             value->SetPrev(nullptr);
337             value->SetNext(nullptr);
338         } else {
339             DEBUG_ASSERT(this->first != nullptr, "null ptr check");
340             this->first->SetPrev(value);
341             value->SetPrev(nullptr);
342             value->SetNext(this->first);
343             this->first = value;
344         }
345     }
346 
pop_front()347     void pop_front()
348     {
349         if (this->first == nullptr) {
350             return;
351         }
352 
353         this->first = this->first->GetNext();
354         if (this->first != nullptr) {
355             this->first->SetPrev(nullptr);
356         }
357     }
358 
update_back(pointer value)359     void update_back(pointer value)
360     {
361         if (value != nullptr) {
362             value->SetNext(nullptr);
363         }
364         this->last = value;
365     }
366 
push_back(pointer value)367     void push_back(pointer value)
368     {
369         if (this->last == nullptr) {
370             this->first = value;
371             this->last = value;
372             value->SetPrev(nullptr);
373         } else {
374             this->last->SetNext(value);
375             value->SetPrev(this->last);
376             this->last = value;
377         }
378         value->SetNext(nullptr);
379     }
380 
pop_back()381     void pop_back()
382     {
383         if (this->last == nullptr) {
384             return;
385         }
386 
387         if (this->last->GetPrev() == nullptr) {
388             this->first = nullptr;
389             this->last = nullptr;
390         } else {
391             this->last = this->last->GetPrev();
392             this->last->SetNext(nullptr);
393         }
394     }
395 
insert(const_iterator where,pointer value)396     void insert(const_iterator where, pointer value)
397     {
398         if (where == const_iterator(this->first)) {
399             this->push_front(value);
400         } else if (where == this->cend()) {
401             this->push_back(value);
402         } else {
403             // `where` stands for the position, however we made the data and node combined, so a const_cast is needed.
404             auto *ptr = const_cast<T *>(&*where);
405             value->SetPrev(ptr->GetPrev());
406             value->SetNext(ptr);
407             value->GetPrev()->SetNext(value);
408             ptr->SetPrev(value);
409         }
410     }
411 
insert(const_pointer where,pointer value)412     void insert(const_pointer where, pointer value)
413     {
414         this->insert(const_iterator(where), value);
415     }
416 
insertAfter(const_iterator where,pointer value)417     void insertAfter(const_iterator where, pointer value)
418     {
419         if (where == const_iterator(nullptr)) {
420             this->push_front(value);
421         } else if (where == const_iterator(this->last)) {
422             this->push_back(value);
423         } else {
424             // `where` stands for the position, however we made the data and node combined, so a const_cast is needed.
425             auto *ptr = const_cast<T *>(&*where);
426             value->SetPrev(ptr);
427             value->SetNext(ptr->GetNext());
428             value->GetNext()->SetPrev(value);
429             ptr->SetNext(value);
430         }
431     }
432 
insertAfter(const_pointer where,pointer value)433     void insertAfter(const_pointer where, pointer value)
434     {
435         this->insertAfter(const_iterator(where), value);
436     }
437 
splice(const_iterator where,PtrListRef & other)438     void splice(const_iterator where, PtrListRef &other)
439     {
440         DEBUG_ASSERT(!other.empty(), "NYI");
441         if (this->empty()) {
442             this->first = &(other.front());
443             this->last = &(other.back());
444         } else if (where == this->cend() || where == const_iterator(this->last)) {
445             DEBUG_ASSERT(this->last != nullptr, "null ptr check");
446             this->last->SetNext(&(other.front()));
447             other.front().SetPrev(this->last);
448             this->last = &(other.back());
449         } else {
450             DEBUG_ASSERT(to_ptr(where) != nullptr, "null ptr check");
451             DEBUG_ASSERT(where->GetNext() != nullptr, "null ptr check");
452             // `where` stands for the position, however we made the data and node combined, so a const_cast is needed.
453             auto *ptr = const_cast<T *>(&*where);
454             other.front().SetPrev(ptr);
455             other.back().SetNext(ptr->GetNext());
456             ptr->GetNext()->SetPrev(&(other.back()));
457             ptr->SetNext(&(other.front()));
458         }
459     }
460 
splice(const_pointer where,PtrListRef & other)461     void splice(const_pointer where, PtrListRef &other)
462     {
463         splice(const_iterator(where), other);
464     }
465 
clear()466     void clear()
467     {
468         this->first = nullptr;
469         this->last = nullptr;
470     }
471 
erase(const_iterator where)472     iterator erase(const_iterator where)
473     {
474         if (where == this->cbegin() && where == this->rbegin().base()) {
475             this->first = nullptr;
476             this->last = nullptr;
477         } else if (where == this->cbegin()) {
478             // `where` stands for the position, however we made the data and node combined, so a const_cast is needed.
479             auto *ptr = const_cast<T *>(&*where);
480             this->first = ptr->GetNext();
481             DEBUG_ASSERT(this->first != nullptr, "null ptr check");
482             this->first->SetPrev(nullptr);
483         } else if (where == this->rbegin().base()) {
484             pop_back();
485         } else {
486             DEBUG_ASSERT(where->GetPrev() != nullptr, "null ptr check");
487             // `where` stands for the position, however we made the data and node combined, so a const_cast is needed.
488             auto *ptr = const_cast<T *>(&*where);
489             ptr->GetPrev()->SetNext(ptr->GetNext());
490             ptr->GetNext()->SetPrev(ptr->GetPrev());
491         }
492         return iterator(nullptr);
493     }
494 
erase(const_pointer where)495     iterator erase(const_pointer where)
496     {
497         return this->erase(const_iterator(where));
498     }
499 
set_first(T * f)500     void set_first(T *f)
501     {
502         this->first = f;
503     }
504 
set_last(T * f)505     void set_last(T *f)
506     {
507         this->last = f;
508     }
509 
510 private:
511     T *first = nullptr;
512     T *last = nullptr;
513 };
514 
515 template <typename Iterator>
516 auto to_ptr(Iterator it) -> typename std::iterator_traits<Iterator>::pointer
517 {
518     return it.d();
519 }
520 
521 template <typename Iterator>
522 auto to_ptr(ReversePtrListRefIterator<Iterator> it) -> typename std::iterator_traits<Iterator>::pointer
523 {
524     return it.base().d();
525 }
526 }  // namespace maple
527 #endif  // MAPLE_UTIL_INCLUDE_PTR_LIST_REF_H
528