00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #pragma once
00021
00022 #include <cstdlib>
00023 #include <cassert>
00024 #include <utility>
00025 #include <algorithm>
00026 #include <drizzled/memory/sql_alloc.h>
00027 #include <drizzled/visibility.h>
00028
00029 namespace drizzled {
00030
00031 struct SQL_LIST
00032 {
00033 uint32_t elements;
00034 unsigned char *first;
00035 unsigned char **next;
00036
00037 void clear()
00038 {
00039 elements=0;
00040 first=0;
00041 next= &first;
00042 }
00043
00044 size_t size() const
00045 {
00046 return elements;
00047 }
00048
00049 void link_in_list(unsigned char *element,unsigned char **next_ptr)
00050 {
00051 elements++;
00052 (*next)=element;
00053 next= next_ptr;
00054 *next=0;
00055 }
00056 void save_and_clear(SQL_LIST *save)
00057 {
00058 *save= *this;
00059 clear();
00060 }
00061 void push_front(SQL_LIST *save)
00062 {
00063 *save->next= first;
00064 first= save->first;
00065 elements+= save->elements;
00066 }
00067 void push_back(SQL_LIST *save)
00068 {
00069 if (save->first)
00070 {
00071 *next= save->first;
00072 next= save->next;
00073 elements+= save->elements;
00074 }
00075 }
00076 };
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00094 struct list_node : public memory::SqlAlloc
00095 {
00096 list_node *next;
00097 void *info;
00098 list_node(void *info_par,list_node *next_par)
00099 :next(next_par),info(info_par)
00100 {}
00101 list_node()
00102 {
00103 info= 0;
00104 next= this;
00105 }
00106 };
00107
00108 extern DRIZZLED_API list_node end_of_list;
00109
00110 class base_list :public memory::SqlAlloc
00111 {
00112 protected:
00113 list_node *first,**last;
00114 uint32_t elements;
00115 public:
00116
00117 void clear() { elements=0; first= &end_of_list; last=&first;}
00118 base_list() { clear(); }
00128 base_list(const base_list &tmp) :memory::SqlAlloc()
00129 {
00130 elements= tmp.elements;
00131 first= tmp.first;
00132 last= elements ? tmp.last : &first;
00133 }
00134 base_list(bool) { }
00135 void push_back(void *info)
00136 {
00137 *last = new list_node(info, &end_of_list);
00138 last= &(*last)->next;
00139 elements++;
00140 }
00141 void push_back(void *info, memory::Root& mem)
00142 {
00143 *last = new (mem) list_node(info, &end_of_list);
00144 last= &(*last)->next;
00145 elements++;
00146 }
00147 void push_front(void *info)
00148 {
00149 list_node *node=new list_node(info,first);
00150 if (last == &first)
00151 last= &node->next;
00152 first=node;
00153 elements++;
00154 }
00155 void remove(list_node **prev)
00156 {
00157 list_node *node=(*prev)->next;
00158 if (!--elements)
00159 last= &first;
00160 else if (last == &(*prev)->next)
00161 last= prev;
00162 delete *prev;
00163 *prev=node;
00164 }
00165 void concat(base_list *list)
00166 {
00167 if (!list->is_empty())
00168 {
00169 *last= list->first;
00170 last= list->last;
00171 elements+= list->elements;
00172 }
00173 }
00174 void *pop()
00175 {
00176 if (first == &end_of_list) return 0;
00177 list_node *tmp=first;
00178 first=first->next;
00179 if (!--elements)
00180 last= &first;
00181 return tmp->info;
00182 }
00183 void disjoin(base_list *list)
00184 {
00185 list_node **prev= &first;
00186 list_node *node= first;
00187 list_node *list_first= list->first;
00188 elements=0;
00189 while (node && node != list_first)
00190 {
00191 prev= &node->next;
00192 node= node->next;
00193 elements++;
00194 }
00195 *prev= *last;
00196 last= prev;
00197 }
00198 void prepand(base_list *list)
00199 {
00200 if (!list->is_empty())
00201 {
00202 *list->last= first;
00203 first= list->first;
00204 elements+= list->elements;
00205 }
00206 }
00210 void swap(base_list &rhs)
00211 {
00212 std::swap(first, rhs.first);
00213 std::swap(last, rhs.last);
00214 std::swap(elements, rhs.elements);
00215 }
00216 bool is_empty() { return first == &end_of_list ; }
00217 friend class base_list_iterator;
00218
00219 #ifdef LIST_EXTRA_DEBUG
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 bool check_list(const char *name)
00236 {
00237 list_node *node= first;
00238 uint32_t cnt= 0;
00239
00240 while (node->next != &end_of_list)
00241 {
00242 if (!node->info)
00243 {
00244 return false;
00245 }
00246 node= node->next;
00247 cnt++;
00248 }
00249 if (last != &(node->next))
00250 {
00251 return false;
00252 }
00253 if (cnt+1 != elements)
00254 {
00255 return false;
00256 }
00257 return true;
00258 }
00259 #endif // LIST_EXTRA_DEBUG
00260
00261 protected:
00262 void after(void *info,list_node *node)
00263 {
00264 list_node *new_node=new list_node(info,node->next);
00265 node->next=new_node;
00266 elements++;
00267 if (last == &(node->next))
00268 last= &new_node->next;
00269 }
00270 };
00271
00272
00273 class base_list_iterator
00274 {
00275 protected:
00276 base_list *list;
00277 list_node **el,**prev,*current;
00278 public:
00279 void sublist(base_list &ls, uint32_t elm) const
00280 {
00281 ls.first= *el;
00282 ls.last= list->last;
00283 ls.elements= elm;
00284 }
00285 base_list_iterator()
00286 :list(0), el(0), prev(0), current(0)
00287 {}
00288
00289 base_list_iterator(base_list &list_par, list_node** el0)
00290 :list(&list_par), el(el0), prev(0), current(0)
00291 {
00292 }
00293
00294 void *replace(base_list &new_list)
00295 {
00296 void *ret_value=current->info;
00297 if (!new_list.is_empty())
00298 {
00299 *new_list.last=current->next;
00300 current->info=new_list.first->info;
00301 current->next=new_list.first->next;
00302 if (list->last == ¤t->next && new_list.elements > 1)
00303 list->last= new_list.last;
00304 list->elements+=new_list.elements-1;
00305 }
00306 return ret_value;
00307 }
00308 void remove()
00309 {
00310 list->remove(prev);
00311 el=prev;
00312 current=0;
00313 }
00314 void after(void *element)
00315 {
00316 list->after(element,current);
00317 current=current->next;
00318 el= ¤t->next;
00319 }
00320 };
00321
00322 template <class T> class List_iterator;
00323
00324 template <class T> class List : public base_list
00325 {
00326 public:
00327 typedef List_iterator<T> iterator;
00328
00329 friend class List_iterator<T>;
00330
00331 List() {}
00332 List(const List<T> &tmp) : base_list(tmp) {}
00333 List(const List<T> &tmp, memory::Root *mem_root) : base_list(tmp, mem_root) {}
00334 T& front() {return *static_cast<T*>(first->info); }
00335 T* pop() {return static_cast<T*>(base_list::pop()); }
00336 void concat(List<T> *list) { base_list::concat(list); }
00337 void disjoin(List<T> *list) { base_list::disjoin(list); }
00338 void prepand(List<T> *list) { base_list::prepand(list); }
00339 void delete_elements()
00340 {
00341 list_node *element,*next;
00342 for (element=first; element != &end_of_list; element=next)
00343 {
00344 next=element->next;
00345 delete (T*) element->info;
00346 }
00347 clear();
00348 }
00349
00350 iterator begin()
00351 {
00352 return iterator(*this, &first);
00353 }
00354
00355 size_t size() const
00356 {
00357 return elements;
00358 }
00359
00360 void set_size(size_t v)
00361 {
00362 elements = v;
00363 }
00364 };
00365
00366 template <class T> class List_iterator : public base_list_iterator
00367 {
00368 public:
00369 List_iterator(List<T>& a, list_node** b) : base_list_iterator(a, b) {};
00370 List_iterator() {};
00371 T *operator++(int) { prev=el; current= *el; el= ¤t->next; return (T*)current->info; }
00372 T *replace(T *a) { T* old = (T*) current->info; current->info= a; return old; }
00373 void replace(List<T> &a) { base_list_iterator::replace(a); }
00374 T** ref() { return (T**) ¤t->info; }
00375
00376 T& operator*()
00377 {
00378 return *(T*)current->info;
00379 }
00380
00381 T* operator->()
00382 {
00383 return (T*)current->info;
00384 }
00385 };
00386
00387 }
00388