~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_list.h

  • Committer: Mark Atwood
  • Date: 2011-10-27 05:08:12 UTC
  • mfrom: (2445.1.11 rf)
  • Revision ID: me@mark.atwood.name-20111027050812-1icvs72lb0u4xdc4
mergeĀ lp:~olafvdspek/drizzle/refactor8

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#ifndef DRIZZLED_SQL_LIST_H
21
 
#define DRIZZLED_SQL_LIST_H
22
 
 
 
20
#pragma once
23
21
 
24
22
#include <cstdlib>
25
23
#include <cassert>
26
24
#include <utility>
27
25
#include <algorithm>
28
 
#include "drizzled/memory/sql_alloc.h"
29
 
 
30
 
namespace drizzled
 
26
#include <drizzled/memory/sql_alloc.h>
 
27
#include <drizzled/visibility.h>
 
28
 
 
29
namespace drizzled {
 
30
 
 
31
struct SQL_LIST 
31
32
{
32
 
 
33
 
/** Struct to handle simple linked lists. */
34
 
typedef struct st_sql_list {
35
33
  uint32_t elements;
36
34
  unsigned char *first;
37
35
  unsigned char **next;
38
36
 
39
 
  st_sql_list() {}                              /* Remove gcc warning */
40
 
  inline void empty()
 
37
  void clear()
41
38
  {
42
39
    elements=0;
43
40
    first=0;
44
41
    next= &first;
45
42
  }
46
 
  inline void link_in_list(unsigned char *element,unsigned char **next_ptr)
 
43
 
 
44
  size_t size() const
 
45
  {
 
46
    return elements;
 
47
  }
 
48
 
 
49
  void link_in_list(unsigned char *element,unsigned char **next_ptr)
47
50
  {
48
51
    elements++;
49
52
    (*next)=element;
50
53
    next= next_ptr;
51
54
    *next=0;
52
55
  }
53
 
  inline void save_and_clear(struct st_sql_list *save)
 
56
  void save_and_clear(SQL_LIST *save)
54
57
  {
55
58
    *save= *this;
56
 
    empty();
 
59
    clear();
57
60
  }
58
 
  inline void push_front(struct st_sql_list *save)
 
61
  void push_front(SQL_LIST *save)
59
62
  {
60
63
    *save->next= first;                         /* link current list last */
61
64
    first= save->first;
62
65
    elements+= save->elements;
63
66
  }
64
 
  inline void push_back(struct st_sql_list *save)
 
67
  void push_back(SQL_LIST *save)
65
68
  {
66
69
    if (save->first)
67
70
    {
70
73
      elements+= save->elements;
71
74
    }
72
75
  }
73
 
} SQL_LIST;
 
76
};
74
77
 
75
78
/*
76
79
  Basic single linked list
102
105
  }
103
106
};
104
107
 
105
 
 
106
 
extern list_node end_of_list;
 
108
extern DRIZZLED_API list_node end_of_list;
107
109
 
108
110
class base_list :public memory::SqlAlloc
109
111
{
110
112
protected:
111
113
  list_node *first,**last;
112
 
 
 
114
  uint32_t elements;
113
115
public:
114
 
  uint32_t elements;
115
116
 
116
 
  inline void empty() { elements=0; first= &end_of_list; last=&first;}
117
 
  inline base_list() { empty(); }
 
117
  void clear() { elements=0; first= &end_of_list; last=&first;}
 
118
  base_list() { clear(); }
118
119
  /**
119
120
    This is a shallow copy constructor that implicitly passes the ownership
120
121
    from the source list to the new instance. The old instance is not
124
125
    relies on this behaviour. This logic is quite tricky: please do not use
125
126
    it in any new code.
126
127
  */
127
 
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
 
128
  base_list(const base_list &tmp) :memory::SqlAlloc()
128
129
  {
129
130
    elements= tmp.elements;
130
131
    first= tmp.first;
131
132
    last= elements ? tmp.last : &first;
132
133
  }
133
 
  inline base_list(bool) { }
134
 
  inline bool push_back(void *info)
135
 
  {
136
 
    if (((*last)=new list_node(info, &end_of_list)))
137
 
    {
138
 
      last= &(*last)->next;
139
 
      elements++;
140
 
      return 0;
141
 
    }
142
 
    return 1;
143
 
  }
144
 
