~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_list.h

  • Committer: Olaf van der Spek
  • Date: 2011-03-06 15:49:49 UTC
  • mto: (2226.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 2227.
  • Revision ID: olafvdspek@gmail.com-20110306154949-zzso0l15mbwi60xb
Provide drizzle/drizzle.h

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#ifndef DRIZZLED_SQL_LIST_H
21
21
#define DRIZZLED_SQL_LIST_H
22
22
 
23
 
 
24
23
#include <cstdlib>
25
24
#include <cassert>
26
25
#include <utility>
27
26
#include <algorithm>
28
 
#include "drizzled/memory/sql_alloc.h"
29
 
 
30
 
namespace drizzled
 
27
#include <drizzled/memory/sql_alloc.h>
 
28
#include <drizzled/visibility.h>
 
29
 
 
30
namespace drizzled {
 
31
 
 
32
typedef struct st_sql_list 
31
33
{
32
 
 
33
 
/** Struct to handle simple linked lists. */
34
 
typedef struct st_sql_list {
35
34
  uint32_t elements;
36
35
  unsigned char *first;
37
36
  unsigned char **next;
38
37
 
39
 
  st_sql_list() {}                              /* Remove gcc warning */
40
 
  inline void empty()
 
38
  void clear()
41
39
  {
42
40
    elements=0;
43
41
    first=0;
44
42
    next= &first;
45
43
  }
46
 
  inline void link_in_list(unsigned char *element,unsigned char **next_ptr)
 
44
 
 
45
  size_t size() const
 
46
  {
 
47
    return elements;
 
48
  }
 
49
 
 
50
  void link_in_list(unsigned char *element,unsigned char **next_ptr)
47
51
  {
48
52
    elements++;
49
53
    (*next)=element;
50
54
    next= next_ptr;
51
55
    *next=0;
52
56
  }
53
 
  inline void save_and_clear(struct st_sql_list *save)
 
57
  void save_and_clear(struct st_sql_list *save)
54
58
  {
55
59
    *save= *this;
56
 
    empty();
 
60
    clear();
57
61
  }
58
 
  inline void push_front(struct st_sql_list *save)
 
62
  void push_front(struct st_sql_list *save)
59
63
  {
60
64
    *save->next= first;                         /* link current list last */
61
65
    first= save->first;
62
66
    elements+= save->elements;
63
67
  }
64
 
  inline void push_back(struct st_sql_list *save)
 
68
  void push_back(struct st_sql_list *save)
65
69
  {
66
70
    if (save->first)
67
71
    {
102
106
  }
103
107
};
104
108
 
105
 
 
106
 
extern list_node end_of_list;
 
109
extern DRIZZLED_API list_node end_of_list;
107
110
 
108
111
class base_list :public memory::SqlAlloc
109
112
{
110
113
protected:
111
114
  list_node *first,**last;
112
 
 
 
115
  uint32_t elements;
113
116
public:
114
 
  uint32_t elements;
115
117
 
116
 
  inline void empty() { elements=0; first= &end_of_list; last=&first;}
117
 
  inline base_list() { empty(); }
 
118
  void clear() { elements=0; first= &end_of_list; last=&first;}
 
119
  base_list() { clear(); }
118
120
  /**
119
121
    This is a shallow copy constructor that implicitly passes the ownership
120
122
    from the source list to the new instance. The old instance is not
124
126
    relies on this behaviour. This logic is quite tricky: please do not use
125
127
    it in any new code.
126
128
  */
127
 
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
 
129
  base_list(const base_list &tmp) :memory::SqlAlloc()
128
130
  {
129
131
    elements= tmp.elements;
130
132
    first= tmp.first;
131
133
    last= elements ? tmp.last : &first;
132
134
  }
133
 
  inline base_list(bool) { }
134
 
  inline bool push_back(void *info)
 
135
  base_list(bool) { }
 
136
  bool push_back(void *info)
135
137
  {
136
138
    if (((*last)=new list_node(info, &end_of_list)))
137
139
    {
141
143
    }
142
144
    return 1;
143
145
  }
144
 
  inline bool push_back(void *info, memory::Root *mem_root)
 
146
  bool push_back(void *info, memory::Root *mem_root)
145
147
  {
146
148
    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
147
149
    {
151
153
    }
152
154
    return 1;
153
155
  }
154
 
  inline bool push_front(void *info)
 
156
  bool push_front(void *info)
155
157
  {
156
158
    list_node *node=new list_node(info,first);
157
159
    if (node)
174
176
    delete *prev;
175
177
    *prev=node;
176
178
  }
177
 
  inline void concat(base_list *list)
 
179
  void concat(base_list *list)
178
180
  {
179
181
    if (!list->is_empty())
180
182
    {
183
185
      elements+= list->elements;
184
186
    }
185
187
  }
186
 
  inline void *pop(void)
 
188
  void *pop()
187
189
  {
188
190
    if (first == &end_of_list) return 0;
189
191
    list_node *tmp=first;
192
194
      last= &first;
193
195
    return tmp->info;
194
196
  }
195
 
  inline void disjoin(base_list *list)
 
197
  void disjoin(base_list *list)
196
198
  {
197
199
    list_node **prev= &first;
198
200
    list_node *node= first;
207
209
    *prev= *last;
208
210
    last= prev;
209
211
  }
210
 
  inline void prepand(base_list *list)
 
212
  void prepand(base_list *list)
211
213
  {
212
214
    if (!list->is_empty())
213
215
    {
219
221
  /**
220
222
    Swap two lists.
221
223
  */
222
 
  inline void swap(base_list &rhs)
 
224
  void swap(base_list &rhs)
223
225
  {
224
226
    std::swap(first, rhs.first);
225
227
    std::swap(last, rhs.last);
226
228
    std::swap(elements, rhs.elements);
227
229
  }
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; }
 
230
  bool is_empty() { return first == &end_of_list ; }
234
231
  friend class base_list_iterator;
235
 
  friend class error_list;
236
 
  friend class error_list_iterator;
237
232
 
238
233
#ifdef LIST_EXTRA_DEBUG
239
234
  /*
295
290
protected:
296
291
  base_list *list;
297
292
  list_node **el,**prev,*current;
 
293
public:
298
294
  void sublist(base_list &ls, uint32_t elm)
299
295
  {
300
296
    ls.first= *el;
301
297
    ls.last= list->last;
302
298
    ls.elements= elm;
303
299
  }
304
 
public:
305
300
  base_list_iterator()
306
301
    :list(0), el(0), prev(0), current(0)
307
302
  {}
308
303
 
309
 
  base_list_iterator(base_list &list_par)
310
 
  { init(list_par); }
311
 
 
312
 
  inline void init(base_list &list_par)
 
304
  base_list_iterator(base_list &list_par, list_node** el0)
 
305
    :list(&list_par), el(el0), prev(0), current(0)
313
306
  {
314
 
    list= &list_par;
315
 
    el= &list_par.first;
316
 
    prev= 0;
317
 
    current= 0;
318
307
  }
319
308
 
320
 
  inline void *next(void)
 
309
  void *next()
321
310
  {
322
311
    prev=el;
323
312
    current= *el;
324
313
    el= &current->next;
325
314
    return current->info;
326
315
  }
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
 
  }
345
316
  void *replace(base_list &new_list)
346
317
  {
347
318
    void *ret_value=current->info;
350
321
      *new_list.last=current->next;
351
322
      current->info=new_list.first->info;
352
323
      current->next=new_list.first->next;
353
 
      if ((list->last == &current->next) && (new_list.elements > 1))
354
 
        list->last= new_list.last;
 
324
      if (list->last == &current->next && new_list.elements > 1)
 
325
        list->last= new_list.last;
355
326
      list->elements+=new_list.elements-1;
356
327
    }
357
328
    return ret_value;                           // return old element
358
329
  }
359
 
  inline void remove(void)                      // Remove current
 
330
  void remove()                 // Remove current
360
331
  {
361
332
    list->remove(prev);
362
333
    el=prev;
368
339
    current=current->next;
369
340
    el= &current->next;
370
341
  }
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
342
};
381
343
 
382
 
template <class T> class List :public base_list
 
344
template <class T> class List_iterator;
 
345
 
 
346
template <class T> class List : public base_list
383
347
{
384
348
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)
 
349
  typedef List_iterator<T> iterator;
 
350
 
 
351
  friend class List_iterator<T>;
 
352
 
 
353
  List() {}
 
354
  List(const List<T> &tmp) : base_list(tmp) {}
 
355
  List(const List<T> &tmp, memory::Root *mem_root) : base_list(tmp, mem_root) {}
 
356
  bool push_back(T *a) { return base_list::push_back(a); }
 
357
  bool push_back(T *a, memory::Root *mem_root) { return base_list::push_back(a, mem_root); }
 
358
  bool push_front(T *a) { return base_list::push_front(a); }
 
359
  T& front() {return *static_cast<T*>(first->info); }
 
360
  T* pop()  {return static_cast<T*>(base_list::pop()); }
 
361
  void concat(List<T> *list) { base_list::concat(list); }
 
362
  void disjoin(List<T> *list) { base_list::disjoin(list); }
 
363
  void prepand(List<T> *list) { base_list::prepand(list); }
 
364
  void delete_elements()
400
365
  {
401
366
    list_node *element,*next;
402
367
    for (element=first; element != &end_of_list; element=next)
404
369
      next=element->next;
405
370
      delete (T*) element->info;
406
371
    }
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
 
}
 
372
    clear();
 
373
  }
 
374
 
 
375
  iterator begin()
 
376
  {
 
377
    return iterator(*this, &first);
 
378
  }
 
379
 
 
380
  size_t size() const
 
381
  {
 
382
    return elements;
 
383
  }
 
384
 
 
385
  void set_size(size_t v)
 
386
  {
 
387
    elements = v;
 
388
  }
 
389
};
 
390
 
 
391
template <class T> class List_iterator : public base_list_iterator
 
392
{
 
393
public:
 
394
  List_iterator(List<T>& a, list_node** b) : base_list_iterator(a, b) {};
 
395
  List_iterator() {};
 
396
  T *operator++(int) { return (T*) base_list_iterator::next(); }
 
397
  T *replace(T *a)   { T* old = (T*) current->info; current->info= a; return old; }
 
398
  void replace(List<T> &a) { base_list_iterator::replace(a); }
 
399
  T** ref() { return (T**) &current->info; }
 
400
 
 
401
  T& operator*()
 
402
  {
 
403
    return *(T*)current->info;
 
404
  }
 
405
};
476
406
 
477
407
} /* namespace drizzled */
478
408