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