1 /*
2   Copyright (c) DataStax, Inc.
3 
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7 
8   http://www.apache.org/licenses/LICENSE-2.0
9 
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15 */
16 
17 #ifndef DATASTAX_INTERNAL_LIST_HPP
18 #define DATASTAX_INTERNAL_LIST_HPP
19 
20 #include "macros.hpp"
21 
22 #include <stddef.h>
23 
24 namespace datastax { namespace internal {
25 
26 template <class T>
27 class List {
28 public:
29   class Node {
30   public:
Node()31     Node()
32         : next_(NULL)
33         , prev_(NULL) {}
34 
35   private:
36     friend class List;
37     Node* next_;
38     Node* prev_;
39   };
40 
41   template <class S>
42   class Iterator {
43   public:
has_next()44     bool has_next() { return curr_ != end_; }
45 
next()46     S* next() {
47       Node* temp = curr_;
48       curr_ = curr_->next_;
49       return static_cast<T*>(temp);
50     }
51 
52   private:
53     friend class List;
Iterator(Node * begin,Node * end)54     Iterator(Node* begin, Node* end)
55         : curr_(begin)
56         , end_(end) {}
57 
58     Node* curr_;
59     Node* end_;
60   };
61 
62 public:
List()63   List()
64       : size_(0) {
65     data_.next_ = &data_;
66     data_.prev_ = &data_;
67   }
68 
69   void add_to_front(T* node);
70   void add_to_back(T* node);
71   void remove(T* node);
72 
front()73   T* front() {
74     if (is_empty()) return NULL;
75     return static_cast<T*>(data_.next_);
76   }
77 
back()78   T* back() {
79     if (is_empty()) return NULL;
80     return static_cast<T*>(data_.prev_);
81   }
82 
pop_front()83   T* pop_front() {
84     T* first = front();
85     if (first != NULL) remove(first);
86     return first;
87   }
88 
size() const89   size_t size() const { return size_; }
is_empty()90   bool is_empty() { return data_.next_ == &data_; }
iterator()91   Iterator<T> iterator() { return Iterator<T>(data_.next_, &data_); }
92 
93 private:
94   void insert_before(Node* pos, Node* node);
95   void insert_after(Node* pos, Node* node);
96 
97   Node data_;
98   size_t size_;
99 
100 private:
101   DISALLOW_COPY_AND_ASSIGN(List);
102 };
103 
104 template <class T>
add_to_front(T * node)105 void List<T>::add_to_front(T* node) {
106   insert_after(&data_, node);
107 }
108 
109 template <class T>
add_to_back(T * node)110 void List<T>::add_to_back(T* node) {
111   insert_before(&data_, node);
112 }
113 
114 template <class T>
remove(T * node)115 void List<T>::remove(T* node) {
116   size_--;
117   node->prev_->next_ = node->next_;
118   node->next_->prev_ = node->prev_;
119   node->next_ = NULL;
120   node->prev_ = NULL;
121 }
122 
123 template <class T>
insert_after(Node * pos,Node * node)124 void List<T>::insert_after(Node* pos, Node* node) {
125   size_++;
126   pos->next_->prev_ = node;
127   node->prev_ = pos;
128   node->next_ = pos->next_;
129   pos->next_ = node;
130 }
131 
132 template <class T>
insert_before(Node * pos,Node * node)133 void List<T>::insert_before(Node* pos, Node* node) {
134   size_++;
135   pos->prev_->next_ = node;
136   node->next_ = pos;
137   node->prev_ = pos->prev_;
138   pos->prev_ = node;
139 }
140 
141 }} // namespace datastax::internal
142 
143 #endif
144