Changeset c71c171 in mainline
- Timestamp:
- 2018-07-05T21:41:21Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 73066e61
- Parents:
- de53138
- git-author:
- Dzejrou <dzejrou@…> (2018-04-20 00:18:51)
- git-committer:
- Dzejrou <dzejrou@…> (2018-07-05 21:41:21)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/cpp/include/impl/list.hpp
rde53138 rc71c171 30 30 #define LIBCPP_LIST 31 31 32 #include <cstdlib> 32 33 #include <iterator> 33 34 #include <memory> 34 35 #include <utility> 35 36 36 namespace cpp37 namespace std 37 38 { 39 template<class T, class Allocator = allocator<T>> 40 class list; 41 38 42 namespace aux 39 43 { … … 44 48 list_node* next; 45 49 list_node* prev; 50 51 template<class... Args> 52 list_node(Args&&... args) 53 : value{forward<Args>(args)...}, 54 next{this}, prev{this} 55 { 56 next = this; 57 prev = this; 58 } 59 60 list_node(const T& val) 61 : value{val}, next{this}, prev{this} 62 { 63 next = this; 64 prev = this; 65 } 66 67 list_node(T&& val) 68 : value{forward<T>(val)}, next{}, prev{} 69 { 70 next = this; 71 prev = this; 72 } 73 74 void append(list_node* node) 75 { 76 node->next = next; 77 node->prev = this; 78 next->prev = node; 79 next = node; 80 } 81 82 void prepend(list_node* node) 83 { 84 node->next = this; 85 node->prev = prev; 86 prev->next = node; 87 prev = node; 88 } 46 89 }; 90 91 template<class T> 92 class list_const_iterator; 93 94 template<class T> 95 class list_iterator 96 { 97 public: 98 using reference = typename list<T>::reference; 99 100 list_iterator(list_node<T>* node = nullptr) 101 : current_{node} 102 { /* DUMMY BODY */ } 103 104 reference operator*() 105 { 106 return current_->value; 107 } 108 109 list_iterator& operator++() 110 { 111 if (current_) 112 current_ = current_->next; 113 114 return *this; 115 } 116 117 list_iterator operator++(int) 118 { 119 auto bckp = current_; 120 121 if (current_) 122 current_ = current_->next; 123 124 return list_iterator{bckp}; 125 } 126 127 list_iterator& operator--() 128 { 129 if (current_) 130 current_ = current_->prev; 131 132 return *this; 133 } 134 135 list_iterator operator--(int) 136 { 137 auto bckp = current_; 138 139 if (current_) 140 current_ = current_->prev; 141 142 return list_iterator{bckp}; 143 } 144 145 list_node<T>* node() 146 { 147 return current_; 148 } 149 150 private: 151 list_node<T>* current_; 152 }; 153 154 // TODO: const iterator, iterator must be convertible to const iterator 47 155 } 48 156 … … 51 159 */ 52 160 53 template<class T, class Allocator = allocator<T>>161 template<class T, class Allocator> 54 162 class list 55 163 { … … 57 165 using value_type = T; 58 166 using reference = value_type&; 59 using const_reference = value_type&;167 using const_reference = const value_type&; 60 168 using allocator_type = Allocator; 61 169 62 using iterator = void;63 using const_iterator = void;64 using size_type = void;65 using difference_type = void;170 using iterator = aux::list_iterator<value_type>; 171 using const_iterator = aux::list_const_iterator<value_type>; 172 using size_type = size_t; 173 using difference_type = ptrdiff_t; 66 174 67 175 using pointer = typename allocator_traits<allocator_type>::pointer; … … 69 177 70 178 using reverse_iterator = std::reverse_iterator<iterator>; 71 using const_reverse_iterator = std:: const_reverse_iterator<iterator>;179 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 72 180 73 181 /** … … 80 188 81 189 explicit list(const allocator_type& alloc) 82 : allocator_{alloc}, head_{nullptr} 190 : allocator_{alloc}, head_{nullptr}, size_{} 83 191 { /* DUMMY BODY */ } 84 192 85 193 explicit list(size_type n, const allocator_type& alloc = allocator_type{}) 86 : allocator_{alloc}, head_{nullptr} 87 { 88 for (size_type i = 0; i < n; ++i) 89 { 90 auto node = append_new_(); 91 allocator_.construct(&node->value); 92 } 194 : allocator_{alloc}, head_{nullptr}, size_{} 195 { 196 init_( 197 aux::insert_iterator<value_type>{value_type{}}, 198 aux::insert_iterator<value_type>{size_} 199 ); 93 200 } 94 201 95 202 list(size_type n, const value_type& val, 96 203 const allocator_type& alloc = allocator_type{}) 97 : allocator_{alloc}, head_{nullptr} 98 { 99 for (size_type i = 0; i < n; ++i) 100 { 101 auto node = append_new_(); 102 allocator_.construct(&node->value, val); 103 } 204 : allocator_{alloc}, head_{nullptr}, size_{} 205 { 206 init_( 207 aux::insert_iterator<value_type>{val}, 208 aux::insert_iterator<value_type>{n} 209 ); 104 210 } 105 211 … … 107 213 list(InputIterator first, InputIterator last, 108 214 const allocator_type& alloc = allocator_type{}) 109 : allocator_{alloc}, head_{nullptr} 215 : allocator_{alloc}, head_{nullptr}, size_{} 216 { 217 init_(first, last); 218 } 219 220 list(const list& other) 221 : list{other, other.allocator_} 222 { /* DUMMY BODY */ } 223 224 list(list&& other) 225 : allocator_{move(other.allocator_)}, 226 head_{move(other.head_)}, 227 size_{move(other.size_)} 228 { 229 other.head_ = nullptr; 230 } 231 232 list(const list& other, const allocator_type alloc) 233 : allocator_{alloc}, head_{nullptr}, size_{other.size_} 234 { 235 init_(other.begin(), other.end()); 236 } 237 238 list(list&& other, const allocator_type& alloc) 239 : allocator_{alloc}, 240 head_{move(other.head_)}, 241 size_{move(other.size_)} 242 { 243 other.head_ = nullptr; 244 } 245 246 list(initializer_list<value_type> init, const allocator_type& alloc) 247 : allocator_{alloc}, head_{nullptr}, size_{} 248 { 249 init_(init.begin(), init.end()); 250 } 251 252 ~list() 253 { 254 fini_(); 255 } 256 257 list& operator=(const list& other) 258 { 259 fini_(); 260 261 allocator_ = other.allocator_; 262 263 init_(other.begin(), other.end()); 264 } 265 266 list& operator=(list&& other) 267 noexcept(allocator_traits<allocator_type>::is_always_equal::value) 268 { 269 fini_(); 270 271 allocator_ = move(other.allocator_); 272 273 init_( 274 make_move_iterator(other.begin()), 275 make_move_iterator(other.end()) 276 ); 277 } 278 279 list& operator=(initializer_list<value_type> init) 280 { 281 fini_(); 282 283 init_(init.begin(), init.end()); 284 } 285 286 template<class InputIterator> 287 void assign(InputIterator first, InputIterator last) 288 { 289 fini_(); 290 291 init_(first, last); 292 } 293 294 void assign(size_type n, const value_type& val) 295 { 296 fini_(); 297 298 init_( 299 aux::insert_iterator<value_type>{val}, 300 aux::insert_iterator<value_type>{n} 301 ); 302 } 303 304 void assign(initializer_list<value_type> init) 305 { 306 fini_(); 307 308 init_(init.begin(), init.end()); 309 } 310 311 allocator_type get_allocator() const noexcept 312 { 313 return allocator_; 314 } 315 316 iterator begin() noexcept 317 { 318 return iterator{head_}; 319 } 320 321 const_iterator begin() const noexcept 322 { 323 return cbegin(); 324 } 325 326 iterator end() noexcept 327 { 328 return iterator{}; 329 } 330 331 const_iterator end() const noexcept 332 { 333 return cend(); 334 } 335 336 reverse_iterator rbegin() noexcept 337 { 338 return make_reverse_iterator(end()); 339 } 340 341 const_reverse_iterator rbegin() const noexcept 342 { 343 return make_reverse_iterator(cend()); 344 } 345 346 reverse_iterator rend() noexcept 347 { 348 return make_reverse_iterator(begin()); 349 } 350 351 const_reverse_iterator rend() const noexcept 352 { 353 return make_reverse_iterator(cbegin()); 354 } 355 356 const_iterator cbegin() const noexcept 357 { 358 return const_iterator{head_}; 359 } 360 361 const_iterator cend() const noexcept 362 { 363 return const_iterator{}; 364 } 365 366 const_reverse_iterator crbegin() const noexcept 367 { 368 return rbegin(); 369 } 370 371 /** 372 * 23.3.5.3, capacity: 373 */ 374 375 bool empty() const noexcept 376 { 377 return size_ == 0; 378 } 379 380 size_type size() const noexcept 381 { 382 return size_; 383 } 384 385 size_type max_size() const noexcept 386 { 387 return allocator_traits<allocator_type>::max_size(allocator_); 388 } 389 390 void resize(size_type sz) 391 { 392 // TODO: implement 393 } 394 395 void resize(size_type sz, const value_type& val) 396 { 397 // TODO: implement 398 } 399 400 reference front() 401 { 402 // TODO: bounds checking 403 return head_->value; 404 } 405 406 const_reference front() const 407 { 408 // TODO: bounds checking 409 return head_->value; 410 } 411 412 reference back() 413 { 414 // TODO: bounds checking 415 return head_->prev->value; 416 } 417 418 const_reference back() const 419 { 420 // TODO: bounds checking 421 return head_->prev->value; 422 } 423 424 /** 425 * 23.3.5.4, modifiers: 426 * Note: These should have no effect when an exception 427 * is thrown while inserting, but since the only 428 * functions that can throw are the constructors, 429 * creating the node before any modifications to the 430 * list itself will satisfy this requirement. 431 */ 432 433 template<class... Args> 434 void emplace_front(Args&&... args) 435 { 436 prepend_new_(forward<Args>(args)...); 437 } 438 439 void pop_front() 440 { 441 if (head_) 442 { 443 --size_; 444 445 if (head_->next == head_) 446 { 447 delete head_; 448 head_ = nullptr; 449 } 450 else 451 { 452 auto tmp = head_; 453 head_->prev->next = head_->next; 454 head_->next->prev = head_->prev; 455 head_ = head_->next; 456 457 delete tmp; 458 } 459 } 460 } 461 462 template<class... Args> 463 void emplace_back(Args&&... args) 464 { 465 append_new_(forward<Args>(args)...); 466 } 467 468 void push_front(const value_type& value) 469 { 470 prepend_new_(value); 471 } 472 473 void push_front(value_type&& value) 474 { 475 prepend_new_(forward<value_type>(value)); 476 } 477 478 void push_back(const value_type& value) 479 { 480 append_new_(value); 481 } 482 483 void push_back(value_type&& value) 484 { 485 append_new_(forward<value_type>(value)); 486 } 487 488 void pop_back() 489 { 490 if (head_) 491 { 492 --size_; 493 auto target = head_->prev; 494 495 if (!target) 496 { 497 delete head_; 498 head_ = nullptr; 499 } 500 else 501 { 502 auto tmp = target; 503 target->prev->next = target->next; 504 target->next->prev = target->prev; 505 target = target->next; 506 507 delete tmp; 508 } 509 } 510 } 511 512 /* private: */ 513 allocator_type allocator_; 514 aux::list_node<value_type>* head_; 515 size_type size_; 516 517 template<class InputIterator> 518 void init_(InputIterator first, InputIterator last) 110 519 { 111 520 while (first != last) … … 116 525 } 117 526 118 list(const list& other) 119 : allocator_{other.allocator_}, head_{nullptr} 120 { 121 auto tmp = other.head_; 122 123 while (tmp->next != other.head_) 124 { 125 auto node = append_new_(); 126 allocator_.construct(&node->value, tmp->value); 127 } 128 } 129 130 list(list&& other) 131 { 132 // TODO: 133 } 134 135 private: 136 allocator_type allocator_; 137 list_node<T>* head_; 138 139 list_node<T>* append_new_() 140 { 141 auto node = new aux::list_node<T>{}; 527 void fini_() 528 { 529 if (!head_) 530 return; 531 532 for (size_type i = size_type{}; i < size_; ++i) 533 { 534 head_ = head_->next; 535 delete head_->prev; 536 } 537 538 head_ = nullptr; 539 size_ = size_type{}; 540 } 541 542 template<class... Args> 543 aux::list_node<value_type>* append_new_(Args&&... args) 544 { 545 auto node = new aux::list_node<value_type>{forward<Args>(args)...}; 142 546 auto last = get_last_(); 143 547 … … 145 549 head_ = node; 146 550 else 147 { 148 last->next = node; 149 node->prev = last; 150 151 node->next = head_; 152 head_->prev = node; 153 } 551 last->append(node); 552 553 ++size_; 154 554 155 555 return node; 156 556 } 157 557 158 list_node<T>* get_last_() 558 template<class... Args> 559 aux::list_node<value_type>* prepend_new_(Args&&... args) 560 { 561 auto node = new aux::list_node<value_type>{forward<Args>(args)...}; 562 563 if (!head_) 564 head_ = node; 565 else 566 { 567 head_->prepend(node); 568 head_ = head_->prev; 569 } 570 571 ++size_; 572 573 return node; 574 } 575 576 aux::list_node<value_type>* get_last_() 159 577 { 160 578 if (!head_) 161 579 return nullptr; 162 580 163 auto node = head_; 164 165 while (node->next != head_) 166 node = node->next; 581 return head_->prev; 582 } 583 584 template<class InputIterator> 585 void insert_range_(InputIterator first, InputIterator last, 586 aux::list_node<value_type>* where = nullptr) 587 { 588 if (first == last) 589 return; 590 591 if (!where) 592 where = get_last_(); 593 594 while (first != last) 595 { 596 where->append(new aux::list_node<value_type>{*first++}); 597 where = where->next; 598 } 167 599 } 168 600 };
Note:
See TracChangeset
for help on using the changeset viewer.