  inline bool push_back(void *info, memory::Root *mem_root)
145
 
  {
146
 
    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
147
 
    {
148
 
      last= &(*last)->next;
149
 
      elements++;
150
 
      return 0;
151
 
    }
152
 
    return 1;
153
 
  }
154
 
  inline bool push_front(void *info)
 
134
  base_list(bool) { }
 
135
  void push_back(void *info)
 
136
  {
 
137
    *last = new list_node(info, &end_of_list);
 
138
    last= &(*last)->next;
 
139
    elements++;
 
140
  }
 
141
  void push_back(void *info, memory::Root& mem)
 
142
  {
 
143
    *last = new (mem) list_node(info, &end_of_list);
 
144
    last= &(*last)->next;
 
145
    elements++;
 
146
  }
 
147
  void push_front(void *info)
155
148
  {
156
149
    list_node *node=new list_node(info,first);
157
 
    if (node)
158
 
    {
159
 
      if (last == &first)
160
 
        last= &node->next;
 
150
    if (last == &first)
 
151
                        last= &node->next;
161
152
      first=node;
162
153
      elements++;
163
 
      return 0;
164
 
    }
165
 
    return 1;
166
154
  }
167
155
  void remove(list_node **prev)
168
156
  {
174
162
    delete *prev;
175
163
    *prev=node;
176
164
  }
177
 
  inline void concat(base_list *list)
 
165
  void concat(base_list *list)
178
166
  {
179
167
    if (!list->is_empty())
180
168
    {
183
171
      elements+= list->elements;
184
172
    }
185
173
  }
186
 
  inline void *pop(void)
 
174
  void *pop()
187
175
  {
188
176
    if (first == &end_of_list) return 0;
189
177
    list_node *tmp=first;
192
180
      last= &first;
193
181
    return tmp->info;
194
182
  }
195
 
  inline void disjoin(base_list *list)
 
183
  void disjoin(base_list *list)
196
184
  {
197
185
    list_node **prev= &first;
198
186
    list_node *node= first;
207
195
    *prev= *last;
208
196
    last= prev;
209
197
  }
210
 
