MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sql_plist.h
1 #ifndef SQL_PLIST_H
2 #define SQL_PLIST_H
3 /* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software Foundation,
16  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
17 
18 
19 #include <my_global.h>
20 
21 template <typename T, typename L>
22 class I_P_List_iterator;
24 template <typename T> class I_P_List_no_push_back;
25 
26 
64 template <typename T, typename B,
65  typename C = I_P_List_null_counter,
66  typename I = I_P_List_no_push_back<T> >
67 class I_P_List : public C, public I
68 {
69  T *m_first;
70 
71  /*
72  Do not prohibit copying of I_P_List object to simplify their usage in
73  backup/restore scenarios. Note that performing any operations on such
74  is a bad idea.
75  */
76 public:
77  I_P_List() : I(&m_first), m_first(NULL) {};
78  inline void empty() { m_first= NULL; C::reset(); I::set_last(&m_first); }
79  inline bool is_empty() const { return (m_first == NULL); }
80  inline void push_front(T* a)
81  {
82  *B::next_ptr(a)= m_first;
83  if (m_first)
84  *B::prev_ptr(m_first)= B::next_ptr(a);
85  else
86  I::set_last(B::next_ptr(a));
87  m_first= a;
88  *B::prev_ptr(a)= &m_first;
89  C::inc();
90  }
91  inline void push_back(T *a)
92  {
93  T **last= I::get_last();
94  *B::next_ptr(a)= *last;
95  *last= a;
96  *B::prev_ptr(a)= last;
97  I::set_last(B::next_ptr(a));
98  C::inc();
99  }
100  inline void insert_after(T *pos, T *a)
101  {
102  if (pos == NULL)
103  push_front(a);
104  else
105  {
106  *B::next_ptr(a)= *B::next_ptr(pos);
107  *B::prev_ptr(a)= B::next_ptr(pos);
108  *B::next_ptr(pos)= a;
109  if (*B::next_ptr(a))
110  {
111  T *old_next= *B::next_ptr(a);
112  *B::prev_ptr(old_next)= B::next_ptr(a);
113  }
114  else
115  I::set_last(B::next_ptr(a));
116  C::inc();
117  }
118  }
119  inline void remove(T *a)
120  {
121  T *next= *B::next_ptr(a);
122  if (next)
123  *B::prev_ptr(next)= *B::prev_ptr(a);
124  else
125  I::set_last(*B::prev_ptr(a));
126  **B::prev_ptr(a)= next;
127  C::dec();
128  }
129  inline T* front() { return m_first; }
130  inline const T *front() const { return m_first; }
131  inline T* pop_front()
132  {
133  T *result= front();
134 
135  if (result)
136  remove(result);
137 
138  return result;
139  }
140  void swap(I_P_List<T, B, C> &rhs)
141  {
142  swap_variables(T *, m_first, rhs.m_first);
143  I::swap(rhs);
144  if (m_first)
145  *B::prev_ptr(m_first)= &m_first;
146  else
147  I::set_last(&m_first);
148  if (rhs.m_first)
149  *B::prev_ptr(rhs.m_first)= &rhs.m_first;
150  else
151  I::set_last(&rhs.m_first);
152  C::swap(rhs);
153  }
154  typedef B Adapter;
155  typedef I_P_List<T, B, C, I> Base;
158 #ifndef _lint
159  friend class I_P_List_iterator<T, Base>;
160  friend class I_P_List_iterator<const T, Base>;
161 #endif
162 };
163 
164 
169 template <typename T, typename L>
171 {
172  const L *list;
173  T *current;
174 public:
175  I_P_List_iterator(const L &a)
176  : list(&a), current(a.m_first) {}
177  I_P_List_iterator(const L &a, T* current_arg)
178  : list(&a), current(current_arg) {}
179  inline void init(const L &a)
180  {
181  list= &a;
182  current= a.m_first;
183  }
184  inline T* operator++(int)
185  {
186  T *result= current;
187  if (result)
188  current= *L::Adapter::next_ptr(current);
189  return result;
190  }
191  inline T* operator++()
192  {
193  current= *L::Adapter::next_ptr(current);
194  return current;
195  }
196  inline void rewind()
197  {
198  current= list->m_first;
199  }
200 };
201 
202 
208 template <typename T, T* T::*next, T** T::*prev>
210 {
211  static inline T **next_ptr(T *el) { return &(el->*next); }
212  static inline const T* const* next_ptr(const T *el) { return &(el->*next); }
213  static inline T ***prev_ptr(T *el) { return &(el->*prev); }
214 };
215 
216 
223 {
224 protected:
225  void reset() {}
226  void inc() {}
227  void dec() {}
228  void swap(I_P_List_null_counter &rhs) {}
229 };
230 
231 
238 {
239  uint m_counter;
240 protected:
241  I_P_List_counter() : m_counter (0) {}
242  void reset() {m_counter= 0;}
243  void inc() {m_counter++;}
244  void dec() {m_counter--;}
245  void swap(I_P_List_counter &rhs)
246  { swap_variables(uint, m_counter, rhs.m_counter); }
247 public:
248  uint elements() const { return m_counter; }
249 };
250 
251 
257 template <typename T> class I_P_List_no_push_back
258 {
259 protected:
260  I_P_List_no_push_back(T **a) {};
261  void set_last(T **a) {}
262  /*
263  T** get_last() const method is intentionally left unimplemented
264  in order to prohibit usage of push_back() method in lists which
265  use this policy.
266  */
267  void swap(I_P_List_no_push_back<T> &rhs) {}
268 };
269 
270 
276 template <typename T> class I_P_List_fast_push_back
277 {
278  T **m_last;
279 protected:
280  I_P_List_fast_push_back(T **a) : m_last(a) { };
281  void set_last(T **a) { m_last= a; }
282  T** get_last() const { return m_last; }
283  void swap(I_P_List_fast_push_back<T> &rhs)
284  { swap_variables(T**, m_last, rhs.m_last); }
285 };
286 
287 #endif