  inline void prepand(base_list *list)
 
198
  void prepand(base_list *list)
211
199
  {
212
200
    if (!list->is_empty())
213
201
    {
219
207
  /**
220
208
    Swap two lists.
221
209
  */
222
 
  inline void swap(base_list &rhs)
 
210
  void swap(base_list &rhs)
223
211
  {
224
212
    std::swap(first, rhs.first);
225
213
    std::swap(last, rhs.last);
226
214
    std::swap(elements, rhs.elements);
227
215
  }
228
 
  inline list_node* last_node() { return *last; }
229
 
  inline list_node* first_node() { return first;}
230
 
  inline void *head() { return first->info; }
231
 
  inline void **head_ref() { return first != &end_of_list ? &first->info : 0; }
232
 
  inline bool is_empty() { return first == &end_of_list ; }
233
 
  inline list_node *last_ref() { return &end_of_list; }
 
216
  bool is_empty() { return first == &end_of_list ; }
234
217
  friend class base_list_iterator;
235
 
  friend class error_list;
236
 
  friend class error_list_iterator;
237
218
 
238
219
#ifdef LIST_EXTRA_DEBUG
239
220
  /*
253
234
 
254
235
  bool check_list(const char *name)
255
236
  {
256
 
    base_list *list= this;
257
237
    list_node *node= first;
258
238
    uint32_t cnt= 0;
259
239
 
295
275
protected:
296
276
  base_list *list;
297
277
  list_node **el,**prev,*current;
298
 
  void sublist(base_list &ls, uint32_t elm)
 
278
public:
 
279
  void sublist(base_list &ls, uint32_t elm) const
299
280
  {
300
281
    ls.first= *el;
301
282
    ls.last= list->last;
302
283
    ls.elements= elm;
303
284
  }
304
 
public:
305
285
  base_list_iterator()
306
286
    :list(0), el(0), prev(0), current(0)
307
287
  {}
308
288
 
309
 
  base_list_iterator(base_list &list_par)
310
 
  { init(list_par); }
311
 
 
312
 
  inline void init(base_list &list_par)
313
 
  {
314
 
    list= &list_par;
315
 
    el= &list_par.first;
316
 
    prev= 0;
317
 
    current= 0;
318
 
  }
319
 
 
320
 
  inline void *next(void)
321
 
  {
322
 
    prev=el;
323
 
    current= *el;
324
 
    el= &current->next;
325
 
    return current->info;
326
 
  }
327
 
  inline void *next_fast(void)
328
 
  {
329
 
    list_node *tmp;
330
 
    tmp= *el;
331
 
    el= &tmp->next;
332
 
    return tmp->info;
333
 
  }
334
 
  inline void rewind(void)
335
 
  {
336
 
    el= &list->first;
337
 
  }
338
 
  inline void *replace(void *element)
339
 
  {                                             // Return old element
340
 
    void *tmp=current->info;
341
 
    assert(current->info != 0);
342
 
    current->info=element;
343
 
    return tmp;
344
 
  }
 
289
  base_list_iterator(base_list &list_par, list_node** el0)
 
290
    :list(&list_par), el(el0), prev(0), current(0)
 
291
  {
 
292
  }
 
293
 
345
294
  void *replace(base_list &new_list)
346
295
  {
347
296
    void *ret_value=current->info;
350
299
      *new_list.last=current->next;
351
300
      current->info=new_list.first->info;
352
301
      current->next=new_list.first->next;
353
 
      if ((list->last == &current->next) && (new_list.elements > 1))
354
 
        list->last= new_list.last;
 
302
      if (list->last == &current->next && new_list.elements > 1)
 
303
        list->last= new_list.last;
355
304
      list->elements+=new_list.elements-1;
356
305
    }
357
306
    return ret_value;                           // return old element
358
307
  }
359
 
  inline void remove(void)                      // Remove current
 
308
  void remove()                 // Remove current
360
309
  {
361
310
    list->remove(prev);
362
311
    el=prev;
368
317
    current=current->next;
369
318
    el= &current->next;
370
319
  }
371
 
  inline void **ref(void)                       // Get reference pointer
372
 
  {
373
 
    return &current->info;
374
 
  }
375
 
  inline bool is_last(void)
376
 
  {
377
 
    return el == &list->last_ref()->next;
378
 
  }
379
 
  friend class error_list_iterator;
380
320
};
381
321
 
382
 
template <class T> class List :public base_list
 
322
template <class T> class List_iterator;
 
323
 
 
324
template <class T> class List : public base_list
383
325
{
384
326
public:
385
 
  inline List() :base_list() {}
386
 
  inline List(const List<T> &tmp) :base_list(tmp) {}
387
 
  inline List(const List<T> &tmp, memory::Root *mem_root) :
388
 
    base_list(tmp, mem_root) {}
389
 
  inline bool push_back(T *a) { return base_list::push_back(a); }
390
 
  inline bool push_back(T *a, memory::Root *mem_root)
391
 
  { return base_list::push_back(a, mem_root); }
392
 
  inline bool push_front(T *a) { return base_list::push_front(a); }
393
 
  inline T* head() {return (T*) base_list::head(); }
394
 
  inline T** head_ref() {return (T**) base_list::head_ref(); }
395
 
  inline T* pop()  {return (T*) base_list::pop(); }
396
 
  inline void concat(List<T> *list) { base_list::concat(list); }
397
 
  inline void disjoin(List<T> *list) { base_list::disjoin(list); }
398
 
  inline void prepand(List<T> *list) { base_list::prepand(list); }
399
 
  void delete_elements(void)
 
327
  typedef List_iterator<T> iterator;
 
328
 
 
329
  friend class List_iterator<T>;
 
330
 
 
331
  List() {}
 
332
  List(const List<T> &tmp) : base_list(tmp) {}
 
333
  List(const List<T> &tmp, memory::Root *mem_root) : base_list(tmp, mem_root) {}
 
334
  T& front() {return *static_cast<T*>(first->info); }
 
335
  T* pop()  {return static_cast<T*>(base_list::pop()); }
 
336
  void concat(List<T> *list) { base_list::concat(list); }
 
337
  void disjoin(List<T> *list) { base_list::disjoin(list); }
 
338
  void prepand(List<T> *list) { base_list::prepand(list); }
 
339
  void delete_elements()
400
340
  {
401
341
    list_node *element,*next;
402
342
    for (element=first; element != &end_of_list; element=next)
404
344
      next=element->next;
405
345
      delete (T*) element->info;
406
346
    }
407
 
    empty();
408
 
  }
409
 
};
410
 
 
411
 
 
412
 
template <class T> class List_iterator :public base_list_iterator
413
 
{
414
 
public:
415
 
  List_iterator(List<T> &a) : base_list_iterator(a) {}
416
 
  List_iterator() : base_list_iterator() {}
417
 
  inline void init(List<T> &a) { base_list_iterator::init(a); }
418
 
  inline T* operator++(int) { return (T*) base_list_iterator::next(); }
419
 
  inline T *replace(T *a)   { return (T*) base_list_iterator::replace(a); }
420
 
  inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
421
 
  inline void rewind(void)  { base_list_iterator::rewind(); }
422
 
  inline void remove()      { base_list_iterator::remove(); }
423
 
  inline void after(T *a)   { base_list_iterator::after(a); }
424
 
  inline T** ref(void)      { return (T**) base_list_iterator::ref(); }
425
 
};
426
 
 
427
 
 
428
 
template <class T> class List_iterator_fast :public base_list_iterator
429
 
{
430
 
protected:
431
 
  inline T *replace(T *)   { return (T*) 0; }
432
 
  inline T *replace(List<T> &) { return (T*) 0; }
433
 
  inline void remove(void)  { }
434
 
  inline void after(T *)   { }
435
 
  inline T** ref(void)      { return (T**) 0; }
436
 
 
437
 
public:
438
 
  inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
439
 
  inline List_iterator_fast() : base_list_iterator() {}
440
 
  inline void init(List<T> &a) { base_list_iterator::init(a); }
441
 
  inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
442
 
  inline void rewind(void)  { base_list_iterator::rewind(); }
443
 
  void sublist(List<T> &list_arg, uint32_t el_arg)
444
 
  {
445
 
    base_list_iterator::sublist(list_arg, el_arg);
446
 
  }
447
 
};
448
 
 
449
 
 
450
 
/**
451
 
  Make a deep copy of each list element.
452
 
 
453
 
  @note A template function and not a template method of class List
454
 
  is employed because of explicit template instantiation:
455
 
  in server code there are explicit instantiations of List<T> and
456
 
  an explicit instantiation of a template requires that any method
457
 
  of the instantiated class used in the template can be resolved.
458
 
  Evidently not all template arguments have clone() method with
459
 
  the right signature.
460
 
 
461
 
  @return You must query the error state in Session for out-of-memory
462
 
  situation after calling this function.
463
 
*/
464
 
 
465
 
template <typename T>
466
 
inline
467
 
void
468
 
list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
469
 
{
470
 
  /* Make a deep copy of each element */
471
 
  List_iterator<T> it(list);
472
 
  T *el;
473
 
  while ((el= it++))
474
 
    it.replace(el->clone(mem_root));
475
 
}
 
347
    clear();
 
348
  }
 
349
 
 
350
  iterator begin()
 
351
  {
 
352
    return iterator(*this, &first);
 
353
  }
 
354
 
 
355
  size_t size() const
 
356
  {
 
357
    return elements;
 
358
  }
 
359
 
 
360
  void set_size(size_t v)
 
361
  {
 
362
    elements = v;
 
363
  }
 
364
};
 
365
 
 
366
template <class T> class List_iterator : public base_list_iterator
 
367
{
 
368
public:
 
369
  List_iterator(List<T>& a, list_node** b) : base_list_iterator(a, b) {};
 
370
  List_iterator() {};
 
371
  T *operator++(int) { prev=el; current= *el; el= &current->next; return (T*)current->info; }
 
372
  T *replace(T *a)   { T* old = (T*) current->info; current->info= a; return old; }
 
373
  void replace(List<T> &a) { base_list_iterator::replace(a); }
 
374
  T** ref() { return (T**) &current->info; }
 
375
 
 
376
  T& operator*()
 
377
  {
 
378
    return *(T*)current->info;
 
379
  }
 
380
 
 
381
  T* operator->()
 
382
  {
 
383
    return (T*)current->info;
 
384
  }
 
385
};
476
386
 
477
387
} /* namespace drizzled */
478
388
 
479
 
#endif /* DRIZZLED_SQL_LIST_H */